packages feed

accelerate 1.2.0.1 → 1.3.0.0

raw patch · 171 files changed

+23019/−23127 lines, 171 filesdep +prettyprinterdep +prettyprinter-ansi-terminaldep +primitivedep −ansi-wl-pprintdep −constraintsdep −th-lift-instancesdep ~basedep ~halfdep ~textbinary-addedPVP ok

version bump matches the API change (PVP)

Dependencies added: prettyprinter, prettyprinter-ansi-terminal, primitive

Dependencies removed: ansi-wl-pprint, constraints, th-lift-instances

Dependency ranges changed: base, half, text

API changes (from Hackage documentation)

- Data.Array.Accelerate: caseof :: (Elt a, Elt b) => Exp a -> [(Exp a -> Exp Bool, Exp b)] -> Exp b -> Exp b
- Data.Array.Accelerate: class IsBounded a
- Data.Array.Accelerate: class (Floating a, IsSingle a, IsNum a) => IsFloating a
- Data.Array.Accelerate: class (IsSingle a, IsNum a, IsBounded a) => IsIntegral a
- Data.Array.Accelerate: class IsNonNum a
- Data.Array.Accelerate: class (Num a, IsSingle a) => IsNum a
- Data.Array.Accelerate: class Typeable a => IsScalar a
- Data.Array.Accelerate: ignore :: Shape sh => Exp sh
- 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.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.Array.Sugar.Elt (Data.Complex.Complex a)) => Data.Array.Accelerate.Classes.Eq.Eq (Data.Complex.Complex 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.Array.Sugar.Elt (Data.Complex.Complex b)) => Data.Array.Accelerate.Classes.FromIntegral.FromIntegral a (Data.Complex.Complex b)
- Data.Array.Accelerate.Data.Complex: instance (Data.Array.Accelerate.Classes.RealFloat.RealFloat a, Data.Array.Accelerate.Array.Sugar.Elt (Data.Complex.Complex 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, Data.Array.Accelerate.Array.Sugar.Elt (Data.Complex.Complex 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, Data.Array.Accelerate.Array.Sugar.Elt (Data.Complex.Complex a)) => GHC.Real.Fractional (Data.Array.Accelerate.Smart.Exp (Data.Complex.Complex a))
- 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.Array.Sugar.Elt (Data.Complex.Complex (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 (Data.Complex.Complex Foreign.C.Types.CDouble)
- Data.Array.Accelerate.Data.Complex: instance Data.Array.Accelerate.Array.Sugar.Elt (Data.Complex.Complex Foreign.C.Types.CFloat)
- Data.Array.Accelerate.Data.Complex: instance Data.Array.Accelerate.Array.Sugar.Elt (Data.Complex.Complex GHC.Types.Double)
- Data.Array.Accelerate.Data.Complex: instance Data.Array.Accelerate.Array.Sugar.Elt (Data.Complex.Complex GHC.Types.Float)
- Data.Array.Accelerate.Data.Complex: instance Data.Array.Accelerate.Array.Sugar.Elt (Data.Complex.Complex Numeric.Half.Half)
- Data.Array.Accelerate.Data.Complex: instance cst a => Data.Array.Accelerate.Product.IsProduct cst (Data.Complex.Complex a)
- Data.Array.Accelerate.Data.Either: instance (Data.Array.Accelerate.Array.Sugar.Elt a, Data.Array.Accelerate.Array.Sugar.Elt b) => Data.Array.Accelerate.Array.Sugar.Elt (Data.Either.Either a b)
- Data.Array.Accelerate.Data.Either: instance (Data.Array.Accelerate.Array.Sugar.Elt a, Data.Array.Accelerate.Array.Sugar.Elt b) => Data.Array.Accelerate.Product.IsProduct Data.Array.Accelerate.Array.Sugar.Elt (Data.Either.Either a b)
- Data.Array.Accelerate.Data.Either: instance (Data.Array.Accelerate.Array.Sugar.Elt a, Data.Array.Accelerate.Array.Sugar.Elt b) => GHC.Base.Semigroup (Data.Array.Accelerate.Smart.Exp (Data.Either.Either a b))
- Data.Array.Accelerate.Data.Either: instance (Data.Array.Accelerate.Lift.Lift Data.Array.Accelerate.Smart.Exp a, Data.Array.Accelerate.Lift.Lift Data.Array.Accelerate.Smart.Exp b, Data.Array.Accelerate.Array.Sugar.Elt (Data.Array.Accelerate.Lift.Plain a), Data.Array.Accelerate.Array.Sugar.Elt (Data.Array.Accelerate.Lift.Plain b)) => Data.Array.Accelerate.Lift.Lift Data.Array.Accelerate.Smart.Exp (Data.Either.Either a b)
- Data.Array.Accelerate.Data.Either: instance Data.Array.Accelerate.Array.Sugar.Elt a => Data.Array.Accelerate.Data.Functor.Functor (Data.Either.Either a)
- Data.Array.Accelerate.Data.Either: left :: forall a b. (Elt a, Elt b) => Exp a -> Exp (Either a b)
- Data.Array.Accelerate.Data.Either: right :: forall a b. (Elt a, Elt b) => Exp b -> Exp (Either a b)
- Data.Array.Accelerate.Data.Maybe: 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 (GHC.Base.Maybe a)
- Data.Array.Accelerate.Data.Maybe: instance (GHC.Base.Monoid (Data.Array.Accelerate.Smart.Exp a), Data.Array.Accelerate.Array.Sugar.Elt a) => GHC.Base.Monoid (Data.Array.Accelerate.Smart.Exp (GHC.Base.Maybe a))
- Data.Array.Accelerate.Data.Maybe: instance (GHC.Base.Semigroup (Data.Array.Accelerate.Smart.Exp a), Data.Array.Accelerate.Array.Sugar.Elt a) => GHC.Base.Semigroup (Data.Array.Accelerate.Smart.Exp (GHC.Base.Maybe a))
- Data.Array.Accelerate.Data.Maybe: instance Data.Array.Accelerate.Array.Sugar.Elt a => Data.Array.Accelerate.Array.Sugar.Elt (GHC.Base.Maybe a)
- Data.Array.Accelerate.Data.Maybe: instance Data.Array.Accelerate.Array.Sugar.Elt a => Data.Array.Accelerate.Product.IsProduct Data.Array.Accelerate.Array.Sugar.Elt (GHC.Base.Maybe a)
- Data.Array.Accelerate.Data.Maybe: instance Data.Array.Accelerate.Classes.Eq.Eq a => Data.Array.Accelerate.Classes.Eq.Eq (GHC.Base.Maybe a)
- Data.Array.Accelerate.Data.Maybe: instance Data.Array.Accelerate.Classes.Ord.Ord a => Data.Array.Accelerate.Classes.Ord.Ord (GHC.Base.Maybe a)
- Data.Array.Accelerate.Data.Maybe: instance Data.Array.Accelerate.Data.Functor.Functor GHC.Base.Maybe
- Data.Array.Accelerate.Data.Maybe: just :: Elt a => Exp a -> Exp (Maybe a)
- Data.Array.Accelerate.Data.Maybe: nothing :: forall a. Elt a => Exp (Maybe a)
- 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.Semigroup.Internal.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.Semigroup.Internal.Sum a)
- Data.Array.Accelerate.Data.Monoid: instance Data.Array.Accelerate.Array.Sugar.Elt a => Data.Array.Accelerate.Array.Sugar.Elt (Data.Semigroup.Internal.Product a)
- Data.Array.Accelerate.Data.Monoid: instance Data.Array.Accelerate.Array.Sugar.Elt a => Data.Array.Accelerate.Array.Sugar.Elt (Data.Semigroup.Internal.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.Semigroup.Internal.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.Semigroup.Internal.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.Semigroup.Internal.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.Semigroup.Internal.Sum a)
- Data.Array.Accelerate.Data.Semigroup: 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.Semigroup (Data.Array.Accelerate.Smart.Exp a), GHC.Base.Semigroup (Data.Array.Accelerate.Smart.Exp b), GHC.Base.Semigroup (Data.Array.Accelerate.Smart.Exp c), GHC.Base.Semigroup (Data.Array.Accelerate.Smart.Exp d), GHC.Base.Semigroup (Data.Array.Accelerate.Smart.Exp e)) => GHC.Base.Semigroup (Data.Array.Accelerate.Smart.Exp (a, b, c, d, e))
- Data.Array.Accelerate.Data.Semigroup: 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.Semigroup (Data.Array.Accelerate.Smart.Exp a), GHC.Base.Semigroup (Data.Array.Accelerate.Smart.Exp b), GHC.Base.Semigroup (Data.Array.Accelerate.Smart.Exp c), GHC.Base.Semigroup (Data.Array.Accelerate.Smart.Exp d)) => GHC.Base.Semigroup (Data.Array.Accelerate.Smart.Exp (a, b, c, d))
- Data.Array.Accelerate.Data.Semigroup: instance (Data.Array.Accelerate.Array.Sugar.Elt a, Data.Array.Accelerate.Array.Sugar.Elt b, Data.Array.Accelerate.Array.Sugar.Elt c, GHC.Base.Semigroup (Data.Array.Accelerate.Smart.Exp a), GHC.Base.Semigroup (Data.Array.Accelerate.Smart.Exp b), GHC.Base.Semigroup (Data.Array.Accelerate.Smart.Exp c)) => GHC.Base.Semigroup (Data.Array.Accelerate.Smart.Exp (a, b, c))
- Data.Array.Accelerate.Data.Semigroup: instance (Data.Array.Accelerate.Array.Sugar.Elt a, Data.Array.Accelerate.Array.Sugar.Elt b, GHC.Base.Semigroup (Data.Array.Accelerate.Smart.Exp a), GHC.Base.Semigroup (Data.Array.Accelerate.Smart.Exp b)) => GHC.Base.Semigroup (Data.Array.Accelerate.Smart.Exp (a, b))
- Data.Array.Accelerate.Data.Semigroup: 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.Semigroup.Max a)
- Data.Array.Accelerate.Data.Semigroup: 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.Semigroup.Min a)
- Data.Array.Accelerate.Data.Semigroup: instance Data.Array.Accelerate.Array.Sugar.Elt a => Data.Array.Accelerate.Array.Sugar.Elt (Data.Semigroup.Max a)
- Data.Array.Accelerate.Data.Semigroup: instance Data.Array.Accelerate.Array.Sugar.Elt a => Data.Array.Accelerate.Array.Sugar.Elt (Data.Semigroup.Min a)
- Data.Array.Accelerate.Data.Semigroup: instance Data.Array.Accelerate.Array.Sugar.Elt a => Data.Array.Accelerate.Lift.Unlift Data.Array.Accelerate.Smart.Exp (Data.Semigroup.Max (Data.Array.Accelerate.Smart.Exp a))
- Data.Array.Accelerate.Data.Semigroup: instance Data.Array.Accelerate.Array.Sugar.Elt a => Data.Array.Accelerate.Lift.Unlift Data.Array.Accelerate.Smart.Exp (Data.Semigroup.Min (Data.Array.Accelerate.Smart.Exp a))
- Data.Array.Accelerate.Data.Semigroup: instance Data.Array.Accelerate.Array.Sugar.Elt a => Data.Array.Accelerate.Product.IsProduct Data.Array.Accelerate.Array.Sugar.Elt (Data.Semigroup.Max a)
- Data.Array.Accelerate.Data.Semigroup: instance Data.Array.Accelerate.Array.Sugar.Elt a => Data.Array.Accelerate.Product.IsProduct Data.Array.Accelerate.Array.Sugar.Elt (Data.Semigroup.Min a)
+ Data.Array.Accelerate: (&) :: a -> (a -> b) -> b
+ Data.Array.Accelerate: --
+ Data.Array.Accelerate: -- </pre>
+ Data.Array.Accelerate: -- <pre>
+ Data.Array.Accelerate: -- <tt>e</tt>.
+ Data.Array.Accelerate: -- For example, the tuple types <tt>(Exp Int, Int)</tt> and <tt>(Int, Exp
+ Data.Array.Accelerate: -- Int)</tt> have the same "Plain" representation. That is, the following
+ Data.Array.Accelerate: -- Plain (Exp Int, Int) ~ (Int,Int) ~ Plain (Int, Exp Int)
+ Data.Array.Accelerate: -- instances of surface type constructors <tt>c</tt> from the input type
+ Data.Array.Accelerate: -- type equality holds:
+ Data.Array.Accelerate: -- | An associated-type (i.e. a type-level function) that strips all
+ Data.Array.Accelerate: Just :: a -> Maybe a
+ Data.Array.Accelerate: Nothing :: Maybe a
+ Data.Array.Accelerate: class Generic a
+ Data.Array.Accelerate: class (Num a, Ord a) => Rational a
+ Data.Array.Accelerate: class Show a
+ Data.Array.Accelerate: compact :: forall sh e. (Shape sh, Elt e) => Acc (Array (sh :. Int) Bool) -> Acc (Array (sh :. Int) e) -> Acc (Vector e, Array sh Int)
+ Data.Array.Accelerate: data Maybe a
+ Data.Array.Accelerate: data Vec (n :: Nat) a
+ Data.Array.Accelerate: expand :: (Elt a, Elt b) => (Exp a -> Exp Int) -> (Exp a -> Exp Int -> Exp b) -> Acc (Vector a) -> Acc (Vector b)
+ Data.Array.Accelerate: fold1Seg' :: forall sh a i. (Shape sh, Elt a, Elt i, IsIntegral i, i ~ EltR i) => (Exp a -> Exp a -> Exp a) -> Acc (Array (sh :. Int) a) -> Acc (Segments i) -> Acc (Array (sh :. Int) a)
+ Data.Array.Accelerate: foldSeg' :: forall sh a i. (Shape sh, Elt a, Elt i, IsIntegral i, i ~ EltR 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: infix 4 <
+ Data.Array.Accelerate: infixl 3 ::.
+ Data.Array.Accelerate: match :: Matching f => f -> f
+ Data.Array.Accelerate: mkPattern :: Name -> DecsQ
+ Data.Array.Accelerate: mkPatterns :: [Name] -> DecsQ
+ Data.Array.Accelerate: otherwise :: Bool
+ Data.Array.Accelerate: pattern Just_ :: forall a_11. (HasCallStack, Elt a_11) => Exp a_11 -> Exp (Maybe a_11)
+ Data.Array.Accelerate: pattern Z_ :: Exp DIM0
+ Data.Array.Accelerate: pattern Vec16 :: Prim a => a -> a -> a -> a -> a -> a -> a -> a -> a -> a -> a -> a -> a -> a -> a -> a -> Vec16 a
+ Data.Array.Accelerate: pattern Pattern :: forall b a context. IsPattern context a b => b -> context a
+ Data.Array.Accelerate: pattern V16 :: IsVector con vec (con x0, con x1, con x2, con x3, con x4, con x5, con x6, con x7, con x8, con x9, con x10, con x11, con x12, con x13, con x14, con x15) => con x0 -> con x1 -> con x2 -> con x3 -> con x4 -> con x5 -> con x6 -> con x7 -> con x8 -> con x9 -> con x10 -> con x11 -> con x12 -> con x13 -> con x14 -> con x15 -> con vec
+ Data.Array.Accelerate: toRational :: (Rational a, FromIntegral Int64 b, Integral b) => Exp a -> Exp (Ratio b)
+ Data.Array.Accelerate: type HasCallStack = ?callStack :: CallStack
+ Data.Array.Accelerate: type VecElt a = (Elt a, Prim a, IsSingle a, EltR a ~ a)
+ Data.Array.Accelerate.Data.Bits: infixl 5 .|.
+ Data.Array.Accelerate.Data.Bits: infixl 6 `xor`
+ Data.Array.Accelerate.Data.Bits: infixl 7 .&.
+ Data.Array.Accelerate.Data.Bits: infixl 8 `rotateR`
+ Data.Array.Accelerate.Data.Bits: instance Data.Array.Accelerate.Data.Bits.Bits Foreign.C.Types.CChar
+ Data.Array.Accelerate.Data.Bits: instance Data.Array.Accelerate.Data.Bits.Bits Foreign.C.Types.CSChar
+ Data.Array.Accelerate.Data.Bits: instance Data.Array.Accelerate.Data.Bits.Bits Foreign.C.Types.CUChar
+ Data.Array.Accelerate.Data.Bits: instance Data.Array.Accelerate.Data.Bits.FiniteBits Foreign.C.Types.CChar
+ Data.Array.Accelerate.Data.Bits: instance Data.Array.Accelerate.Data.Bits.FiniteBits Foreign.C.Types.CSChar
+ Data.Array.Accelerate.Data.Bits: instance Data.Array.Accelerate.Data.Bits.FiniteBits Foreign.C.Types.CUChar
+ Data.Array.Accelerate.Data.Complex: infix 6 ::+
+ Data.Array.Accelerate.Data.Complex: instance (Data.Array.Accelerate.Classes.FromIntegral.FromIntegral a b, Data.Array.Accelerate.Classes.Num.Num b, Data.Array.Accelerate.Sugar.Elt.Elt (Data.Complex.Complex 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.Sugar.Elt.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.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 Data.Array.Accelerate.Sugar.Elt.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.Sugar.Elt.Elt a => Data.Array.Accelerate.Sugar.Elt.Elt (Data.Complex.Complex a)
+ Data.Array.Accelerate.Data.Complex: magnitude' :: RealFloat a => Exp (Complex a) -> Exp a
+ Data.Array.Accelerate.Data.Complex: pattern (::+) :: Elt a => Exp a -> Exp a -> Exp (Complex a)
+ Data.Array.Accelerate.Data.Either: instance (Data.Array.Accelerate.Lift.Lift Data.Array.Accelerate.Smart.Exp a, Data.Array.Accelerate.Lift.Lift Data.Array.Accelerate.Smart.Exp b, Data.Array.Accelerate.Sugar.Elt.Elt (Data.Array.Accelerate.Lift.Plain a), Data.Array.Accelerate.Sugar.Elt.Elt (Data.Array.Accelerate.Lift.Plain b)) => Data.Array.Accelerate.Lift.Lift Data.Array.Accelerate.Smart.Exp (Data.Either.Either a b)
+ Data.Array.Accelerate.Data.Either: instance (Data.Array.Accelerate.Sugar.Elt.Elt a, Data.Array.Accelerate.Sugar.Elt.Elt b) => GHC.Base.Semigroup (Data.Array.Accelerate.Smart.Exp (Data.Either.Either a b))
+ Data.Array.Accelerate.Data.Either: instance Data.Array.Accelerate.Sugar.Elt.Elt a => Data.Array.Accelerate.Data.Functor.Functor (Data.Either.Either a)
+ Data.Array.Accelerate.Data.Either: pattern Right_ :: forall a_ac3a b_ac3b. (HasCallStack, Elt a_ac3a, Elt b_ac3b) => Exp b_ac3b -> Exp (Either a_ac3a b_ac3b)
+ Data.Array.Accelerate.Data.Maybe: instance (Data.Array.Accelerate.Lift.Lift Data.Array.Accelerate.Smart.Exp a, Data.Array.Accelerate.Sugar.Elt.Elt (Data.Array.Accelerate.Lift.Plain a)) => Data.Array.Accelerate.Lift.Lift Data.Array.Accelerate.Smart.Exp (GHC.Maybe.Maybe a)
+ Data.Array.Accelerate.Data.Maybe: instance (GHC.Base.Monoid (Data.Array.Accelerate.Smart.Exp a), Data.Array.Accelerate.Sugar.Elt.Elt a) => GHC.Base.Monoid (Data.Array.Accelerate.Smart.Exp (GHC.Maybe.Maybe a))
+ Data.Array.Accelerate.Data.Maybe: instance (GHC.Base.Semigroup (Data.Array.Accelerate.Smart.Exp a), Data.Array.Accelerate.Sugar.Elt.Elt a) => GHC.Base.Semigroup (Data.Array.Accelerate.Smart.Exp (GHC.Maybe.Maybe a))
+ Data.Array.Accelerate.Data.Maybe: instance Data.Array.Accelerate.Classes.Eq.Eq a => Data.Array.Accelerate.Classes.Eq.Eq (GHC.Maybe.Maybe a)
+ Data.Array.Accelerate.Data.Maybe: instance Data.Array.Accelerate.Classes.Ord.Ord a => Data.Array.Accelerate.Classes.Ord.Ord (GHC.Maybe.Maybe a)
+ Data.Array.Accelerate.Data.Maybe: instance Data.Array.Accelerate.Data.Functor.Functor GHC.Maybe.Maybe
+ Data.Array.Accelerate.Data.Maybe: pattern Just_ :: forall a_11. (HasCallStack, Elt a_11) => Exp a_11 -> Exp (Maybe a_11)
+ Data.Array.Accelerate.Data.Monoid: instance (Data.Array.Accelerate.Lift.Lift Data.Array.Accelerate.Smart.Exp a, Data.Array.Accelerate.Sugar.Elt.Elt (Data.Array.Accelerate.Lift.Plain a)) => Data.Array.Accelerate.Lift.Lift Data.Array.Accelerate.Smart.Exp (Data.Semigroup.Internal.Product a)
+ Data.Array.Accelerate.Data.Monoid: instance (Data.Array.Accelerate.Lift.Lift Data.Array.Accelerate.Smart.Exp a, Data.Array.Accelerate.Sugar.Elt.Elt (Data.Array.Accelerate.Lift.Plain a)) => Data.Array.Accelerate.Lift.Lift Data.Array.Accelerate.Smart.Exp (Data.Semigroup.Internal.Sum a)
+ Data.Array.Accelerate.Data.Monoid: instance (Data.Array.Accelerate.Sugar.Elt.Elt a, Data.Array.Accelerate.Sugar.Elt.Elt b, Data.Array.Accelerate.Sugar.Elt.Elt c, Data.Array.Accelerate.Sugar.Elt.Elt d, Data.Array.Accelerate.Sugar.Elt.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.Sugar.Elt.Elt a, Data.Array.Accelerate.Sugar.Elt.Elt b, Data.Array.Accelerate.Sugar.Elt.Elt c, Data.Array.Accelerate.Sugar.Elt.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.Sugar.Elt.Elt a, Data.Array.Accelerate.Sugar.Elt.Elt b, Data.Array.Accelerate.Sugar.Elt.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.Sugar.Elt.Elt a, Data.Array.Accelerate.Sugar.Elt.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.Sugar.Elt.Elt a => Data.Array.Accelerate.Lift.Unlift Data.Array.Accelerate.Smart.Exp (Data.Semigroup.Internal.Product (Data.Array.Accelerate.Smart.Exp a))
+ Data.Array.Accelerate.Data.Monoid: instance Data.Array.Accelerate.Sugar.Elt.Elt a => Data.Array.Accelerate.Lift.Unlift Data.Array.Accelerate.Smart.Exp (Data.Semigroup.Internal.Sum (Data.Array.Accelerate.Smart.Exp a))
+ Data.Array.Accelerate.Data.Monoid: instance Data.Array.Accelerate.Sugar.Elt.Elt a => Data.Array.Accelerate.Sugar.Elt.Elt (Data.Semigroup.Internal.Product a)
+ Data.Array.Accelerate.Data.Monoid: instance Data.Array.Accelerate.Sugar.Elt.Elt a => Data.Array.Accelerate.Sugar.Elt.Elt (Data.Semigroup.Internal.Sum a)
+ Data.Array.Accelerate.Data.Monoid: pattern Product_ :: Elt a => Exp a -> Exp (Product a)
+ Data.Array.Accelerate.Data.Ratio: (%) :: Integral a => Exp a -> Exp a -> Exp (Ratio a)
+ Data.Array.Accelerate.Data.Ratio: data Ratio a
+ Data.Array.Accelerate.Data.Ratio: denominator :: Exp (Ratio a) -> Elt a => Exp a
+ Data.Array.Accelerate.Data.Ratio: infixl 7 %
+ Data.Array.Accelerate.Data.Ratio: instance (Data.Array.Accelerate.Classes.FromIntegral.FromIntegral a b, Data.Array.Accelerate.Classes.Integral.Integral b) => Data.Array.Accelerate.Classes.FromIntegral.FromIntegral a (GHC.Real.Ratio b)
+ Data.Array.Accelerate.Data.Ratio: instance (Data.Array.Accelerate.Classes.Integral.Integral a, Data.Array.Accelerate.Classes.FromIntegral.FromIntegral a GHC.Int.Int64) => Data.Array.Accelerate.Classes.RealFrac.RealFrac (GHC.Real.Ratio a)
+ Data.Array.Accelerate.Data.Ratio: instance (Data.Array.Accelerate.Classes.Integral.Integral a, Data.Array.Accelerate.Classes.ToFloating.ToFloating a b) => Data.Array.Accelerate.Classes.ToFloating.ToFloating (GHC.Real.Ratio a) b
+ Data.Array.Accelerate.Data.Ratio: instance Data.Array.Accelerate.Classes.Integral.Integral a => Data.Array.Accelerate.Classes.Eq.Eq (GHC.Real.Ratio a)
+ Data.Array.Accelerate.Data.Ratio: instance Data.Array.Accelerate.Classes.Integral.Integral a => Data.Array.Accelerate.Classes.Ord.Ord (GHC.Real.Ratio a)
+ Data.Array.Accelerate.Data.Ratio: instance Data.Array.Accelerate.Classes.Integral.Integral a => GHC.Enum.Enum (Data.Array.Accelerate.Smart.Exp (GHC.Real.Ratio a))
+ Data.Array.Accelerate.Data.Ratio: instance Data.Array.Accelerate.Classes.Integral.Integral a => GHC.Num.Num (Data.Array.Accelerate.Smart.Exp (GHC.Real.Ratio a))
+ Data.Array.Accelerate.Data.Ratio: instance Data.Array.Accelerate.Classes.Integral.Integral a => GHC.Real.Fractional (Data.Array.Accelerate.Smart.Exp (GHC.Real.Ratio a))
+ Data.Array.Accelerate.Data.Ratio: instance Data.Array.Accelerate.Sugar.Elt.Elt a => Data.Array.Accelerate.Sugar.Elt.Elt (GHC.Real.Ratio a)
+ Data.Array.Accelerate.Data.Ratio: numerator :: Exp (Ratio a) -> Elt a => Exp a
+ Data.Array.Accelerate.Data.Ratio: pattern (:%) :: Elt a => Exp a -> Exp a -> Exp (Ratio a)
+ Data.Array.Accelerate.Data.Semigroup: infixr 6 <>
+ Data.Array.Accelerate.Data.Semigroup: instance (Data.Array.Accelerate.Lift.Lift Data.Array.Accelerate.Smart.Exp a, Data.Array.Accelerate.Sugar.Elt.Elt (Data.Array.Accelerate.Lift.Plain a)) => Data.Array.Accelerate.Lift.Lift Data.Array.Accelerate.Smart.Exp (Data.Semigroup.Max a)
+ Data.Array.Accelerate.Data.Semigroup: instance (Data.Array.Accelerate.Lift.Lift Data.Array.Accelerate.Smart.Exp a, Data.Array.Accelerate.Sugar.Elt.Elt (Data.Array.Accelerate.Lift.Plain a)) => Data.Array.Accelerate.Lift.Lift Data.Array.Accelerate.Smart.Exp (Data.Semigroup.Min a)
+ Data.Array.Accelerate.Data.Semigroup: instance (Data.Array.Accelerate.Sugar.Elt.Elt a, Data.Array.Accelerate.Sugar.Elt.Elt b, Data.Array.Accelerate.Sugar.Elt.Elt c, Data.Array.Accelerate.Sugar.Elt.Elt d, Data.Array.Accelerate.Sugar.Elt.Elt e, GHC.Base.Semigroup (Data.Array.Accelerate.Smart.Exp a), GHC.Base.Semigroup (Data.Array.Accelerate.Smart.Exp b), GHC.Base.Semigroup (Data.Array.Accelerate.Smart.Exp c), GHC.Base.Semigroup (Data.Array.Accelerate.Smart.Exp d), GHC.Base.Semigroup (Data.Array.Accelerate.Smart.Exp e)) => GHC.Base.Semigroup (Data.Array.Accelerate.Smart.Exp (a, b, c, d, e))
+ Data.Array.Accelerate.Data.Semigroup: instance (Data.Array.Accelerate.Sugar.Elt.Elt a, Data.Array.Accelerate.Sugar.Elt.Elt b, Data.Array.Accelerate.Sugar.Elt.Elt c, Data.Array.Accelerate.Sugar.Elt.Elt d, GHC.Base.Semigroup (Data.Array.Accelerate.Smart.Exp a), GHC.Base.Semigroup (Data.Array.Accelerate.Smart.Exp b), GHC.Base.Semigroup (Data.Array.Accelerate.Smart.Exp c), GHC.Base.Semigroup (Data.Array.Accelerate.Smart.Exp d)) => GHC.Base.Semigroup (Data.Array.Accelerate.Smart.Exp (a, b, c, d))
+ Data.Array.Accelerate.Data.Semigroup: instance (Data.Array.Accelerate.Sugar.Elt.Elt a, Data.Array.Accelerate.Sugar.Elt.Elt b, Data.Array.Accelerate.Sugar.Elt.Elt c, GHC.Base.Semigroup (Data.Array.Accelerate.Smart.Exp a), GHC.Base.Semigroup (Data.Array.Accelerate.Smart.Exp b), GHC.Base.Semigroup (Data.Array.Accelerate.Smart.Exp c)) => GHC.Base.Semigroup (Data.Array.Accelerate.Smart.Exp (a, b, c))
+ Data.Array.Accelerate.Data.Semigroup: instance (Data.Array.Accelerate.Sugar.Elt.Elt a, Data.Array.Accelerate.Sugar.Elt.Elt b, GHC.Base.Semigroup (Data.Array.Accelerate.Smart.Exp a), GHC.Base.Semigroup (Data.Array.Accelerate.Smart.Exp b)) => GHC.Base.Semigroup (Data.Array.Accelerate.Smart.Exp (a, b))
+ Data.Array.Accelerate.Data.Semigroup: instance Data.Array.Accelerate.Sugar.Elt.Elt a => Data.Array.Accelerate.Lift.Unlift Data.Array.Accelerate.Smart.Exp (Data.Semigroup.Max (Data.Array.Accelerate.Smart.Exp a))
+ Data.Array.Accelerate.Data.Semigroup: instance Data.Array.Accelerate.Sugar.Elt.Elt a => Data.Array.Accelerate.Lift.Unlift Data.Array.Accelerate.Smart.Exp (Data.Semigroup.Min (Data.Array.Accelerate.Smart.Exp a))
+ Data.Array.Accelerate.Data.Semigroup: instance Data.Array.Accelerate.Sugar.Elt.Elt a => Data.Array.Accelerate.Sugar.Elt.Elt (Data.Semigroup.Max a)
+ Data.Array.Accelerate.Data.Semigroup: instance Data.Array.Accelerate.Sugar.Elt.Elt a => Data.Array.Accelerate.Sugar.Elt.Elt (Data.Semigroup.Min a)
+ Data.Array.Accelerate.Data.Semigroup: pattern Max_ :: Elt a => Exp a -> Exp (Max a)
+ Data.Array.Accelerate.Unsafe: class Coerce a b
- Data.Array.Accelerate: (!!) :: (Shape sh, Elt e) => Acc (Array sh e) -> Exp Int -> Exp e
+ Data.Array.Accelerate: (!!) :: forall sh e. (Shape sh, Elt e) => Acc (Array sh e) -> Exp Int -> Exp e
- Data.Array.Accelerate: (!) :: (Shape sh, Elt e) => Acc (Array sh e) -> Exp sh -> Exp e
+ Data.Array.Accelerate: (!) :: forall sh e. (Shape sh, Elt e) => Acc (Array sh e) -> Exp sh -> Exp e
- Data.Array.Accelerate: ($) :: () => a -> b -> a -> b
+ Data.Array.Accelerate: ($) :: forall (r :: RuntimeRep) a (b :: TYPE r). (a -> b) -> a -> b
- 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: (++) :: (Shape sh, Elt e) => Acc (Array (sh :. Int) e) -> Acc (Array (sh :. Int) e) -> Acc (Array (sh :. Int) e)
- Data.Array.Accelerate: (.) :: () => b -> c -> a -> b -> a -> c
+ Data.Array.Accelerate: (.) :: (b -> c) -> (a -> b) -> a -> c
- Data.Array.Accelerate: (:.) :: tail -> head -> (:.) tail head
+ Data.Array.Accelerate: (:.) :: !tail -> !head -> (:.) tail head
- Data.Array.Accelerate: (>->) :: (Arrays a, Arrays b, Arrays c) => (Acc a -> Acc b) -> (Acc b -> Acc c) -> (Acc a -> Acc c)
+ Data.Array.Accelerate: (>->) :: forall a b c. (Arrays a, Arrays b, Arrays c) => (Acc a -> Acc b) -> (Acc b -> Acc c) -> Acc a -> Acc c
- Data.Array.Accelerate: afst :: forall a b. (Arrays a, Arrays b) => Acc (a, b) -> Acc a
+ Data.Array.Accelerate: afst :: (Arrays a, Arrays b) => Acc (a, b) -> Acc a
- Data.Array.Accelerate: arrayRank :: Shape sh => sh -> Int
+ Data.Array.Accelerate: arrayRank :: forall sh e. Shape sh => Array sh e -> Int
- Data.Array.Accelerate: arrayReshape :: (Shape sh, Shape sh', Elt e) => sh -> Array sh' e -> Array sh e
+ Data.Array.Accelerate: arrayReshape :: (Shape sh, Shape sh') => sh -> Array sh' e -> Array sh e
- Data.Array.Accelerate: arraySize :: Shape sh => sh -> Int
+ Data.Array.Accelerate: arraySize :: Shape sh => Array sh e -> Int
- Data.Array.Accelerate: asnd :: forall a b. (Arrays a, Arrays b) => Acc (a, b) -> Acc b
+ Data.Array.Accelerate: asnd :: (Arrays a, Arrays b) => Acc (a, b) -> Acc b
- Data.Array.Accelerate: awhile :: Arrays a => (Acc a -> Acc (Scalar Bool)) -> (Acc a -> Acc a) -> Acc a -> Acc a
+ Data.Array.Accelerate: awhile :: forall a. Arrays a => (Acc a -> Acc (Scalar Bool)) -> (Acc a -> Acc a) -> Acc a -> Acc 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: backpermute :: forall sh sh' a. (Shape sh, Shape sh', Elt a) => Exp sh' -> (Exp sh' -> Exp sh) -> Acc (Array sh a) -> Acc (Array sh' a)
- Data.Array.Accelerate: bitcast :: (Elt a, Elt b, IsScalar (EltRepr a), IsScalar (EltRepr b), BitSizeEq (EltRepr a) (EltRepr b)) => Exp a -> Exp b
+ Data.Array.Accelerate: bitcast :: (Elt a, Elt b, IsScalar (EltR a), IsScalar (EltR b), BitSizeEq (EltR a) (EltR b)) => Exp a -> Exp b
- Data.Array.Accelerate: ceiling :: (RealFrac a, Elt b, IsIntegral b) => Exp a -> Exp b
+ Data.Array.Accelerate: ceiling :: (RealFrac a, Integral b, FromIntegral Int64 b) => Exp a -> Exp b
- Data.Array.Accelerate: class (Typeable a, Typeable (ArrRepr a)) => Arrays a
+ Data.Array.Accelerate: class Arrays a
- Data.Array.Accelerate: class (Show a, Typeable a, Typeable (EltRepr a), ArrayElt (EltRepr a)) => Elt a
+ Data.Array.Accelerate: class Elt a
- Data.Array.Accelerate: class (Real a, Fractional a) => RealFrac a
+ Data.Array.Accelerate: class (Ord a, Fractional a) => RealFrac a
- Data.Array.Accelerate: class (Elt sh, Elt (Any sh), Shape (EltRepr sh), FullShape sh ~ sh, CoSliceShape sh ~ sh, SliceShape sh ~ Z) => Shape sh
+ Data.Array.Accelerate: class (Elt sh, Elt (Any sh), FullShape sh ~ sh, CoSliceShape sh ~ sh, SliceShape sh ~ Z) => Shape sh
- Data.Array.Accelerate: class (Elt (StencilRepr sh stencil), Stencil sh a (StencilRepr sh stencil)) => Stencil sh a stencil
+ Data.Array.Accelerate: class Stencil sh e stencil
- Data.Array.Accelerate: const :: () => a -> b -> a
+ Data.Array.Accelerate: const :: a -> b -> a
- Data.Array.Accelerate: constant :: Elt t => t -> Exp t
+ Data.Array.Accelerate: constant :: forall e. (HasCallStack, Elt e) => e -> Exp e
- Data.Array.Accelerate: data tail (:.) head
+ Data.Array.Accelerate: data tail :. head
- Data.Array.Accelerate: div' :: (RealFrac a, Elt b, IsIntegral b) => Exp a -> Exp a -> Exp b
+ Data.Array.Accelerate: div' :: (RealFrac a, FromIntegral Int64 b, Integral b) => Exp a -> Exp a -> Exp b
- 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: divMod' :: (Floating a, RealFrac a, Integral b, FromIntegral Int64 b, ToFloating b a) => Exp a -> Exp a -> (Exp b, Exp a)
- 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: drop :: (Shape sh, Elt e) => Exp Int -> Acc (Array (sh :. Int) e) -> Acc (Array (sh :. Int) e)
- Data.Array.Accelerate: error :: HasCallStack => [Char] -> a
+ Data.Array.Accelerate: error :: forall (r :: RuntimeRep) (a :: TYPE r). HasCallStack => [Char] -> 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: filter :: (Shape sh, Elt e) => (Exp e -> Exp Bool) -> Acc (Array (sh :. Int) e) -> Acc (Vector e, Array sh Int)
- Data.Array.Accelerate: floor :: (RealFrac a, Elt b, IsIntegral b) => Exp a -> Exp b
+ Data.Array.Accelerate: floor :: (RealFrac a, Integral b, FromIntegral Int64 b) => Exp a -> Exp b
- 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: fold :: forall sh a. (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 sh, Elt a) => (Exp a -> Exp a -> Exp a) -> Acc (Array (sh :. Int) a) -> Acc (Array sh a)
+ Data.Array.Accelerate: fold1 :: forall sh a. (Shape sh, Elt a) => (Exp a -> Exp a -> Exp a) -> Acc (Array (sh :. Int) a) -> Acc (Array sh 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: fold1Seg :: forall sh e i. (Shape sh, Elt e, Elt i, i ~ EltR i, IsIntegral i) => (Exp e -> Exp e -> Exp e) -> Acc (Array (sh :. Int) e) -> Acc (Segments i) -> Acc (Array (sh :. Int) e)
- 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: foldSeg :: forall sh e i. (Shape sh, Elt e, Elt i, i ~ EltR i, IsIntegral i) => (Exp e -> Exp e -> Exp e) -> Exp e -> Acc (Array (sh :. Int) e) -> Acc (Segments i) -> Acc (Array (sh :. Int) e)
- Data.Array.Accelerate: foreignAcc :: (Arrays as, Arrays bs, Foreign asm) => asm (as -> bs) -> (Acc as -> Acc bs) -> Acc as -> Acc bs
+ Data.Array.Accelerate: foreignAcc :: forall as bs asm. (Arrays as, Arrays bs, Foreign asm) => asm (ArraysR as -> ArraysR bs) -> (Acc as -> Acc bs) -> Acc as -> Acc bs
- Data.Array.Accelerate: foreignExp :: (Elt x, Elt y, Foreign asm) => asm (x -> y) -> (Exp x -> Exp y) -> Exp x -> Exp y
+ Data.Array.Accelerate: foreignExp :: forall x y asm. (Elt x, Elt y, Foreign asm) => asm (EltR x -> EltR y) -> (Exp x -> Exp y) -> Exp x -> Exp y
- Data.Array.Accelerate: fromFunctionM :: (Shape sh, Elt e) => sh -> (sh -> IO e) -> IO (Array sh e)
+ Data.Array.Accelerate: fromFunctionM :: forall sh e. (Shape sh, Elt e) => sh -> (sh -> IO e) -> IO (Array sh e)
- Data.Array.Accelerate: fromIndex :: Shape sh => Exp sh -> Exp Int -> Exp sh
+ Data.Array.Accelerate: fromIndex :: forall sh. Shape sh => Exp sh -> Exp Int -> Exp sh
- Data.Array.Accelerate: fromInteger :: Num a => Integer -> Exp a
+ Data.Array.Accelerate: fromInteger :: Num a => Integer -> a
- Data.Array.Accelerate: fromList :: (Shape sh, Elt e) => sh -> [e] -> Array sh e
+ Data.Array.Accelerate: fromList :: forall sh e. (Shape sh, Elt e) => sh -> [e] -> Array sh e
- Data.Array.Accelerate: fromRational :: Fractional a => Rational -> Exp a
+ Data.Array.Accelerate: fromRational :: Fractional a => Rational -> a
- Data.Array.Accelerate: fst :: forall a b. (Elt a, Elt b) => Exp (a, b) -> Exp a
+ Data.Array.Accelerate: fst :: (Elt a, Elt b) => Exp (a, b) -> Exp a
- Data.Array.Accelerate: function :: (Shape sh, Elt e) => (Exp sh -> Exp e) -> Boundary (Array sh e)
+ Data.Array.Accelerate: function :: forall sh e. (Shape sh, Elt e) => (Exp sh -> Exp e) -> Boundary (Array sh e)
- Data.Array.Accelerate: generate :: (Shape sh, Elt a) => Exp sh -> (Exp sh -> Exp a) -> Acc (Array sh a)
+ Data.Array.Accelerate: generate :: forall sh a. (Shape sh, Elt a) => Exp sh -> (Exp sh -> Exp a) -> Acc (Array sh a)
- Data.Array.Accelerate: index2 :: (Elt i, Slice (Z :. i)) => Exp i -> Exp i -> Exp (Z :. i :. i)
+ Data.Array.Accelerate: index2 :: Elt i => Exp i -> Exp i -> Exp ((Z :. i) :. i)
- 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: index3 :: Elt i => Exp i -> Exp i -> Exp i -> Exp (((Z :. i) :. i) :. i)
- Data.Array.Accelerate: indexArray :: Array sh e -> sh -> e
+ Data.Array.Accelerate: indexArray :: (Shape sh, Elt e) => Array sh e -> sh -> e
- Data.Array.Accelerate: indexHead :: (Slice sh, Elt a) => Exp (sh :. a) -> Exp a
+ Data.Array.Accelerate: indexHead :: (Elt sh, Elt a) => Exp (sh :. a) -> Exp a
- Data.Array.Accelerate: indexTail :: (Slice sh, Elt a) => Exp (sh :. a) -> Exp sh
+ Data.Array.Accelerate: indexTail :: (Elt sh, Elt a) => Exp (sh :. a) -> Exp sh
- Data.Array.Accelerate: infixl 1 >->
+ Data.Array.Accelerate: infixl 1 &
- 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: init :: (Shape sh, Elt e) => Acc (Array (sh :. Int) e) -> Acc (Array (sh :. Int) e)
- Data.Array.Accelerate: intersect :: Shape sh => Exp sh -> Exp sh -> Exp sh
+ Data.Array.Accelerate: intersect :: forall sh. Shape sh => Exp sh -> Exp sh -> Exp sh
- Data.Array.Accelerate: iterate :: forall a. Elt a => Exp Int -> (Exp a -> Exp a) -> Exp a -> Exp a
+ Data.Array.Accelerate: iterate :: Elt a => Exp Int -> (Exp a -> Exp a) -> Exp a -> Exp a
- Data.Array.Accelerate: linearIndexArray :: Array sh e -> Int -> e
+ Data.Array.Accelerate: linearIndexArray :: Elt e => Array sh e -> Int -> e
- 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: map :: forall sh a b. (Shape sh, Elt a, Elt b) => (Exp a -> Exp b) -> Acc (Array sh a) -> Acc (Array sh b)
- Data.Array.Accelerate: mod' :: (Floating a, RealFrac a, ToFloating Int a) => Exp a -> Exp a -> Exp a
+ Data.Array.Accelerate: mod' :: (Floating a, RealFrac a, ToFloating Int64 a) => Exp a -> Exp a -> Exp 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: permute :: forall sh sh' a. (Shape sh, Shape sh', Elt a) => (Exp a -> Exp a -> Exp a) -> Acc (Array sh' a) -> (Exp sh -> Exp (Maybe sh')) -> Acc (Array sh a) -> Acc (Array sh' a)
- Data.Array.Accelerate: properFraction :: (RealFrac a, Num b, ToFloating b a, IsIntegral b) => Exp a -> (Exp b, Exp a)
+ Data.Array.Accelerate: properFraction :: (RealFrac a, Integral b, FromIntegral Int64 b) => Exp a -> (Exp b, Exp a)
- Data.Array.Accelerate: replicate :: (Slice slix, Elt e) => Exp slix -> Acc (Array (SliceShape slix) e) -> Acc (Array (FullShape slix) e)
+ Data.Array.Accelerate: replicate :: forall slix e. (Slice slix, Elt e) => Exp slix -> Acc (Array (SliceShape slix) e) -> Acc (Array (FullShape slix) e)
- Data.Array.Accelerate: reshape :: (Shape sh, Shape sh', Elt e) => Exp sh -> Acc (Array sh' e) -> Acc (Array sh e)
+ Data.Array.Accelerate: reshape :: forall sh sh' e. (Shape sh, Shape sh', Elt e) => Exp sh -> Acc (Array sh' e) -> Acc (Array sh e)
- Data.Array.Accelerate: round :: (RealFrac a, Elt b, IsIntegral b) => Exp a -> Exp b
+ Data.Array.Accelerate: round :: (RealFrac a, Integral b, FromIntegral Int64 b) => Exp a -> Exp b
- 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 :: forall sh a. (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' :: (Shape sh, Elt a) => (Exp a -> Exp a -> Exp a) -> Exp a -> Acc (Array (sh :. Int) a) -> Acc (Array (sh :. Int) a, Array sh a)
+ Data.Array.Accelerate: scanl' :: forall sh a. (Shape sh, Elt a) => (Exp a -> Exp a -> Exp a) -> Exp a -> Acc (Array (sh :. Int) a) -> Acc (Array (sh :. Int) a, Array sh 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: scanl1 :: forall sh a. (Shape sh, Elt a) => (Exp a -> Exp a -> Exp a) -> Acc (Array (sh :. Int) a) -> Acc (Array (sh :. Int) 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 :: forall sh a. (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' :: (Shape sh, Elt a) => (Exp a -> Exp a -> Exp a) -> Exp a -> Acc (Array (sh :. Int) a) -> Acc (Array (sh :. Int) a, Array sh a)
+ Data.Array.Accelerate: scanr' :: forall sh a. (Shape sh, Elt a) => (Exp a -> Exp a -> Exp a) -> Exp a -> Acc (Array (sh :. Int) a) -> Acc (Array (sh :. Int) a, Array sh 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: scanr1 :: forall sh a. (Shape sh, Elt a) => (Exp a -> Exp a -> Exp a) -> Acc (Array (sh :. Int) a) -> Acc (Array (sh :. Int) 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: sfoldl :: (Shape 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 sh, Elt e) => Acc (Array sh e) -> Exp sh
+ Data.Array.Accelerate: shape :: forall sh e. (Shape sh, Elt e) => Acc (Array sh e) -> Exp sh
- Data.Array.Accelerate: shapeSize :: Shape sh => Exp sh -> Exp Int
+ Data.Array.Accelerate: shapeSize :: forall sh. Shape sh => Exp sh -> Exp Int
- Data.Array.Accelerate: slice :: (Slice slix, Elt e) => Acc (Array (FullShape slix) e) -> Exp slix -> Acc (Array (SliceShape slix) e)
+ Data.Array.Accelerate: slice :: forall slix e. (Slice slix, Elt e) => Acc (Array (FullShape slix) e) -> Exp slix -> Acc (Array (SliceShape slix) e)
- Data.Array.Accelerate: sliceIndex :: Slice sl => sl -> SliceIndex (EltRepr sl) (EltRepr (SliceShape sl)) (EltRepr (CoSliceShape sl)) (EltRepr (FullShape sl))
+ Data.Array.Accelerate: sliceIndex :: Slice sl => SliceIndex (EltR sl) (EltR (SliceShape sl)) (EltR (CoSliceShape sl)) (EltR (FullShape sl))
- 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: slit :: (Shape sh, Elt e) => Exp Int -> Exp Int -> Acc (Array (sh :. Int) e) -> Acc (Array (sh :. Int) e)
- Data.Array.Accelerate: snd :: forall a b. (Elt a, Elt b) => Exp (a, b) -> Exp b
+ Data.Array.Accelerate: snd :: (Elt a, Elt b) => Exp (a, b) -> Exp b
- Data.Array.Accelerate: stencil :: (Stencil sh a stencil, Elt b) => (stencil -> Exp b) -> Boundary (Array sh a) -> Acc (Array sh a) -> Acc (Array sh b)
+ Data.Array.Accelerate: stencil :: forall sh stencil a b. (Stencil sh a stencil, Elt b) => (stencil -> Exp b) -> Boundary (Array sh a) -> Acc (Array sh a) -> Acc (Array sh b)
- Data.Array.Accelerate: stencil2 :: (Stencil sh a stencil1, Stencil sh b stencil2, Elt c) => (stencil1 -> stencil2 -> Exp c) -> Boundary (Array sh a) -> Acc (Array sh a) -> Boundary (Array sh b) -> Acc (Array sh b) -> Acc (Array sh c)
+ Data.Array.Accelerate: stencil2 :: forall sh stencil1 stencil2 a b c. (Stencil sh a stencil1, Stencil sh b stencil2, Elt c) => (stencil1 -> stencil2 -> Exp c) -> Boundary (Array sh a) -> Acc (Array sh a) -> Boundary (Array sh b) -> Acc (Array sh b) -> Acc (Array sh c)
- 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: tail :: (Shape sh, Elt e) => Acc (Array (sh :. Int) e) -> Acc (Array (sh :. Int) 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: take :: (Shape sh, Elt e) => Exp Int -> Acc (Array (sh :. Int) e) -> Acc (Array (sh :. Int) e)
- Data.Array.Accelerate: toIndex :: Shape sh => Exp sh -> Exp sh -> Exp Int
+ Data.Array.Accelerate: toIndex :: forall sh. Shape sh => Exp sh -> Exp sh -> Exp Int
- Data.Array.Accelerate: toList :: forall sh e. Array sh e -> [e]
+ Data.Array.Accelerate: toList :: forall sh e. (Shape sh, Elt e) => Array sh e -> [e]
- Data.Array.Accelerate: truncate :: (RealFrac a, Elt b, IsIntegral b) => Exp a -> Exp b
+ Data.Array.Accelerate: truncate :: (RealFrac a, Integral b, FromIntegral Int64 b) => Exp a -> Exp b
- Data.Array.Accelerate: type Integral a = (Enum a, Real a, Integral (Exp a))
+ Data.Array.Accelerate: type Integral a = (Enum a, Ord a, Num a, Integral (Exp a))
- Data.Array.Accelerate: type Matrix = Array DIM2
+ Data.Array.Accelerate: type Matrix = Array DIM2 " Matrices are two-dimensional arrays"
- Data.Array.Accelerate: type Scalar = Array DIM0
+ Data.Array.Accelerate: type Scalar = Array DIM0 " Scalar arrays hold a single element"
- Data.Array.Accelerate: type Vector = Array DIM1
+ Data.Array.Accelerate: type Vector = Array DIM1 " Vectors are one-dimensional arrays"
- Data.Array.Accelerate: undefined :: HasCallStack => a
+ Data.Array.Accelerate: undefined :: forall (r :: RuntimeRep) (a :: TYPE r). HasCallStack => a
- Data.Array.Accelerate: unindex2 :: forall i. (Elt i, Slice (Z :. i)) => Exp (Z :. i :. i) -> Exp (i, i)
+ Data.Array.Accelerate: unindex2 :: Elt i => Exp ((Z :. i) :. i) -> Exp (i, i)
- 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: unindex3 :: Elt i => Exp (((Z :. i) :. i) :. i) -> Exp (i, i, i)
- Data.Array.Accelerate: unit :: Elt e => Exp e -> Acc (Scalar e)
+ Data.Array.Accelerate: unit :: forall e. Elt e => Exp e -> Acc (Scalar e)
- Data.Array.Accelerate: use :: Arrays arrays => arrays -> Acc arrays
+ Data.Array.Accelerate: use :: forall arrays. Arrays arrays => arrays -> Acc arrays
- Data.Array.Accelerate: while :: Elt e => (Exp e -> Exp Bool) -> (Exp e -> Exp e) -> Exp e -> Exp e
+ Data.Array.Accelerate: while :: forall e. Elt e => (Exp e -> Exp Bool) -> (Exp e -> Exp e) -> Exp e -> Exp e
- 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: zipWith :: forall sh a b c. (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: cis :: forall a. (Floating a, Elt (Complex 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 :: (Num a, Elt (Complex 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: imag :: (Elt a, Elt (Complex a)) => Exp (Complex a) -> Exp a
+ Data.Array.Accelerate.Data.Complex: imag :: Elt a => Exp (Complex a) -> Exp a
- Data.Array.Accelerate.Data.Complex: magnitude :: (RealFloat a, Elt (Complex 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 :: forall a. (Floating a, Elt (Complex 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 :: (RealFloat a, Elt (Complex 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 :: (RealFloat a, Elt (Complex a)) => Exp (Complex a) -> Exp (a, a)
+ Data.Array.Accelerate.Data.Complex: polar :: RealFloat a => Exp (Complex a) -> Exp (a, a)
- Data.Array.Accelerate.Data.Complex: real :: (Elt a, Elt (Complex a)) => Exp (Complex a) -> Exp a
+ Data.Array.Accelerate.Data.Complex: real :: Elt a => Exp (Complex a) -> Exp a
- Data.Array.Accelerate.Interpreter: class (Typeable a, Typeable (ArrRepr a)) => Arrays a
+ Data.Array.Accelerate.Interpreter: class Arrays a
- Data.Array.Accelerate.Interpreter: run :: Arrays a => Acc a -> a
+ Data.Array.Accelerate.Interpreter: run :: (HasCallStack, Arrays a) => Acc a -> a
- Data.Array.Accelerate.Interpreter: run1 :: (Arrays a, Arrays b) => (Acc a -> Acc b) -> a -> b
+ Data.Array.Accelerate.Interpreter: run1 :: (HasCallStack, Arrays a, Arrays b) => (Acc a -> Acc b) -> a -> b
- Data.Array.Accelerate.Interpreter: runN :: Afunction f => f -> AfunctionR f
+ Data.Array.Accelerate.Interpreter: runN :: forall f. (HasCallStack, Afunction f) => f -> AfunctionR f
- Data.Array.Accelerate.Unsafe: coerce :: (Elt a, Elt b) => Exp a -> Exp b
+ Data.Array.Accelerate.Unsafe: coerce :: Coerce (EltR a) (EltR b) => Exp a -> Exp b
- Data.Array.Accelerate.Unsafe: undef :: Elt t => Exp t
+ Data.Array.Accelerate.Unsafe: undef :: forall e. Elt e => Exp e

Files

CHANGELOG.md view
@@ -6,6 +6,59 @@ project adheres to the [Haskell Package Versioning Policy (PVP)](https://pvp.haskell.org) +## [1.3.0.0] - 2020-08-26+### Added+  * Instances of `Elt` are now derivable via `Generic` for simple (Haskell'98)+    product _and_ sum data types.+  * Pattern synonyms for manipulating custom product and sum types can now be+    created; see `Pattern`, `mkPattern`+  * Added pattern synonyms for accessing tuples and indices, as an alternative+    to `lift` and `unlift`.+  * Support for pattern matching in the embedded language; see `match`++### Changed+  * The `stencil` functions now support fusion. Note however that the source+    (delayed) array will be evaluated at _every_ access to the stencil pattern;+    if the delayed function is expensive, you may wish to explicitly `compute`+    the source array first, matching the old behaviour.+  * Removed `Slice` constraint from some indexing operations+  * Improve fusion for `zipWith*` ([#453])+  * The indexing function to `permute` now returns a `Maybe` type ([#87])++  * (internal) Visible type applications are used instead of `Proxy` types+  * (internal) `EltR` is now a class-associated type of `Elt`+  * (internal) `GArrayData` has been simplified+  * (internal) SIMD representation has been improved and generalised+  * (internal) Internal refactoring ([#449], [#455], [#457], [#460])++  * Probably many others I have forgotten about++### Removed+  * Drop support for GHC-7.10 .. 8.4.++### Contributors++Special thanks to those who contributed patches as part of this release:++  * Trevor L. McDonell (@tmcdonell)+  * Joshua Meredith (@JoshMeredith)+  * Ivo Gabe de Wolff (@ivogabe)+  * David van Balen (@dpvanbalen)+  * Jaro Reinders (@noughtmare)+  * Alex Lang (@alang9)+  * Paul Wilson (@status_failed)+  * @lennonhill+  * Travis Whitaker (@TravisWhitaker)+  * Roger Bosman (@rogerbosman)+  * Robbert van der Helm (@robbert-vdh)+  * Sam (@sam-340453)+  * Lars van den Haak (@sakehl)+  * Rinat Striungis (@Haskell-mouse)+  * Viktor Kronvall (@considerate)+  * Tom Smeding (@tomsmeding)+  * Ryan Scott (@RyanGlScott)++ ## [1.2.0.1] - 2018-10-06 ### Fixed   * Build fix for ghc-8.6@@ -133,6 +186,7 @@   * Initial release of the CUDA backend  +[1.3.0.0]:          https://github.com/AccelerateHS/accelerate/compare/v1.2.0.1...v1.3.0.0 [1.2.0.1]:          https://github.com/AccelerateHS/accelerate/compare/v1.2.0.0...v1.2.0.1 [1.2.0.0]:          https://github.com/AccelerateHS/accelerate/compare/v1.1.0.0...v1.2.0.0 [1.1.1.0]:          https://github.com/AccelerateHS/accelerate/compare/v1.1.0.0...v1.1.1.0@@ -148,6 +202,12 @@ [0.9.0.0]:          https://github.com/AccelerateHS/accelerate/compare/0_8_1_0...0.9.0.0 [0.7.1.0]:          https://github.com/AccelerateHS/accelerate/compare/0_6_0_0...0_7_1_0 +[#87]:              https://github.com/AccelerateHS/accelerate/issues/87 [#340]:             https://github.com/AccelerateHS/accelerate/issues/340 [#390]:             https://github.com/AccelerateHS/accelerate/issues/390+[#453]:             https://github.com/AccelerateHS/accelerate/pull/453+[#449]:             https://github.com/AccelerateHS/accelerate/pull/449+[#455]:             https://github.com/AccelerateHS/accelerate/pull/455+[#457]:             https://github.com/AccelerateHS/accelerate/pull/457+[#460]:             https://github.com/AccelerateHS/accelerate/pull/460 
LICENSE view
@@ -1,4 +1,4 @@-Copyright (c) [2007..2017] The Accelerate Team.  All rights reserved.+Copyright (c) [2007..2020] 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:@@ -7,8 +7,8 @@     * Redistributions in binary form must reproduce the above copyright       notice, this list of conditions and the following disclaimer in the       documentation and/or other materials provided with the distribution.-    * Neither the names of the contributors nor of their affiliations may -      be used to endorse or promote products derived from this software +    * Neither the names of the contributors nor of their affiliations may+      be used to endorse or promote products derived from this software       without specific prior written permission.  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
README.md view
@@ -1,13 +1,16 @@-An Embedded Language for Accelerated Array Computations-=======================================================+<div align="center">+<img width="450" src="https://github.com/AccelerateHS/accelerate/raw/master/images/accelerate-logo-text-v.png?raw=true" alt="henlo, my name is Theia"/> -[![Travis](https://img.shields.io/travis/AccelerateHS/accelerate/master.svg?label=linux)](https://travis-ci.org/AccelerateHS/accelerate)-[![AppVeyor](https://img.shields.io/appveyor/ci/tmcdonell/accelerate/master.svg?label=windows)](https://ci.appveyor.com/project/tmcdonell/accelerate)+# High-performance parallel arrays for Haskell++[![GitHub CI](https://github.com/tmcdonell/accelerate/workflows/CI/badge.svg)](https://github.com/tmcdonell/accelerate/actions)+[![Gitter](https://img.shields.io/gitter/room/nwjs/nw.js.svg)](https://gitter.im/AccelerateHS/Lobby)+<br> [![Stackage LTS](https://stackage.org/package/accelerate/badge/lts)](https://stackage.org/lts/package/accelerate) [![Stackage Nightly](https://stackage.org/package/accelerate/badge/nightly)](https://stackage.org/nightly/package/accelerate) [![Hackage](https://img.shields.io/hackage/v/accelerate.svg)](https://hackage.haskell.org/package/accelerate)-[![Gitter](https://img.shields.io/gitter/room/nwjs/nw.js.svg)](https://gitter.im/AccelerateHS/Lobby) +</div>  `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 executed on a range of architectures. @@ -17,6 +20,7 @@  * [Optimising Purely Functional GPU Programs][MCKL13] ([slides][MCKL13-slides])  * [Embedding Foreign Code][CMCK14]  * [Type-safe Runtime Code Generation: Accelerate to LLVM][MCGN15] ([slides][MCGN15-slides]) ([video][MCGN15-video])+ * [Streaming Irregular Arrays][CMCK17] ([video][CMCK17-video])  There are also slides from some fairly recent presentations: @@ -37,6 +41,7 @@   - [Requirements](#requirements)   - [Documentation](#documentation)   - [Examples](#examples)+  - [Who are we?](#who-are-we)   - [Mailing list and contacts](#mailing-list-and-contacts)   - [Citing Accelerate](#citing-accelerate)   - [What's missing?](#whats-missing)@@ -106,8 +111,8 @@   * A cellular automata simulation   * A "password recovery" tool, for dictionary lookup of MD5 hashes -[![Mandelbrot](http://i.imgur.com/5Tbsp1j.jpg "accelerate-mandelbrot")](http://i.imgur.com/RgXRqsc.jpg)-[![Raytracer](http://i.imgur.com/7ohhKm9.jpg "accelerate-ray")](http://i.imgur.com/ZNEGEJK.jpg)+[![Mandelbrot](https://i.imgur.com/5Tbsp1j.jpg "accelerate-mandelbrot")](https://i.imgur.com/RgXRqsc.jpg)+[![Raytracer](https://i.imgur.com/7ohhKm9.jpg "accelerate-ray")](https://i.imgur.com/ZNEGEJK.jpg)  <!-- <video width=400 height=300 controls=false autoplay loop>@@ -120,12 +125,7 @@  [LULESH-accelerate][lulesh-accelerate] is in implementation of the Livermore Unstructured Lagrangian Explicit Shock Hydrodynamics (LULESH) mini-app. [LULESH][LULESH] represents a typical hydrodynamics code such as [ALE3D][ALE3D], but is a highly simplified application, hard-coded to solve the Sedov blast problem on an unstructured hexahedron mesh. -![LULESH mesh](https://codesign.llnl.gov/images/sedov-3d-LLNL.png)---### Λ ○ λ (Lol)--Λ ○ λ ([Lol][lol]) is a general-purpose library for ring-based lattice cryptography. Lol has applications in, for example, symmetric-key somewhat-homomorphic encryption schemes. The [lol-accelerate][lol-accelerate] package provides an Accelerate backend for Lol.+![LULESH mesh](https://i.imgur.com/bIkODKd.jpg)   ### Additional examples@@ -133,27 +133,50 @@ Accelerate users have also built some substantial applications of their own. Please feel free to add your own examples! +  * Jonathan Fraser, [GPUVAC](https://github.com/GeneralFusion/gpuvac): An explicit advection magnetohydrodynamics simulation+  * David van Balen, [Sudokus](https://github.com/dpvanbalen/Sudokus): A sudoku solver+  * Trevor L. McDonell, [lol-accelerate][lol-accelerate]: A backend to the Λ ○ λ ([Lol][lol]) library for ring-based lattice cryptography   * Henning Thielemann, [patch-image](http://hackage.haskell.org/package/patch-image): Combine a collage of overlapping images   * apunktbau, [bildpunkt](https://github.com/abau/bildpunkt): A ray-marching distance field renderer   * klarh, [hasdy](https://github.com/klarh/hasdy): Molecular dynamics in Haskell using Accelerate   * Alexandros Gremm used Accelerate as part of the [2014 CSCS summer school](http://user.cscs.ch/blog/2014/cscs_usi_summer_school_2014_30_june_10_july_2014_in_serpiano_tessin/index.html) ([code](https://github.com/agremm/cscs))  +Who are we?+-----------++The Accelerate team (past and present) consists of:++  * Manuel M T Chakravarty ([@mchakravarty])  <!-- 2008..2017? -->+  * Gabriele Keller ([@gckeller])             <!-- 2008..     -->+  * Trevor L. McDonell ([@tmcdonell])         <!-- 2009..     -->+  * Robert Clifton-Everest ([@robeverest])    <!-- 2013..     -->+  * Frederik M. Madsen ([@fmma])              <!-- 2014       -->+  * Ryan R. Newton ([@rrnewton])              <!-- 2012..2013 -->+  * Joshua Meredith ([@JoshMeredith])         <!-- 2018..     -->+  * Ben Lever ([@blever])                     <!-- 2010..2011 -->+  * Sean Seefried ([@sseefried])              <!-- 2010..2011 -->+  * Ivo Gabe de Wolff ([@ivogabe])            <!-- 2019..     -->++The maintainer and principal developer of Accelerate is Trevor L.+McDonell <trevor.mcdonell@gmail.com>.++ Mailing list and contacts -------------------------    * Mailing list: [`accelerate-haskell@googlegroups.com`](mailto:accelerate-haskell@googlegroups.com) (discussions on both use and development are welcome)-  * Sign up for the mailing list at the [Accelerate Google Groups page][Google-Group].-  * Bug reports and issues tracking: [GitHub project page][Issues].--The maintainers of Accelerate are Manuel M T Chakravarty <chak@cse.unsw.edu.au> and Trevor L McDonell <tmcdonell@cse.unsw.edu.au>.+  * Sign up for the mailing list at the [Accelerate Google Groups page][Google-Group]+  * Bug reports and issues tracking: [GitHub project page][Issues]+  * Chat with us on [gitter](https://gitter.im/AccelerateHS/Lobby)   Citing Accelerate -----------------  If you use Accelerate for academic research, you are encouraged (though not-required) to cite the following papers ([BibTeX](http://www.cse.unsw.edu.au/~tmcdonell/papers/accelerate.bib)):+required) to cite the following papers:+<!-- ([BibTeX](http://www.cse.unsw.edu.au/~tmcdonell/papers/accelerate.bib)): -->    * Manuel M. T. Chakravarty, Gabriele Keller, Sean Lee, Trevor L. McDonell, and Vinod Grover.     [Accelerating Haskell Array Codes with Multicore GPUs][CKLM+11].@@ -171,6 +194,11 @@     [Type-safe Runtime Code Generation: Accelerate to LLVM][MCGN15].     In _Haskell '15: The 8th ACM SIGPLAN Symposium on Haskell_, ACM, 2015. +  * Robert Clifton-Everest, Trevor L. McDonell, Manuel M. T. Chakravarty, and Gabriele Keller.+    [Streaming Irregular Arrays][CMCK17].+    In Haskell '17: The 10th ACM SIGPLAN Symposium on Haskell, ACM, 2017.++ Accelerate is primarily developed by academics, so citations matter a lot to us. As an added benefit, you increase Accelerate's exposure and potential user (and developer!) base, which is a benefit to all users of Accelerate. Thanks in advance!@@ -182,17 +210,29 @@ Here is a list of features that are currently missing:   * Preliminary API (parts of the API may still change in subsequent releases)-+ * Many more features... contact us! +  [@mchakravarty]:              https://github.com/mchakravarty+  [@gckeller]:                  https://github.com/gckeller+  [@tmcdonell]:                 https://github.com/tmcdonell+  [@robeverest]:                https://github.com/robeverest+  [@fmma]:                      https://github.com/fmma+  [@rrnewton]:                  https://github.com/rrnewton+  [@JoshMeredith]:              https://github.com/JoshMeredith+  [@blever]:                    https://github.com/blever+  [@sseefried]:                 https://github.com/sseefried+  [@ivogabe]:                   https://github.com/ivogabe -  [CKLM+11]:                    http://www.cse.unsw.edu.au/~chak/papers/CKLM+11.html-  [MCKL13]:                     http://www.cse.unsw.edu.au/~chak/papers/MCKL13.html+  [CKLM+11]:                    https://github.com/tmcdonell/tmcdonell.github.io/raw/master/papers/acc-cuda-damp2011.pdf+  [MCKL13]:                     https://github.com/tmcdonell/tmcdonell.github.io/raw/master/papers/acc-optim-icfp2013.pdf   [MCKL13-slides]:              https://speakerdeck.com/tmcdonell/optimising-purely-functional-gpu-programs-  [CMCK14]:                     http://www.cse.unsw.edu.au/~chak/papers/CMCK14.html-  [MCGN15]:                     http://www.cse.unsw.edu.au/~chak/papers/MCGN15.html+  [CMCK14]:                     https://github.com/tmcdonell/tmcdonell.github.io/raw/master/papers/acc-ffi-padl2014.pdf+  [MCGN15]:                     https://github.com/tmcdonell/tmcdonell.github.io/raw/master/papers/acc-llvm-haskell2015.pdf   [MCGN15-slides]:              https://speakerdeck.com/tmcdonell/type-safe-runtime-code-generation-accelerate-to-llvm   [MCGN15-video]:               https://www.youtube.com/watch?v=snXhXA5noVc   [HIW'09]:                     https://wiki.haskell.org/HaskellImplementorsWorkshop+  [CMCK17]:                     https://github.com/tmcdonell/tmcdonell.github.io/raw/master/papers/acc-seq2-haskell2017.pdf+  [CMCK17-video]:               https://www.youtube.com/watch?v=QIWSqp7AaNo   [Mar13]:                      http://chimera.labs.oreilly.com/books/1230000000929   [Embedded]:                   https://speakerdeck.com/mchakravarty/embedded-languages-for-high-performance-computing-in-haskell   [Hackage]:                    http://hackage.haskell.org/package/accelerate@@ -215,7 +255,8 @@   [Wiki]:                       https://github.com/AccelerateHS/accelerate/wiki   [Issues]:                     https://github.com/AccelerateHS/accelerate/issues   [Google-Group]:               http://groups.google.com/group/accelerate-haskell-  [HOAS-conv]:                  http://www.cse.unsw.edu.au/~chak/haskell/term-conv/+  [HOAS-conv]:                  https://github.com/mchakravarty/hoas-conv+  <!-- [HOAS-conv]:                  https://web.archive.org/web/20180805092417/http://www.cse.unsw.edu.au/~chak/haskell/term-conv/ -->   [repa]:                       http://hackage.haskell.org/package/repa   [wiki-cc]:                    https://en.wikipedia.org/wiki/CUDA#Supported_GPUs   [YLJ13-video]:                http://youtu.be/ARqE4yT2Z0o@@ -226,7 +267,7 @@   [wiki-nbody]:                 https://en.wikipedia.org/wiki/N-body   [wiki-raytracing]:            https://en.wikipedia.org/wiki/Ray_tracing   [wiki-pagerank]:              https://en.wikipedia.org/wiki/Pagerank-  [Trevor-thesis]:              http://www.cse.unsw.edu.au/~tmcdonell/papers/TrevorMcDonell_PhD_submission.pdf+  [Trevor-thesis]:              https://github.com/tmcdonell/tmcdonell.github.io/raw/master/papers/TrevorMcDonell_PhD_Thesis.pdf   [colour-accelerate]:          https://github.com/tmcdonell/colour-accelerate   [gloss]:                      https://hackage.haskell.org/package/gloss   [gloss-accelerate]:           https://github.com/tmcdonell/gloss-accelerate
accelerate.cabal view
@@ -1,12 +1,12 @@-Name:                   accelerate-Version:                1.2.0.1-Cabal-version:          >= 1.18-Tested-with:            GHC >= 7.8-Build-type:             Custom+name:                   accelerate+version:                1.3.0.0+cabal-version:          1.18+tested-with:            GHC >= 8.6+build-type:             Custom -Synopsis:               An embedded language for accelerated array processing+synopsis:               An embedded language for accelerated array processing -Description:+description:   @Data.Array.Accelerate@ defines an embedded array language for computations   for high-performance computing in Haskell. Computations on multi-dimensional,   regular arrays are expressed in the form of parameterised collective@@ -41,18 +41,25 @@       greater. See the following table for supported GPUs:       <http://en.wikipedia.org/wiki/CUDA#Supported_GPUs>   .-    * @accelerate-examples@: Computational kernels and applications showcasing-      the use of Accelerate as well as a regression test suite, supporting-      function and performance testing.+    * @accelerate-examples@: Computational kernels and applications+      demonstrating the use of Accelerate.   .-    * @accelerate-io@: Fast conversions between Accelerate arrays and other-      array formats (including vector and repa).+    * @accelerate-io*@: Fast conversions between Accelerate arrays and other+      array and data formats.   .     * @accelerate-fft@: Discrete Fourier transforms, with FFI bindings to       optimised implementations.   .+    * @accelerate-blas@: Numeric linear algebra, with FFI bindings to optimised+      implementations.+  .     * @accelerate-bignum@: Fixed-width large integer arithmetic.   .+    * @containers-accelerate@: Container types for use with Accelerate.+  .+    * @hashable-accelerate@: Class for types which can be converted to a hash+      value.+  .     * @colour-accelerate@: Colour representations in Accelerate (RGB, sRGB, HSV,       and HSL).   .@@ -77,7 +84,7 @@   .     * An implementation of the Canny edge detection algorithm   .-    * An interactive Mandelbrot set generator+    * Interactive Mandelbrot and Julia set generators   .     * A particle-based simulation of stable fluid flows   .@@ -99,6 +106,8 @@   .   [/Mailing list and contacts/]   .+    * Gitter chat: <https://gitter.im/AccelerateHS/Lobby>+  .     * Mailing list: <accelerate-haskell@googlegroups.com> (discussion of both       use and development welcome).   .@@ -109,40 +118,34 @@       <https://github.com/AccelerateHS/accelerate/issues>   . -License:                BSD3-License-file:           LICENSE-Author:                 Manuel M T Chakravarty,-                        Robert Clifton-Everest,-                        Gabriele Keller,-                        Ben Lever,-                        Trevor L. McDonell,-                        Ryan Newtown,-                        Sean Seefried-Maintainer:             Trevor L. McDonell <tmcdonell@cse.unsw.edu.au>-Homepage:               https://github.com/AccelerateHS/accelerate/-Bug-reports:            https://github.com/AccelerateHS/accelerate/issues+license:                BSD3+license-file:           LICENSE+author:                 The Accelerate Team+maintainer:             Trevor L. McDonell <trevor.mcdonell@gmail.com>+homepage:               https://github.com/AccelerateHS/accelerate/+bug-reports:            https://github.com/AccelerateHS/accelerate/issues -Category:               Compilers/Interpreters, Concurrency, Data, Parallelism-Stability:              Experimental+category:               Accelerate, Compilers/Interpreters, Concurrency, Data, Parallelism+stability:              Experimental -Extra-source-files:+extra-source-files:     README.md     CHANGELOG.md-    cbits/flags.inc-    cbits/monitoring.inc+    cbits/*.c+    cbits/*.h -Extra-doc-files:+extra-doc-files:     images/*.png  custom-setup   setup-depends:-      base              >= 4.7+      base              >= 4.10     , Cabal     , cabal-doctest     >= 1.0 -Flag debug-  Default:              False-  Description:+flag debug+  default:              False+  description:     Enable debug tracing messages. The following options are read from the     environment variable @ACCELERATE_FLAGS@, and via the command-line as:     .@@ -161,6 +164,8 @@     .       * @simplify@: Enable program simplification phase (True).     .+      * @inplace@: Enable in-place array updates (True).+    .       * @flush-cache@: Clear any persistent caches on program startup (False).     .       * @force-recomp@: Force recompilation of array programs (False).@@ -168,6 +173,9 @@       * @fast-math@: Allow algebraically equivalent transformations which may         change floating point results (e.g., reassociate) (True).     .+      * @fast-permute-const@: Allow non-atomic `permute const` for product types+        (True).+    .     The following options control debug message output, and are enabled with     @-d\<flag\>@.     .@@ -212,9 +220,9 @@       * @dump-sched@: Print information related to execution scheduling.     . -Flag ekg-  Default:              False-  Description:+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     call @Data.Array.Accelerate.Debug.beginMonitoring@ before running any@@ -248,57 +256,56 @@     > -with-rtsopts=-T     . -Flag bounds-checks-  Description:          Enable bounds checking-  Default:              True+flag bounds-checks+  description:          Enable bounds checking+  default:              True -Flag unsafe-checks-  Description:          Enable bounds checking in unsafe operations-  Default:              False+flag unsafe-checks+  description:          Enable bounds checking in unsafe operations+  default:              False -Flag internal-checks-  Description:          Enable internal consistency checks-  Default:              False+flag internal-checks+  description:          Enable internal consistency checks+  default:              False -Flag nofib-  Default:              True-  Description:-    You can disable building the nofib test suite with this flag. Disabling this-    is an unsupported configuration, but is useful for accelerating builds.+-- Enabling this drastically increases build times+-- See: https://gitlab.haskell.org/ghc/ghc/issues/15751+flag nofib+  default:              False+  description:          Build the nofib test suite (required for backend testing) -Library-  Build-depends:-          base                          >= 4.7 && < 4.13+library+  build-depends:+          base                          >= 4.12 && < 4.15         , ansi-terminal                 >= 0.6.2-        , ansi-wl-pprint                >= 0.6         , base-orphans                  >= 0.3         , bytestring                    >= 0.10.2         , containers                    >= 0.3-        , constraints                   >= 0.9         , cryptonite                    >= 0.21         , deepseq                       >= 1.3         , directory                     >= 1.0         , exceptions                    >= 0.6         , filepath                      >= 1.0         , ghc-prim-        , half                          >= 0.2+        , half                          >= 0.3         , hashable                      >= 1.1         , hashtables                    >= 1.2.3         , hedgehog                      >= 0.5         , lens                          >= 4.0         , mtl                           >= 2.0+        , prettyprinter                 >= 1.2+        , prettyprinter-ansi-terminal   >= 1.0+        , primitive                     >= 0.6.4         , tasty                         >= 0.11-        , tasty-expected-failure        >= 0.11-        , tasty-hedgehog                >= 0.1-        , tasty-hunit                   >= 0.9         , template-haskell         , terminal-size                 >= 0.3+        , text                          >= 1.2         , transformers                  >= 0.3         , unique         , unordered-containers          >= 0.2         , vector                        >= 0.10 -  Exposed-modules:+  exposed-modules:         -- The core language and reference implementation         Data.Array.Accelerate         Data.Array.Accelerate.Interpreter@@ -311,41 +318,60 @@         Data.Array.Accelerate.Data.Functor         Data.Array.Accelerate.Data.Maybe         Data.Array.Accelerate.Data.Monoid+        Data.Array.Accelerate.Data.Ratio         Data.Array.Accelerate.Unsafe          -- For backend development (hidden)         Data.Array.Accelerate.AST+        Data.Array.Accelerate.AST.Environment+        Data.Array.Accelerate.AST.Idx+        Data.Array.Accelerate.AST.LeftHandSide+        Data.Array.Accelerate.AST.Var         Data.Array.Accelerate.Analysis.Hash         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.Lifetime         Data.Array.Accelerate.Pretty-        Data.Array.Accelerate.Product+        Data.Array.Accelerate.Representation.Array+        Data.Array.Accelerate.Representation.Elt+        Data.Array.Accelerate.Representation.Shape+        Data.Array.Accelerate.Representation.Slice+        Data.Array.Accelerate.Representation.Stencil+        Data.Array.Accelerate.Representation.Tag+        Data.Array.Accelerate.Representation.Type+        Data.Array.Accelerate.Representation.Vec         Data.Array.Accelerate.Smart+        Data.Array.Accelerate.Sugar.Array+        Data.Array.Accelerate.Sugar.Elt+        Data.Array.Accelerate.Sugar.Foreign+        Data.Array.Accelerate.Sugar.Shape+        Data.Array.Accelerate.Sugar.Vec         Data.Array.Accelerate.Trafo+        Data.Array.Accelerate.Trafo.Config+        Data.Array.Accelerate.Trafo.Delayed+        Data.Array.Accelerate.Trafo.Fusion+        Data.Array.Accelerate.Trafo.Sharing+        Data.Array.Accelerate.Trafo.Substitution         Data.Array.Accelerate.Type          -- For testing         Data.Array.Accelerate.Test.NoFib         Data.Array.Accelerate.Test.Similar -  Other-modules:-        Data.Atomic+        -- Other+        Data.BitSet+        Data.Primitive.Vec++  other-modules:         Data.Array.Accelerate.Analysis.Hash.TH-        Data.Array.Accelerate.Array.Lifted         Data.Array.Accelerate.Array.Remote.Nursery         Data.Array.Accelerate.Classes         Data.Array.Accelerate.Classes.Bounded@@ -357,10 +383,12 @@         Data.Array.Accelerate.Classes.Integral         Data.Array.Accelerate.Classes.Num         Data.Array.Accelerate.Classes.Ord+        Data.Array.Accelerate.Classes.Rational         Data.Array.Accelerate.Classes.Real         Data.Array.Accelerate.Classes.RealFloat         Data.Array.Accelerate.Classes.RealFrac         Data.Array.Accelerate.Classes.ToFloating+        Data.Array.Accelerate.Debug.Clock         Data.Array.Accelerate.Debug.Flags         Data.Array.Accelerate.Debug.Monitoring         Data.Array.Accelerate.Debug.Stats@@ -368,27 +396,40 @@         Data.Array.Accelerate.Debug.Trace         Data.Array.Accelerate.Language         Data.Array.Accelerate.Lift+        Data.Array.Accelerate.Orphans+        Data.Array.Accelerate.Pattern+        Data.Array.Accelerate.Pattern.Bool+        Data.Array.Accelerate.Pattern.Either+        Data.Array.Accelerate.Pattern.Maybe+        Data.Array.Accelerate.Pattern.Ordering+        Data.Array.Accelerate.Pattern.TH         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.Environment+        Data.Array.Accelerate.Trafo.LetSplit         Data.Array.Accelerate.Trafo.Shrink         Data.Array.Accelerate.Trafo.Simplify-        Data.Array.Accelerate.Trafo.Substitution+        Data.Array.Accelerate.Trafo.Var+        Data.Atomic++        -- Data.Array.Accelerate.Array.Lifted         -- Data.Array.Accelerate.Trafo.Vectorise          -- nofib test suite         Data.Array.Accelerate.Test.NoFib.Base         Data.Array.Accelerate.Test.NoFib.Config +        Language.Haskell.TH.Extra+   if flag(nofib)-    -- build-depends:+    build-depends:+          tasty-expected-failure        >= 0.11+        , tasty-hedgehog                >= 0.1+        , tasty-hunit                   >= 0.9     --     , pipes                         >= 4.1.6   -- #286      other-modules:@@ -396,6 +437,7 @@         Data.Array.Accelerate.Test.NoFib.Prelude         Data.Array.Accelerate.Test.NoFib.Prelude.Map         Data.Array.Accelerate.Test.NoFib.Prelude.ZipWith+        Data.Array.Accelerate.Test.NoFib.Prelude.SIMD         Data.Array.Accelerate.Test.NoFib.Prelude.Fold         Data.Array.Accelerate.Test.NoFib.Prelude.Scan         Data.Array.Accelerate.Test.NoFib.Prelude.Backpermute@@ -428,8 +470,13 @@         Data.Array.Accelerate.Test.NoFib.Issues.Issue287         Data.Array.Accelerate.Test.NoFib.Issues.Issue288         Data.Array.Accelerate.Test.NoFib.Issues.Issue362+        Data.Array.Accelerate.Test.NoFib.Issues.Issue364         Data.Array.Accelerate.Test.NoFib.Issues.Issue407         Data.Array.Accelerate.Test.NoFib.Issues.Issue409+        Data.Array.Accelerate.Test.NoFib.Issues.Issue436+        Data.Array.Accelerate.Test.NoFib.Issues.Issue437+        Data.Array.Accelerate.Test.NoFib.Issues.Issue439+   else     cpp-options:         -DACCELERATE_DISABLE_NOFIB@@ -451,19 +498,6 @@     cpp-options:         -DACCELERATE_DEBUG -    -- Weird handling of C files because Cabal is not recompile C files on-    -- changes to cc-options: <https://github.com/haskell/cabal/issues/4937>-    c-sources:-        cbits/atomic.c-        cbits/clock.c-        cbits/flags_debug.c-        cbits/monitoring_debug.c-  else-    c-sources:-        cbits/atomic.c-        cbits/flags.c-        cbits/monitoring.c-   if flag(ekg)     cpp-options:         -DACCELERATE_MONITORING@@ -500,30 +534,17 @@   ghc-options:         -O2         -Wall+        -Wcompat+        -Wmissed-specialisations+        -- -Wredundant-constraints+        -freduction-depth=100+        -fspec-constr-count=50         -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:-        -Wcompat-        -freduction-depth=35--  if impl(ghc < 7.10)-    build-depends:-          th-lift-instances             >= 0.1-   -- 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.@@ -538,7 +559,7 @@   main-is:              Main.hs    build-depends:-          base                          >= 4.7+          base                          >= 4.10         , accelerate         , doctest                       >= 0.11 @@ -547,17 +568,9 @@         -threaded         -rtsopts -  -- older ghc does not support the dimension-specialised show instances for-  -- arrays, which the doctests use-  if impl(ghc < 7.10)-    buildable:          False--  -- doctest only supports a single x-doctest-options line-  if impl(ghc == 7.*)-    x-doctest-options:  -fspec-constr-count=25 -fcontext-stack=35--  if impl(ghc >= 8.0)-    x-doctest-options:  -fspec-constr-count=25 -freduction-depth=35+  x-doctest-options:+        -freduction-depth=100+        -fspec-constr-count=50   test-suite nofib-interpreter@@ -566,8 +579,11 @@   hs-source-dirs:       test/nofib   main-is:              Main.hs +  if !flag(nofib)+    buildable: False+   build-depends:-          base                          >= 4.7+          base                          >= 4.10         , accelerate    ghc-options:@@ -584,7 +600,7 @@  source-repository this   Type:                 git-  Tag:                  v1.2.0.1+  Tag:                  v1.3.0.0   Location:             git://github.com/AccelerateHS/accelerate.git  -- vim: nospell
cbits/atomic.c view
@@ -1,9 +1,9 @@ /*  * Module      : Data.Atomic- * Copyright   : [2017] Trevor L. McDonell+ * Copyright   : [2017..2020] The Accelerate Team  * License     : BSD3  *- * Maintainer  : Trevor L. McDonell <tmcdonell@cse.unsw.edu.au>+ * Maintainer  : Trevor L. McDonell <trevor.mcdonell@gmail.com>  * Stability   : experimental  * Portability : non-portable (GHC extensions)  *
cbits/clock.c view
@@ -1,9 +1,9 @@ /*  * Module      : Data.Array.Accelerate.Debug.Clock- * Copyright   : [2017] Trevor L. McDonell+ * Copyright   : [2017..2020] The Accelerate Team  * License     : BSD3  *- * Maintainer  : Trevor L. McDonell <tmcdonell@cse.unsw.edu.au>+ * Maintainer  : Trevor L. McDonell <trevor.mcdonell@gmail.com>  * Stability   : experimental  * Portability : non-portable (GHC extensions)  *@@ -26,16 +26,39 @@ #include <mach/clock.h> #include <mach/mach.h> -static void clock_darwin_gettime(clock_id_t clock, struct timespec *t)+static clock_serv_t __cclock;++/* constructors with priority execute before constructors without a priority+ * value.+ *+ * constructors with a lower [numeric] priority value are executed before+ * constructors with a higher [numeric] priority.+ *+ * constructor priority values [0,100] are reserved.+ */+__attribute__((constructor(101))) void initialise_clock_service(void) {+    host_get_clock_service(mach_host_self(), SYSTEM_CLOCK, &__cclock);+}++/* destructors without a priority execute before destructors with a priority+ *+ * destructors with a higher [numeric] priority value are executed before+ * destructors with a lower priority value.+ *+ * destructor priority values [0,100] are reserved.+ */+__attribute__((destructor(101))) void deallocate_clock_service(void)+{+    mach_port_deallocate(mach_task_self(), __cclock);+}++static void clock_darwin_gettime(struct timespec *t)+{     // OS X does not have clock_gettime, use clock_get_time     // see http://stackoverflow.com/questions/11680461/monotonic-clock-on-osx-    clock_serv_t cclock;     mach_timespec_t mts;--    host_get_clock_service(mach_host_self(), clock, &cclock);-    clock_get_time(cclock, &mts);-    mach_port_deallocate(mach_task_self(), cclock);+    clock_get_time(__cclock, &mts);      t->tv_sec  = mts.tv_sec;     t->tv_nsec = mts.tv_nsec;@@ -44,7 +67,7 @@ double clock_gettime_monotonic_seconds() {     struct timespec t;-    clock_darwin_gettime(SYSTEM_CLOCK, &t);+    clock_darwin_gettime(&t);      return (double) t.tv_sec + (double) t.tv_nsec * 1.0E-9; }
cbits/flags.c view
@@ -1,12 +1,343 @@ /*  * Module      : Data.Array.Accelerate.Debug.Flags- * Copyright   : [2017] Trevor L. McDonell+ * Copyright   : [2017..2020] The Accelerate Team  * License     : BSD3  *- * Maintainer  : Trevor L. McDonell <tmcdonell@cse.unsw.edu.au>+ * Maintainer  : Trevor L. McDonell <trevor.mcdonell@gmail.com>  * Stability   : experimental  * Portability : non-portable (GHC extensions)+ *+ * Option parsing for debug flags. This is a translation of the module+ * Data.Array.Accelerate.Debug.Flags into C, so that we can implement it at+ * program initialisation.+ *+ * This processes flags between +ACC ... -ACC on the command line. The+ * corresponding fields are removed from the command line. Note that we can't at+ * this stage update the number of command line arguments, but with some tricks+ * they can be mostly deleted.  */ -#include "flags.inc"+#include <ctype.h>+#include <getopt.h>+#include <inttypes.h>+#include <libgen.h>+#include <stdint.h>+#include <stdio.h>+#include <stdlib.h>+#include <string.h>++#include "flags.h"+++/* These globals will be accessed from the Haskell side to implement the+ * corresponding behaviour.+ */++__flags_t __cmd_line_flags            = { 0xff };  // SEE: [layout of command line options bitfield]+uint32_t  __unfolding_use_threshold   = 1;+uint32_t  __max_simplifier_iterations = 25;++enum {+  OPT_ENABLE = 1,+  OPT_DISABLE,+  OPT_UNFOLDING_USE_THRESHOLD,+  OPT_MAX_SIMPLIFIER_ITERATIONS+};++/* NOTE: [layout of command line options bitfield]+ *+ * When adding new options, make sure the offset value in the OPT_DISABLE branch+ * is updated, and that the flags are kept in order.+ */+static const char*         shortopts  = "";+static const struct option longopts[] =+  { { "fseq-sharing",                   no_argument,       NULL, OPT_ENABLE                    }+  , { "facc-sharing",                   no_argument,       NULL, OPT_ENABLE                    }+  , { "fexp-sharing",                   no_argument,       NULL, OPT_ENABLE                    }+  , { "ffusion",                        no_argument,       NULL, OPT_ENABLE                    }+  , { "fsimplify",                      no_argument,       NULL, OPT_ENABLE                    }+  , { "finplace",                       no_argument,       NULL, OPT_ENABLE                    }+  , { "ffast-math",                     no_argument,       NULL, OPT_ENABLE                    }+  , { "ffast-permute-const",            no_argument,       NULL, OPT_ENABLE                    }+  , { "fflush-cache",                   no_argument,       NULL, OPT_ENABLE                    }+  , { "fforce-recomp",                  no_argument,       NULL, OPT_ENABLE                    }++  , { "ddebug",                         no_argument,       NULL, OPT_ENABLE                    }+  , { "dverbose",                       no_argument,       NULL, OPT_ENABLE                    }+  , { "ddump-phases",                   no_argument,       NULL, OPT_ENABLE                    }+  , { "ddump-sharing",                  no_argument,       NULL, OPT_ENABLE                    }+  , { "ddump-fusion",                   no_argument,       NULL, OPT_ENABLE                    }+  , { "ddump-simpl-stats",              no_argument,       NULL, OPT_ENABLE                    }+  , { "ddump-simpl-iterations",         no_argument,       NULL, OPT_ENABLE                    }+  , { "ddump-vectorisation",            no_argument,       NULL, OPT_ENABLE                    }+  , { "ddump-dot",                      no_argument,       NULL, OPT_ENABLE                    }+  , { "ddump-simpl-dot",                no_argument,       NULL, OPT_ENABLE                    }+  , { "ddump-gc",                       no_argument,       NULL, OPT_ENABLE                    }+  , { "ddump-gc-stats",                 no_argument,       NULL, OPT_ENABLE                    }+  , { "ddump-cc",                       no_argument,       NULL, OPT_ENABLE                    }+  , { "ddump-ld",                       no_argument,       NULL, OPT_ENABLE                    }+  , { "ddump-asm",                      no_argument,       NULL, OPT_ENABLE                    }+  , { "ddump-exec",                     no_argument,       NULL, OPT_ENABLE                    }+  , { "ddump-sched",                    no_argument,       NULL, OPT_ENABLE                    }++  , { "fno-seq-sharing",                no_argument,       NULL, OPT_DISABLE                   }+  , { "fno-acc-sharing",                no_argument,       NULL, OPT_DISABLE                   }+  , { "fno-exp-sharing",                no_argument,       NULL, OPT_DISABLE                   }+  , { "fno-fusion",                     no_argument,       NULL, OPT_DISABLE                   }+  , { "fno-simplify",                   no_argument,       NULL, OPT_DISABLE                   }+  , { "fno-inplace",                    no_argument,       NULL, OPT_DISABLE                   }+  , { "fno-fast-math",                  no_argument,       NULL, OPT_DISABLE                   }+  , { "fno-fast-permute-const",         no_argument,       NULL, OPT_DISABLE                   }+  , { "fno-flush-cache",                no_argument,       NULL, OPT_DISABLE                   }+  , { "fno-force-recomp",               no_argument,       NULL, OPT_DISABLE                   }++  , { "funfolding-use-threshold=INT",   required_argument, NULL, OPT_UNFOLDING_USE_THRESHOLD   }+  , { "fmax-simplifier-iterations=INT", required_argument, NULL, OPT_MAX_SIMPLIFIER_ITERATIONS }++  /* required sentinel */+  , { NULL, 0, NULL, 0 }+  };+++/* Parse the given vector of command line arguments and set the corresponding+ * flags. The vector should contain no non-option arguments (aside from the name+ * of the program as the first entry, which is required for getopt()).+ */+static void parse_options(int argc, char *argv[])+{+  const struct option* opt;+  char* this;+  int   did_show_banner;+  int   prefix;+  int   result;+  int   longindex;++  while (-1 != (result = getopt_long_only(argc, argv, shortopts, longopts, &longindex)))+  {+    switch(result)+    {+    /* the option flag was set */+    case 0:+      break;++    case OPT_ENABLE:+      __cmd_line_flags.bitfield |= 1 << longindex;+      break;++    case OPT_DISABLE:+      __cmd_line_flags.bitfield &= ~(1 << (longindex - 27));  // SEE: [layout of command line options bitfield]+      break;++    /* attempt to decode the argument to flags which require them */+    case OPT_UNFOLDING_USE_THRESHOLD:+      if (1 != sscanf(optarg, "%"PRIu32, &__unfolding_use_threshold)) {+        fprintf(stderr, "%s: option `-%s' requires an integer argument, but got: %s\n"+                      , basename(argv[0])+                      , longopts[longindex].name+                      , optarg+                      );+      }+      break;++    case OPT_MAX_SIMPLIFIER_ITERATIONS:+      if (1 != sscanf(optarg, "%"PRIu32, &__max_simplifier_iterations)) {+        fprintf(stderr, "%s: option `-%s' requires an integer argument, but got: %s\n"+                      , basename(argv[0])+                      , longopts[longindex].name+                      , optarg+                      );+      }+      break;++    /* option was ambiguous or was missing a required argument+     *+     * TLM: longindex is not being updated correctly on my system for the case+     *      of an ambiguous argument, which makes it tricker to directly test+     *      whether we got here due to a missing argument or ambiguous option.+     */+    case ':':+    case '?':+      opt             = longopts;+      this            = argv[optind-1];+      did_show_banner = 0;++      /* drop the leading '-' from the input command line argument */+      while (*this) {+        if ('-' == *this) {+          ++this;+        } else {+          break;+        }+      }+      prefix = strlen(this);++      /* display any options which are a prefix match for the ambiguous option */+      while (opt->name) {+        if (0 == strncmp(opt->name, this, prefix)) {+          /* only here can we determine if this was a missing argument case */+          if (opt->has_arg == required_argument)+            break;++          /* only show the banner if there are possible matches */+          if (0 == did_show_banner) {+            did_show_banner = 1;+            fprintf(stderr, "Did you mean one of these?\n");+          }+          fprintf(stderr, "    -%s\n", opt->name);+        }+        ++opt;+      }+      break;++    default:+      fprintf(stderr, "failed to process command line options (%d)\n", result);+      abort();+    }+  }++#if !defined(ACCELERATE_DEBUG)+  if (__cmd_line_flags.bitfield & 0x7fffc00) {  // SEE: [layout of command line options bitfield]+    fprintf(stderr, "Data.Array.Accelerate: Debugging options are disabled.\n");+    fprintf(stderr, "Reinstall package 'accelerate' with '-fdebug' to enable them.\n");+  }+#endif+}+++/* This function will be run automatically before main() to process options sent+ * to the Accelerate runtime system.+ *+ * This processes both command line flags as well as those specified via the+ * environment variable "ACCELERATE_FLAGS" (with precedence to the former).+ *+ * The input 'argv' vector is mutated to remove the entries processed by this+ * module. This prevents the flags from interfering with the regular Haskell+ * program (in the same way as the RTS options). Note however that since we can+ * not update the 'argc' length of the vector, the removed entries are simply+ * set to NULL (and moved to the end of the vector).+ */+__attribute__((constructor)) void process_options(int argc, char *argv[])+{+  int i;++  /* Find the command line options which need to be processed. These will be+   * between +ACC ... [-ACC] (similar to the Haskell RTS options).+   *+   * Note that this only recognises a single +ACC ... -ACC group. Should we be+   * able to handle multiple (disjoint) groups of flags? To do this properly we+   * probably want to collect the arguments (from both sources) into a linked+   * list. This would not be particularly difficult, just tedious... \:+   */+  int cl_start;+  int cl_end;+  int num_cl_options = 0;++  for (cl_start = 1; cl_start < argc; ++cl_start) {+    if (0 == strncmp("+ACC", argv[cl_start], 4)) {+      break;+    }+  }++  for (cl_end = cl_start+1; cl_end < argc; ++cl_end) {+    if (0 == strncmp("-ACC", argv[cl_end], 4)) {+      break;+    }+  }+  num_cl_options = cl_end-cl_start-1;++  /* Gather options from the ACCELERATE_FLAGS environment variable. Note that we+   * must not modify this variable, otherwise subsequent invocations of getenv()+   * will get the modified version.+   */+  char *env            = getenv("ACCELERATE_FLAGS");+  int  num_env_options = 0;++  if (NULL != env) {+    /* copy the environment string, as we will mutate it during tokenisation */+    char *p = env = strdup(env);++    /* first count how many tokens there are, so that we can allocate memory for+     * the combined options vector+     */+    while (*p) {+      while (*p && isspace(*p)) ++p;++      if (*p) {+        ++num_env_options;+        while (*p && !isspace(*p)) ++p;+      }+    }+  }++  /* Create the combined options vector containing both the environment and+   * command line options for parsing. The command line options are placed at+   * the end, so that they may override environment options.+   */+  int    argc2 = num_cl_options + num_env_options + 1;+  char** argv2 = NULL;++  if (argc2 > 1) {+    char*  p = env;+    char** r = argv2 = malloc(argc2 * sizeof(char*));++    /* program name */+    *r++ = argv[0];++    /* environment variables */+    if (p) {+      while (*p) {+        while (*p && isspace(*p)) ++p;++        if (*p) {+          *r++ = p;+          while (*p && !isspace(*p)) ++p;++          if (isspace(*p)) {+            *p++ = '\0';+          }+        }+      }+    }++    /* command line flags */+    for (i = cl_start+1; i < cl_end; ++i)+      *r++ = argv[i];++    /* finally process command lines */+    parse_options(argc2, argv2);+  }++  /* Remove the Accelerate options from the command line arguments which will be+   * passed to main(). We can't do this in a sensible fashion by updating argc,+   * but we can pull a small sleight-of-hand by rewriting them to -RTS, so that+   * they will be deleted by the GHC RTS when it is initialised.+   *+   * In this method, we can also updated them in place, without permuting the+   * order of the options to place the (now unused) Accelerate flags at the end+   * of the vector. This does create a slight change in behaviour though, where+   * the application will become more lenient to the user not (correctly)+   * closing the RTS group, for example:+   *+   * > ./foo +RTS -... +ACC -... -ACC+   *+   * is rewritten to:+   *+   * > ./foo +RTS -... -RTS -... -RTS+   *+   * Previously, since the RTS group was not terminated correctly the GHC RTS+   * would complain that the trailing Accelerate options (+ACC -...) were+   * unknown RTS flags.+   */+  for (i = cl_start; i < cl_end+1 && i < argc; ++i) {+    if (strlen(argv[i]) >= 4) {+      strcpy(argv[i], "-RTS");+    } else {+      argv[i][0] = '\0';+    }+  }++  /* cleanup */+  if (argv2) free(argv2);+  if (env)   free(env);+} 
+ cbits/flags.h view
@@ -0,0 +1,52 @@+/*+ * Module      : Data.Array.Accelerate.Debug.Flags+ * Copyright   : [2017..2020] The Accelerate Team+ * License     : BSD3+ *+ * Maintainer  : Trevor L. McDonell <trevor.mcdonell@gmail.com>+ * Stability   : experimental+ * Portability : non-portable (GHC extensions)+ */++#ifndef __ACCELERATE_FLAGS_H__+#define __ACCELERATE_FLAGS_H__++/* NOTE: [layout of command line options bitfield]+ */+typedef union {+  uint32_t bitfield;++  struct {+    uint32_t seq_sharing            : 1;+    uint32_t acc_sharing            : 1;+    uint32_t exp_sharing            : 1;+    uint32_t fusion                 : 1;+    uint32_t simplify               : 1;+    uint32_t inplace                : 1;+    uint32_t fast_math              : 1;+    uint32_t fast_permute_const     : 1;+    uint32_t flush_cache            : 1;+    uint32_t force_recomp           : 1;++    uint32_t debug                  : 1;+    uint32_t verbose                : 1;+    uint32_t dump_phases            : 1;+    uint32_t dump_sharing           : 1;+    uint32_t dump_fusion            : 1;+    uint32_t dump_simpl_stats       : 1;+    uint32_t dump_simpl_iterations  : 1;+    uint32_t dump_vectorisation     : 1;+    uint32_t dump_dot               : 1;+    uint32_t dump_simpl_dot         : 1;+    uint32_t dump_gc                : 1;+    uint32_t dump_gc_stats          : 1;+    uint32_t dump_cc                : 1;+    uint32_t dump_ld                : 1;+    uint32_t dump_asm               : 1;+    uint32_t dump_exec              : 1;+    uint32_t dump_sched             : 1;+  };+} __flags_t;++#endif // __ACCELERATE_FLAGS_H__+
− cbits/flags.inc
@@ -1,336 +0,0 @@-/*- * Module      : Data.Array.Accelerate.Debug.Flags- * Copyright   : [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. This is a translation of the module- * Data.Array.Accelerate.Debug.Flags into C, so that we can implement it at- * program initialisation.- *- * This processes flags between +ACC ... -ACC on the command line. The- * corresponding fields are removed from the command line. Note that we can't at- * this stage update the number of command line arguments, but with some tricks- * they can be mostly deleted.- *- * This is a hack to work around <https://github.com/haskell/cabal/issues/4937>- */--#include <ctype.h>-#include <getopt.h>-#include <libgen.h>-#include <stdint.h>-#include <stdio.h>-#include <stdlib.h>-#include <string.h>---/* These globals will be accessed from the Haskell side to implement the- * corresponding behaviour.- */-int32_t __acc_sharing               = 1;-int32_t __exp_sharing               = 1;-int32_t __fusion                    = 1;-int32_t __simplify                  = 1;-int32_t __unfolding_use_threshold   = 1;-int32_t __fast_math                 = 1;-int32_t __flush_cache               = 0;-int32_t __force_recomp              = 0;-int32_t __debug                     = 0;--int32_t __verbose                   = 0;-int32_t __dump_phases               = 0;-int32_t __dump_sharing              = 0;-int32_t __dump_fusion               = 0;-int32_t __dump_simpl_stats          = 0;-int32_t __dump_simpl_iterations     = 0;-int32_t __dump_vectorisation        = 0;-int32_t __dump_dot                  = 0;-int32_t __dump_simpl_dot            = 0;-int32_t __dump_gc                   = 0;-int32_t __dump_gc_stats             = 0;-int32_t __dump_cc                   = 0;-int32_t __dump_ld                   = 0;-int32_t __dump_asm                  = 0;-int32_t __dump_exec                 = 0;-int32_t __dump_sched                = 0;--#if defined(ACCELERATE_DEBUG)--static const char*         shortopts  = "";-static const struct option longopts[] =-  { { "dverbose",                     no_argument,       &__verbose,               1    }-  , { "ddump-phases",                 no_argument,       &__dump_phases,           1    }-  , { "ddump-sharing",                no_argument,       &__dump_sharing,          1    }-  , { "ddump-fusion",                 no_argument,       &__dump_fusion,           1    }-  , { "ddump-simpl-stats",            no_argument,       &__dump_simpl_stats,      1    }-  , { "ddump-simpl-iterations",       no_argument,       &__dump_simpl_iterations, 1    }-  , { "ddump-vectorisation",          no_argument,       &__dump_vectorisation,    1    }-  , { "ddump-dot",                    no_argument,       &__dump_dot,              1    }-  , { "ddump-simpl-dot",              no_argument,       &__dump_simpl_dot,        1    }-  , { "ddump-gc",                     no_argument,       &__dump_gc,               1    }-  , { "ddump-gc-stats",               no_argument,       &__dump_gc_stats,         1    }-  , { "ddump-cc",                     no_argument,       &__dump_cc,               1    }-  , { "ddump-ld",                     no_argument,       &__dump_ld,               1    }-  , { "ddump-asm",                    no_argument,       &__dump_asm,              1    }-  , { "ddump-exec",                   no_argument,       &__dump_exec,             1    }-  , { "ddump-sched",                  no_argument,       &__dump_sched,            1    }--  , { "facc-sharing",                 no_argument,       &__acc_sharing,           1    }-  , { "fexp-sharing",                 no_argument,       &__exp_sharing,           1    }-  , { "ffusion",                      no_argument,       &__fusion,                1    }-  , { "fsimplify",                    no_argument,       &__simplify,              1    }-  , { "fflush-cache",                 no_argument,       &__flush_cache,           1    }-  , { "fforce-recomp",                no_argument,       &__force_recomp,          1    }-  , { "ffast-math",                   no_argument,       &__fast_math,             1    }-  , { "fdebug",                       no_argument,       &__debug,                 1    }--  , { "fno-acc-sharing",              no_argument,       &__acc_sharing,           0    }-  , { "fno-exp-sharing",              no_argument,       &__exp_sharing,           0    }-  , { "fno-fusion",                   no_argument,       &__fusion,                0    }-  , { "fno-simplify",                 no_argument,       &__simplify,              0    }-  , { "fno-flush-cache",              no_argument,       &__flush_cache,           0    }-  , { "fno-force-recomp",             no_argument,       &__force_recomp,          0    }-  , { "fno-fast-math",                no_argument,       &__fast_math,             0    }-  , { "fno-debug",                    no_argument,       &__debug,                 0    }--  , { "funfolding-use-threshold=INT", required_argument, NULL,                     1000 }--  /* required sentinel */-  , { NULL, 0, NULL, 0 }-  };--#endif /* ACCELERATE_DEBUG */---/* Parse the given vector of command line arguments and set the corresponding- * flags. The vector should contain no non-option arguments (aside from the name- * of the program as the first entry, which is required for getopt()).- */-static void parse_options(int argc, char *argv[])-{-#if defined(ACCELERATE_DEBUG)--  const struct option* opt;-  char* this;-  int   did_show_banner;-  int   prefix;-  int   result;-  int   longindex;--  while (-1 != (result = getopt_long_only(argc, argv, shortopts, longopts, &longindex)))-  {-    switch(result)-    {-    /* the option flag was set */-    case 0:-      break;--    /* attempt to decode the argument to flags which require them */-    case 1000:-      if (1 != sscanf(optarg, "%d", &__unfolding_use_threshold)) {-        fprintf(stderr, "%s: option `-%s' requires an integer argument, but got: %s\n"-                      , basename(argv[0])-                      , longopts[longindex].name-                      , optarg-                      );-      }-      break;--    /* option was ambiguous or was missing a required argument-     *-     * TLM: longindex is not being updated correctly on my system for the case-     *      of an ambiguous argument, which makes it tricker to directly test-     *      whether we got here due to a missing argument or ambiguous option.-     */-    case ':':-    case '?':-      opt             = longopts;-      this            = argv[optind-1];-      did_show_banner = 0;--      /* drop the leading '-' from the input command line argument */-      while (*this) {-        if ('-' == *this) {-          ++this;-        } else {-          break;-        }-      }-      prefix = strlen(this);--      /* display any options which are a prefix match for the ambiguous option */-      while (opt->name) {-        if (0 == strncmp(opt->name, this, prefix)) {-          /* only here can we determine if this was a missing argument case */-          if (opt->has_arg == required_argument)-            break;--          /* only show the banner if there are possible matches */-          if (0 == did_show_banner) {-            did_show_banner = 1;-            fprintf(stderr, "Did you mean one of these?\n");-          }-          fprintf(stderr, "    -%s\n", opt->name);-        }-        ++opt;-      }-      break;--    default:-      fprintf(stderr, "failed to process command line options (%d)\n", result);-      abort();-    }-  }--#else--  fprintf(stderr, "Data.Array.Accelerate: Debugging options are disabled.\n");-  fprintf(stderr, "Reinstall package 'accelerate' with '-fdebug' to enable them.\n");--#endif-}---/* This function will be run automatically before main() to process options sent- * to the Accelerate runtime system.- *- * This processes both command line flags as well as those specified via the- * environment variable "ACCELERATE_FLAGS" (with precedence to the former).- *- * The input 'argv' vector is mutated to remove the entries processed by this- * module. This prevents the flags from interfering with the regular Haskell- * program (in the same way as the RTS options). Note however that since we can- * not update the 'argc' length of the vector, the removed entries are simply- * set to NULL (and moved to the end of the vector).- */-__attribute__((constructor)) void process_options(int argc, char *argv[])-{-  int i;--  /* Find the command line options which need to be processed. These will be-   * between +ACC ... [-ACC] (similar to the Haskell RTS options).-   *-   * Note that this only recognises a single +ACC ... -ACC group. Should we be-   * able to handle multiple (disjoint) groups of flags? To do this properly we-   * probably want to collect the arguments (from both sources) into a linked-   * list. This would not be particularly difficult, just tedious... \:-   */-  int cl_start;-  int cl_end;-  int num_cl_options = 0;--  for (cl_start = 1; cl_start < argc; ++cl_start) {-    if (0 == strncmp("+ACC", argv[cl_start], 4)) {-      break;-    }-  }--  for (cl_end = cl_start+1; cl_end < argc; ++cl_end) {-    if (0 == strncmp("-ACC", argv[cl_end], 4)) {-      break;-    }-  }-  num_cl_options = cl_end-cl_start-1;--  /* Gather options from the ACCELERATE_FLAGS environment variable. Note that we-   * must not modify this variable, otherwise subsequent invocations of getenv()-   * will get the modified version.-   */-  char *env            = getenv("ACCELERATE_FLAGS");-  int  num_env_options = 0;--  if (NULL != env) {-    /* copy the environment string, as we will mutate it during tokenisation */-    char *p = env = strdup(env);--    /* first count how many tokens there are, so that we can allocate memory for-     * the combined options vector-     */-    while (*p) {-      while (*p && isspace(*p)) ++p;--      if (*p) {-        ++num_env_options;-        while (*p && !isspace(*p)) ++p;-      }-    }-  }--  /* Create the combined options vector containing both the environment and-   * command line options for parsing. The command line options are placed at-   * the end, so that they may override environment options.-   */-  int    argc2 = num_cl_options + num_env_options + 1;-  char** argv2 = NULL;--  if (argc2 > 1) {-    char*  p = env;-    char** r = argv2 = malloc(argc2 * sizeof(char*));--    /* program name */-    *r++ = argv[0];--    /* environment variables */-    if (p) {-      while (*p) {-        while (*p && isspace(*p)) ++p;--        if (*p) {-          *r++ = p;-          while (*p && !isspace(*p)) ++p;--          if (isspace(*p)) {-            *p++ = '\0';-          }-        }-      }-    }--    /* command line flags */-    for (i = cl_start+1; i < cl_end; ++i)-      *r++ = argv[i];--    /* finally process command lines */-    parse_options(argc2, argv2);-  }--  /* Remove the Accelerate options from the command line arguments which will be-   * passed to main(). We can't do this in a sensible fashion by updating argc,-   * but we can pull a small sleight-of-hand by rewriting them to -RTS, so that-   * they will be deleted by the GHC RTS when it is initialised.-   *-   * In this method, we can also updated them in place, without permuting the-   * order of the options to place the (now unused) Accelerate flags at the end-   * of the vector. This does create a slight change in behaviour though, where-   * the application will become more lenient to the user not (correctly)-   * closing the RTS group, for example:-   *-   * > ./foo +RTS -... +ACC -... -ACC-   *-   * is rewritten to:-   *-   * > ./foo +RTS -... -RTS -... -RTS-   *-   * Previously, since the RTS group was not terminated correctly the GHC RTS-   * would complain that the trailing Accelerate options (+ACC -...) were-   * unknown RTS flags.-   */-  for (i = cl_start; i < cl_end+1 && i < argc; ++i) {-    if (strlen(argv[i]) >= 4) {-      strcpy(argv[i], "-RTS");-    } else {-      argv[i][0] = '\0';-    }-  }--  /* cleanup */-  if (argv2) free(argv2);-  if (env)   free(env);-}--// vim: filetype=c-
− cbits/flags_debug.c
@@ -1,13 +0,0 @@-/*- * Module      : Data.Array.Accelerate.Debug.Flags- * Copyright   : [2017] Trevor L. McDonell- * License     : BSD3- *- * Maintainer  : Trevor L. McDonell <tmcdonell@cse.unsw.edu.au>- * Stability   : experimental- * Portability : non-portable (GHC extensions)- */--#define ACCELERATE_DEBUG-#include "flags.inc"-
cbits/monitoring.c view
@@ -1,12 +1,142 @@ /*  * Module      : Data.Array.Accelerate.Debug.Monitoring- * Copyright   : [2016..2017] Manuel M T Chakravarty, Gabriele Keller, Trevor L. McDonell+ * Copyright   : [2016..2020] The Accelerate Team  * License     : BSD3  *- * Maintainer  : Trevor L. McDonell <tmcdonell@cse.unsw.edu.au>+ * Maintainer  : Trevor L. McDonell <trevor.mcdonell@gmail.com>  * Stability   : experimental  * Portability : non-portable (GHC extensions)+ *+ * Support for runtime system monitoring+ *+ * This is a hack to work around <https://github.com/haskell/cabal/issues/4937>  */ -#include "monitoring.inc"+#include <inttypes.h>+#include <stdint.h>+#include <stdio.h>++#include "flags.h"+++/* These monitoring counters are globals which will be accessed from the+ * Haskell side.+ */+int64_t __active_ns_llvm_native             = 0;+int64_t __active_ns_llvm_ptx                = 0;++int64_t __current_bytes_remote              = 0;+int64_t __current_bytes_nursery             = 0;++int64_t __total_bytes_allocated_local       = 0;+int64_t __total_bytes_allocated_remote      = 0;+int64_t __total_bytes_copied_to_remote      = 0;+int64_t __total_bytes_copied_from_remote    = 0;+int64_t __total_bytes_evicted_from_remote   = 0;+int64_t __num_remote_gcs                    = 0;+int64_t __num_evictions                     = 0;++/* cbits/flags.c */+extern __flags_t __cmd_line_flags;++#if defined(ACCELERATE_DEBUG)++/* cbits/clock.c */+double clock_gettime_elapsed_seconds(void);++/*+ * Format a large number, using comma separators.+ */+static char* format_int64(char *buffer, int64_t x)+{+  char *s = buffer;++  if (x < 0)+  {+    *s++  = '-';+    x     = -x;+  }++  if (x < 1000)+  {+    sprintf(s, "%"PRIi64, x);+  }+  else if (x < 1000000)+  {+    sprintf(s, "%"PRIi64",%03"PRIi64, x/1000, x%1000);+  }+  else if (x < 1000000000)+  {+    sprintf(s, "%"PRIi64",%03"PRIi64",%03"PRIi64+             ,  x/1000000+             , (x/1000)%1000+             ,  x%1000);+  }+  else if (x < 1000000000000)+  {+    sprintf(s, "%"PRIi64",%03"PRIi64",%03"PRIi64",%03"PRIi64+             ,  x/1000000000+             , (x/1000000)%1000+             , (x/1000)%1000+             ,  x%1000);+  }+  else if (x < 1000000000000000)+  {+    sprintf(s, "%"PRIi64",%03"PRIi64",%03"PRIi64",%03"PRIi64",%03"PRIi64+             ,  x/1000000000000+             , (x/1000000000)%1000+             , (x/1000000)%1000+             , (x/1000)%1000+             ,  x%1000);+  }+  else if (x < 1000000000000000000)+  {+    sprintf(s, "%"PRIi64",%03"PRIi64",%03"PRIi64",%03"PRIi64",%03"PRIi64",%03"PRIi64+             ,  x/1000000000000000+             , (x/1000000000000)%1000+             , (x/1000000000)%1000+             , (x/1000000)%1000+             , (x/1000)%1000+             ,  x%1000);+  }+  else+  {+    sprintf(s, "%"PRIi64",%03"PRIi64",%03"PRIi64",%03"PRIi64",%03"PRIi64",%03"PRIi64",%03"PRIi64+             ,  x/1000000000000000000+             , (x/1000000000000000)%1000+             , (x/1000000000000)%1000+             , (x/1000000000)%1000+             , (x/1000000)%1000+             , (x/1000)%1000+             ,  x%1000);+  }++  return buffer;+}++/*+ * This function runs after main(), and is used to print final GC and memory+ * statistics (if enabled). This is similar to the +RTS -s option.+ */+__attribute__((destructor)) void dump_gc_stats(void)+{+  if (__cmd_line_flags.dump_gc_stats) {+    /*+     * int64 ranges from -9223372036854775807..9223372036854775807, so we need a+     * buffer size of at least 27 characters (including the terminating \0) to+     * format any number with commas.+     */+    char buffer[96];+    double timestamp = clock_gettime_elapsed_seconds();++    fprintf(stderr, "\n");+    fprintf(stderr, "[%8.3f] gc: %s bytes allocated locally\n", timestamp, format_int64(buffer, __total_bytes_allocated_local));+    fprintf(stderr, "[%8.3f] gc: %s bytes allocated on the remote device\n", timestamp, format_int64(buffer, __total_bytes_allocated_remote));+    fprintf(stderr, "[%8.3f] gc: %s bytes copied to the remote device\n", timestamp, format_int64(buffer, __total_bytes_copied_to_remote));+    fprintf(stderr, "[%8.3f] gc: %s bytes copied from the remote device\n", timestamp, format_int64(buffer, __total_bytes_copied_from_remote));+    fprintf(stderr, "[%8.3f] gc: %s bytes evicted from the remote (%s evictions, %s GCs)\n", timestamp, format_int64(&buffer[0], __total_bytes_evicted_from_remote), format_int64(&buffer[32], __num_evictions), format_int64(&buffer[64], __num_remote_gcs));+  }+}++#endif /* ACCELERATE_DEBUG */ 
− cbits/monitoring.inc
@@ -1,141 +0,0 @@-/*- * 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)- *- * Support for runtime system monitoring- *- * This is a hack to work around <https://github.com/haskell/cabal/issues/4937>- */--#include <stdint.h>-#include <stdio.h>---/* These monitoring counters are globals which will be accessed from the- * Haskell side.- */-int64_t __active_ns_llvm_native             = 0;-int64_t __active_ns_llvm_ptx                = 0;--int64_t __current_bytes_remote              = 0;-int64_t __current_bytes_nursery             = 0;--int64_t __total_bytes_allocated_local       = 0;-int64_t __total_bytes_allocated_remote      = 0;-int64_t __total_bytes_copied_to_remote      = 0;-int64_t __total_bytes_copied_from_remote    = 0;-int64_t __total_bytes_evicted_from_remote   = 0;-int64_t __num_remote_gcs                    = 0;-int64_t __num_evictions                     = 0;--extern int32_t __dump_gc;-extern int32_t __dump_gc_stats;--#if defined(ACCELERATE_DEBUG)--/* cbits/clock.c */-double clock_gettime_elapsed_seconds(void);--/*- * Format a large number, using comma separators.- */-static char* format_int64(char *buffer, int64_t x)-{-  char *s = buffer;--  if (x < 0)-  {-    *s++  = '-';-    x     = -x;-  }--  if (x < 1000)-  {-    sprintf(s, "%lld", x);-  }-  else if (x < 1000000)-  {-    sprintf(s, "%lld,%03lld", x/1000, x%1000);-  }-  else if (x < 1000000000)-  {-    sprintf(s, "%lld,%03lld,%03lld"-             ,  x/1000000-             , (x/1000)%1000-             ,  x%1000);-  }-  else if (x < 1000000000000)-  {-    sprintf(s, "%lld,%03lld,%03lld,%03lld"-             ,  x/1000000000-             , (x/1000000)%1000-             , (x/1000)%1000-             ,  x%1000);-  }-  else if (x < 1000000000000000)-  {-    sprintf(s, "%lld,%03lld,%03lld,%03lld,%03lld"-             ,  x/1000000000000-             , (x/1000000000)%1000-             , (x/1000000)%1000-             , (x/1000)%1000-             ,  x%1000);-  }-  else if (x < 1000000000000000000)-  {-    sprintf(s, "%lld,%03lld,%03lld,%03lld,%03lld,%03lld"-             ,  x/1000000000000000-             , (x/1000000000000)%1000-             , (x/1000000000)%1000-             , (x/1000000)%1000-             , (x/1000)%1000-             ,  x%1000);-  }-  else-  {-    sprintf(s, "%lld,%03lld,%03lld,%03lld,%03lld,%03lld,%03lld"-             ,  x/1000000000000000000-             , (x/1000000000000000)%1000-             , (x/1000000000000)%1000-             , (x/1000000000)%1000-             , (x/1000000)%1000-             , (x/1000)%1000-             ,  x%1000);-  }--  return buffer;-}--/*- * This function runs after main(), and is used to print final GC and memory- * statistics (if enabled). This is similar to the +RTS -s option.- */-__attribute__((destructor)) void dump_gc_stats(void)-{-  if (__dump_gc_stats) {-    /*-     * int64 ranges from -9223372036854775807..9223372036854775807, so we need a-     * buffer size of at least 27 characters (including the terminating \0) to-     * format any numbers with commas.-     */-    char buffer[96];-    double timestamp = clock_gettime_elapsed_seconds();--    printf("\n");-    printf("[%8.3f] gc: %s bytes allocated locally\n", timestamp, format_int64(buffer, __total_bytes_allocated_local));-    printf("[%8.3f] gc: %s bytes allocated on the remote device\n", timestamp, format_int64(buffer, __total_bytes_allocated_remote));-    printf("[%8.3f] gc: %s bytes copied to the remote device\n", timestamp, format_int64(buffer, __total_bytes_copied_to_remote));-    printf("[%8.3f] gc: %s bytes copied from the remote device\n", timestamp, format_int64(buffer, __total_bytes_copied_from_remote));-    printf("[%8.3f] gc: %s bytes evicted from the remote (%s evictions, %s GCs)\n", timestamp, format_int64(&buffer[0], __total_bytes_evicted_from_remote), format_int64(&buffer[32], __num_evictions), format_int64(&buffer[64], __num_remote_gcs));-  }-}--#endif /* ACCELERATE_DEBUG */--// vim: filetype=c-
− cbits/monitoring_debug.c
@@ -1,13 +0,0 @@-/*- * 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)- */--#define ACCELERATE_DEBUG-#include "monitoring.inc"-
+ images/accelerate-logo-text-v.png view

binary file changed (absent → 207024 bytes)

src/Data/Array/Accelerate.hs view
@@ -1,12 +1,13 @@+{-# LANGUAGE PatternSynonyms     #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TypeApplications    #-} -- | -- Module      : Data.Array.Accelerate--- Copyright   : [2008..2017] Manuel M T Chakravarty, Gabriele Keller---               [2009..2017] Trevor L. McDonell---               [2013..2017] Robert Clifton-Everest---               [2014..2014] Frederik M. Madsen+-- Description : The Accelerate standard prelude+-- Copyright   : [2008..2020] The Accelerate Team -- License     : BSD3 ----- Maintainer  : Trevor L. McDonell <tmcdonell@cse.unsw.edu.au>+-- Maintainer  : Trevor L. McDonell <trevor.mcdonell@gmail.com> -- Stability   : experimental -- Portability : non-portable (GHC extensions) --@@ -84,7 +85,7 @@ -- --      - For more information on LULESH: <https://codesign.llnl.gov/lulesh.php>. -----      <<https://codesign.llnl.gov/images/sedov-3d-LLNL.png>>+--      <<https://i.imgur.com/bIkODKd.jpg>> -- -- [/Starting a new project:/] --@@ -109,6 +110,12 @@ -- * <https://hackage.haskell.org/package/accelerate-bignum accelerate-bignum>: -- Fixed-width large integer arithmetic. --+-- * <https://hackage.haskell.org/package/containers-accelerate containers-accelerate>:+-- Container types for use with Accelerate.+--+-- * <https://hackage.haskell.org/package/hashable-accelerate hashable-accelerate>:+-- Class for types which can be converted to a value.+-- -- * <https://hackage.haskell.org/package/colour-accelerate colour-accelerate>: -- Colour representations in Accelerate (RGB, sRGB, HSV, and HSL). --@@ -139,10 +146,7 @@ -- -- * 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>+-- * Maintainer: Trevor L. McDonell: <mailto:trevor.mcdonell@gmail.com> -- -- [/Tip:/] --@@ -200,6 +204,9 @@   -- *** Concatenation   (++), concatOn, +  -- *** Expansion+  expand,+   -- ** Composition   -- *** Flow control   (?|), acond, awhile,@@ -239,7 +246,6 @@   -- *** Permutations   -- **** Forward permutation (scatter)   permute,-  ignore,   scatter,    -- **** Backward permutation (gather)@@ -251,13 +257,14 @@   reverseOn, transposeOn,    -- *** Filtering-  filter,+  filter, compact,    -- ** Folding   fold, fold1, foldAll, fold1All,    -- *** Segmented reductions-  foldSeg, fold1Seg,+  foldSeg,  fold1Seg,+  foldSeg', fold1Seg',    -- *** Specialised reductions   all, any, and, or, sum, product, minimum, maximum,@@ -301,17 +308,20 @@   -- ** Scalar data types   Exp, +  -- ** SIMD vectors+  Vec, VecElt,+   -- ** Type classes   -- *** Basic type classes   Eq(..),-  Ord(..), Ordering(..),+  Ord(..), Ordering(..), pattern LT_, pattern EQ_, pattern GT_,   Enum, succ, pred,   Bounded, minBound, maxBound,    -- *** Numeric type classes   Num, (+), (-), (*), negate, abs, signum, fromInteger,-  -- Real, -- vacuous   Integral, quot, rem, div, mod, quotRem, divMod,+  Rational(..),   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',@@ -328,6 +338,26 @@   lift1, lift2, lift3,   ilift1, ilift2, ilift3, +  -- ** Pattern synonyms+  -- $pattern_synonyms+  --+  pattern Pattern,+  pattern T2,  pattern T3,  pattern T4,  pattern T5,  pattern T6,+  pattern T7,  pattern T8,  pattern T9,  pattern T10, pattern T11,+  pattern T12, pattern T13, pattern T14, pattern T15, pattern T16,++  pattern Z_, pattern Ix, pattern (::.),+  pattern I0, pattern I1, pattern I2, pattern I3, pattern I4,+  pattern I5, pattern I6, pattern I7, pattern I8, pattern I9,++  pattern Vec2, pattern V2,+  pattern Vec3, pattern V3,+  pattern Vec4, pattern V4,+  pattern Vec8, pattern V8,+  pattern Vec16, pattern V16,++  mkPattern, mkPatterns,+   -- ** Scalar operations   -- *** Introduction   constant,@@ -336,7 +366,7 @@   fst, afst, snd, asnd, curry, uncurry,    -- *** Flow control-  (?), caseof, cond, while, iterate,+  (?), match, cond, while, iterate,    -- *** Scalar reduction   sfoldl,@@ -378,36 +408,49 @@   fromList, toList,    -- ----------------------------------------------------------------------------  -- * Prelude re-exports-  (.), ($), error, undefined, const,+  -- * Useful re-exports+  (.), ($), (&), error, undefined, const, otherwise,+  Show, Generic, HasCallStack,    -- ---------------------------------------------------------------------------   -- Types   Int, Int8, Int16, Int32, Int64,   Word, Word8, Word16, Word32, Word64,   Half(..), Float, Double,-  Bool(..), Char,+  Bool(..), pattern True_, pattern False_,+  Maybe(..), pattern Nothing_, pattern Just_,+  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.Array.Sugar                            hiding ( (!), (!!), rank, shape, reshape, size, toIndex, fromIndex, intersect, ignore ) import Data.Array.Accelerate.Classes+import Data.Array.Accelerate.Data.Maybe import Data.Array.Accelerate.Language+import Data.Array.Accelerate.Pattern+import Data.Array.Accelerate.Pattern.TH import Data.Array.Accelerate.Prelude-import Data.Array.Accelerate.Trafo                                  () -- show instances+import Data.Array.Accelerate.Pretty                                 () -- show instances+import Data.Array.Accelerate.Smart+import Data.Array.Accelerate.Sugar.Array                            ( Array, Arrays, Scalar, Vector, Matrix, Segments, fromFunction, fromFunctionM, toList, fromList )+import Data.Array.Accelerate.Sugar.Elt+import Data.Array.Accelerate.Sugar.Shape                            hiding ( size, toIndex, fromIndex, intersect )+import Data.Array.Accelerate.Sugar.Vec import Data.Array.Accelerate.Type-import qualified Data.Array.Accelerate.Array.Sugar                  as S+import Data.Primitive.Vec+import qualified Data.Array.Accelerate.Sugar.Array                  as S+import qualified Data.Array.Accelerate.Sugar.Shape                  as S -import Prelude                                                      ( (.), ($), undefined, error, const )+import Data.Function                                                ( (&) )+import Prelude                                                      ( (.), ($), Char, Show, undefined, error, const, otherwise ) +import GHC.Generics                                                 ( Generic )+import GHC.Stack++ -- $setup -- >>> :seti -XTypeOperators -- >>> import Data.Array.Accelerate.Interpreter@@ -425,34 +468,40 @@  -- | Array indexing in plain Haskell code. ---indexArray :: Array sh e -> sh -> e+{-# INLINE indexArray #-}+indexArray :: (Shape sh, Elt e) => Array sh e -> sh -> e indexArray = (S.!)  -- | Linear array indexing in plain Haskell code. ---linearIndexArray :: Array sh e -> Int -> e+{-# INLINE linearIndexArray #-}+linearIndexArray :: Elt e => Array sh e -> Int -> e linearIndexArray = (S.!!) --- | Rank of an array.+-- | Rank of an array (as a plain Haskell value) ---arrayRank :: Shape sh => sh -> Int-arrayRank = S.rank+{-# INLINE arrayRank #-}+arrayRank :: forall sh e. Shape sh => Array sh e -> Int+arrayRank _ = S.rank @sh --- |Array shape in plain Haskell code.+-- | Shape of an array (as a plain Haskell value) --+{-# INLINE arrayShape #-} 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'.+-- | Total number of elements in an array (as a plain Haskell value) ---arraySize :: Shape sh => sh -> Int-arraySize = S.size+{-# INLINE arraySize #-}+arraySize :: Shape sh => Array sh e -> Int+arraySize = S.size . S.shape  -- | Change the shape of an array without altering its contents. The 'arraySize' -- of the source and result arrays must be identical. ---arrayReshape :: (Shape sh, Shape sh', Elt e) => sh -> Array sh' e -> Array sh e+{-# INLINE arrayReshape #-}+arrayReshape :: (Shape sh, Shape sh') => sh -> Array sh' e -> Array sh e arrayReshape = S.reshape  @@ -549,6 +598,61 @@ -- > 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+--+-- For an alternative, see section <#pattern_synonyms Pattern synonyms>.+--++-- $pattern_synonyms+-- #pattern_synonyms#+--+-- Pattern synonyms can be used as an alternative to 'lift' and 'unlift' for+-- constructing and accessing data types isomorphic to simple product (tuple)+-- types.+--+-- In contrast to 'lift' and 'unlift' however, pattern synonyms do /not/ require+-- these data types to be fully polymorphic.+--+-- For example, let's say we have regular Haskell data type representing a point+-- in two-dimensional space:+--+-- > data Point = Point_ Float Float+-- >   deriving (Generic, Elt)+--+-- Here we derive instance an instance of the 'Elt' class (via 'Generic'),+-- so that this data type can be used within scalar Accelerate expressions+--+-- In order to access the individual fields of the data constructor from within+-- an Accelerate expression, we define the following pattern synonym:+--+-- > pattern Point :: Exp Float -> Exp Float -> Exp Point+-- > pattern Point x y = Pattern (x,y)+--+-- Notice how we named the constructor of our original datatype with a trailing+-- underscore, so that we can use the undecorated name for the pattern synonym;+-- these must have unique names.+--+-- In essence, the 'Pattern' pattern is really telling GHC how to treat our @Point@+-- type as a regular pair for use in Accelerate code. The pattern can then be+-- used on both the left and right hand side of an expression:+--+-- > addPoint :: Exp Point -> Exp Point -> Exp Point+-- > addPoint (Point x1 y1) (Point x2 y2) = Point (x1+x2) (y1+y2)+--+-- Similarly, we can define pattern synonyms for values in 'Acc'. We can also+-- use record syntax to generate field accessors, if we desire:+--+-- > data SparseVector a = SparseVector_ (Vector Int) (Vector a)+-- >   deriving (Generic, Arrays)+-- >+-- > pattern SparseVector :: Elt a => Acc (Vector Int) -> Acc (Vector a) -> Acc (SparseVector a)+-- > pattern SparseVector { indices, values } = Pattern (indices, values)+--+-- For convenience, we have defined several pattern synonyms for regular tuples,+-- 'T2' (for pairs), 'T3' (for triples), and so on up to 'T16'. These are+-- occasionally more convenient to use than 'lift' and 'unlift' together with+-- the regular tuple syntax.+--+-- @since 1.3.0.0 --  -- $getting_data_in
src/Data/Array/Accelerate/AST.hs view
@@ -1,1931 +1,1420 @@ {-# LANGUAGE BangPatterns          #-}-{-# LANGUAGE CPP                   #-}-{-# LANGUAGE DeriveDataTypeable    #-}-{-# LANGUAGE FlexibleContexts      #-}-{-# LANGUAGE FlexibleInstances     #-}-{-# LANGUAGE GADTs                 #-}-{-# LANGUAGE MultiParamTypeClasses #-}-{-# LANGUAGE QuasiQuotes           #-}-{-# LANGUAGE RankNTypes            #-}-{-# LANGUAGE ScopedTypeVariables   #-}-{-# LANGUAGE StandaloneDeriving    #-}-{-# LANGUAGE TemplateHaskell       #-}-{-# LANGUAGE TypeFamilies          #-}-{-# LANGUAGE TypeOperators         #-}-{-# LANGUAGE TypeSynonymInstances  #-}-{-# OPTIONS_HADDOCK hide #-}--- |--- Module      : Data.Array.Accelerate.AST--- 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  : Trevor L. McDonell <tmcdonell@cse.unsw.edu.au>--- Stability   : experimental--- Portability : non-portable (GHC extensions)------ /Scalar versus collective operations/------ The embedded array processing language is a two-level language.  It--- combines a language of scalar expressions and functions with a language of--- collective array operations.  Scalar expressions are used to compute--- arguments for collective operations and scalar functions are used to--- parametrise higher-order, collective array operations.  The two-level--- structure, in particular, ensures that collective operations cannot be--- parametrised with collective operations; hence, we are following a flat--- data-parallel model.  The collective operations manipulate--- multi-dimensional arrays whose shape is explicitly tracked in their types.--- In fact, collective operations cannot produce any values other than--- multi-dimensional arrays; when they yield a scalar, this is in the form of--- a 0-dimensional, singleton array.  Similarly, scalar expression can -as--- their name indicates- only produce tuples of scalar, but not arrays.------ There are, however, two expression forms that take arrays as arguments.  As--- a result scalar and array expressions are recursively dependent.  As we--- cannot and don't want to compute arrays in the middle of scalar--- computations, array computations will always be hoisted out of scalar--- expressions.  So that this is always possible, these array expressions may--- not contain any free scalar variables.  To express that condition in the--- type structure, we use separate environments for scalar and array variables.------ /Programs/------ Collective array programs comprise closed expressions of array operations.--- There is no explicit sharing in the initial AST form, but sharing is--- introduced subsequently by common subexpression elimination and floating--- of array computations.------ /Functions/------ The array expression language is first-order and only provides limited--- control structures to ensure that it can be efficiently executed on--- compute-acceleration hardware, such as GPUs.  To restrict functions to--- first-order, we separate function abstraction from the main expression--- type.  Functions are represented using de Bruijn indices.------ /Parametric and ad-hoc polymorphism/------ The array language features paramatric polymophism (e.g., pairing and--- projections) as well as ad-hoc polymorphism (e.g., arithmetic operations).--- All ad-hoc polymorphic constructs include reified dictionaries (c.f.,--- module 'Types').  Reified dictionaries also ensure that constants--- (constructor 'Const') are representable on compute acceleration hardware.------ The AST contains both reified dictionaries and type class constraints.--- Type classes are used for array-related functionality that is uniformly--- available for all supported types.  In contrast, reified dictionaries are--- used for functionality that is only available for certain types, such as--- arithmetic operations.-----module Data.Array.Accelerate.AST (--  -- * Typed de Bruijn indices-  Idx(..), idxToInt, tupleIdxToInt,--  -- * Valuation environment-  Val(..), ValElt(..), prj, prjElt,--  -- * Accelerated array expressions-  PreOpenAfun(..), OpenAfun, PreAfun, Afun, PreOpenAcc(..), OpenAcc(..), Acc,-  PreBoundary(..), Boundary, 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,-  rnfArrays,--  -- TemplateHaskell-  LiftAcc,-  liftIdx, liftTupleIdx, liftArrays,-  liftConst, liftSliceIndex, liftPrimConst, liftPrimFun,-  liftPreOpenAfun, liftPreOpenAcc, liftPreOpenFun, liftPreOpenExp,--  -- debugging-  showPreAccOp, showPreExpOp,--) where----standard library-import Control.DeepSeq-import Data.List-import Data.Typeable-import Foreign.ForeignPtr-import Foreign.Marshal-import Foreign.Ptr-import Foreign.Storable-import System.IO.Unsafe-import GHC.Ptr                                                      ( Ptr(..) )-import Language.Haskell.TH                                          ( Q, TExp )-import qualified Language.Haskell.TH                                as TH-import qualified Language.Haskell.TH.Syntax                         as TH-#if __GLASGOW_HASKELL__ <= 708-import Instances.TH.Lift                                            () -- Int8, Int16...-#endif---- friends-import Data.Array.Accelerate.Array.Data-import Data.Array.Accelerate.Array.Representation                   ( SliceIndex(..), size )-import Data.Array.Accelerate.Array.Sugar                            hiding ( size )-import Data.Array.Accelerate.Array.Unique-import Data.Array.Accelerate.Product-import Data.Array.Accelerate.Type-#if __GLASGOW_HASKELL__ < 800-import Data.Array.Accelerate.Error-#endif----- Typed de Bruijn indices--- --------------------------- De Bruijn variable index projecting a specific type from a type--- environment.  Type environments are nested pairs (..((), t1), t2, ..., tn).----data Idx env t where-  ZeroIdx ::              Idx (env, t) t-  SuccIdx :: Idx env t -> Idx (env, s) t---- de Bruijn Index to Int conversion----idxToInt :: Idx env t -> Int-idxToInt ZeroIdx       = 0-idxToInt (SuccIdx idx) = 1 + idxToInt idx--tupleIdxToInt :: TupleIdx tup e -> Int-tupleIdxToInt ZeroTupIdx       = 0-tupleIdxToInt (SuccTupIdx idx) = 1 + tupleIdxToInt idx----- Environments--- ---------------- Valuation for an environment----data Val env where-  Empty :: Val ()-  Push  :: Val env -> t -> Val (env, t)--deriving instance Typeable Val---- Valuation for an environment of array elements----data ValElt env where-  EmptyElt :: ValElt ()-  PushElt  :: Elt t-           => ValElt env -> EltRepr t -> ValElt (env, t)---- Projection of a value from a valuation using a de Bruijn index----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) = toElt v-prjElt (SuccIdx idx) (PushElt val _) = prjElt idx val-#if __GLASGOW_HASKELL__ < 800-prjElt _             _               = $internalError "prjElt" "inconsistent valuation"-#endif---- Array expressions--- --------------------- |Function abstraction over parametrised array computations----data PreOpenAfun acc aenv t where-  Abody :: Arrays t => acc             aenv      t -> PreOpenAfun acc aenv t-  Alam  :: Arrays a => PreOpenAfun acc (aenv, a) t -> PreOpenAfun acc aenv (a -> t)---- Function abstraction over vanilla open array computations----type OpenAfun = PreOpenAfun OpenAcc---- |Parametrised array-computation function without free array variables----type PreAfun acc = PreOpenAfun acc ()---- |Vanilla array-computation function without free array variables----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.------ * Scalar functions and expressions embedded in well-formed array---   computations cannot contain free scalar variable indices.  The latter---   cannot be bound in array computations, and hence, cannot appear in any---   well-formed program.------ * The let-form is used to represent the sharing discovered by common---   subexpression elimination as well as to control evaluation order.  (We---   need to hoist array expressions out of scalar expressions - they occur in---   scalar indexing and in determining an arrays shape.)------ The data type is parameterised over the surface types (not the representation--- type).------ We use a non-recursive variant parametrised over the recursive closure, to facilitate attribute--- calculation in the backend.----data PreOpenAcc acc aenv a where--  -- Local binding to represent sharing and demand explicitly; this is an-  -- eager(!) binding-  Alet        :: (Arrays bndArrs, Arrays bodyArrs)-              => acc            aenv            bndArrs         -- bound expression-              -> acc            (aenv, bndArrs) bodyArrs        -- the bound expression scope-              -> PreOpenAcc acc aenv            bodyArrs--  -- Variable bound by a 'Let', represented by a de Bruijn index-  Avar        :: Arrays arrs-              => Idx            aenv arrs-              -> PreOpenAcc acc aenv arrs--  -- Tuples of arrays-  Atuple      :: (Arrays arrs, IsAtuple arrs)-              => Atuple    (acc aenv) (TupleRepr arrs)-              -> PreOpenAcc acc aenv  arrs--  Aprj        :: (Arrays arrs, IsAtuple arrs, Arrays a)-              => TupleIdx (TupleRepr arrs) a-              ->            acc aenv arrs-              -> PreOpenAcc acc aenv a--  -- Array-function application.-  ---  -- The array function is not closed at the core level because we need access-  -- to free variables introduced by 'run1' style evaluators. See Issue#95.-  ---  Apply       :: (Arrays arrs1, Arrays arrs2)-              => PreOpenAfun acc aenv (arrs1 -> arrs2)-              -> acc             aenv arrs1-              -> PreOpenAcc  acc aenv arrs2--  -- 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 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-              => PreExp     acc aenv Bool-              -> acc            aenv arrs-              -> acc            aenv arrs-              -> PreOpenAcc acc aenv arrs--  -- Value-recursion for array-level computations-  Awhile      :: Arrays arrs-              => PreOpenAfun acc aenv (arrs -> Scalar Bool)     -- continue iteration while true-              -> PreOpenAfun acc aenv (arrs -> arrs)            -- function to iterate-              -> acc             aenv arrs                      -- initial value-              -> PreOpenAcc  acc aenv arrs---  -- Array inlet (triggers async host->device transfer if necessary)-  Use         :: Arrays arrs-              => ArrRepr arrs-              -> PreOpenAcc acc aenv arrs--  -- Capture a scalar (or a tuple of scalars) in a singleton array-  Unit        :: Elt e-              => PreExp     acc aenv e-              -> PreOpenAcc acc aenv (Scalar e)--  -- Change the shape of an array without altering its contents-  -- > precondition: size dim == size dim'-  Reshape     :: (Shape sh, Shape sh', Elt e)-              => PreExp     acc aenv sh                         -- new shape-              -> acc            aenv (Array sh' e)              -- array to be reshaped-              -> PreOpenAcc acc aenv (Array sh e)--  -- Construct a new array by applying a function to each index.-  Generate    :: (Shape sh, Elt e)-              => PreExp     acc aenv sh                         -- output shape-              -> PreFun     acc aenv (sh -> e)                  -- representation function-              -> PreOpenAcc acc aenv (Array sh e)--  -- Hybrid map/backpermute, where we separate the index and value-  -- transformations.-  Transform   :: (Elt a, Elt b, Shape sh, Shape sh')-              => PreExp     acc aenv sh'                        -- dimension of the result-              -> PreFun     acc aenv (sh' -> sh)                -- index permutation function-              -> PreFun     acc aenv (a   -> b)                 -- function to apply at each element-              ->            acc aenv (Array sh  a)              -- source array-              -> PreOpenAcc acc aenv (Array sh' b)--  -- Replicate an array across one or more dimensions as given by the first-  -- argument-  Replicate   :: (Shape sh, Shape sl, Elt slix, Elt e)-              => SliceIndex (EltRepr slix)                      -- slice type specification-                            (EltRepr sl)-                            co-                            (EltRepr sh)-              -> PreExp     acc aenv slix                       -- slice value specification-              -> acc            aenv (Array sl e)               -- data to be replicated-              -> PreOpenAcc acc aenv (Array sh e)--  -- Index a sub-array out of an array; i.e., the dimensions not indexed are-  -- returned whole-  Slice       :: (Shape sh, Shape sl, Elt slix, Elt e)-              => SliceIndex (EltRepr slix)                      -- slice type specification-                            (EltRepr sl)-                            co-                            (EltRepr sh)-              -> acc            aenv (Array sh e)               -- array to be indexed-              -> PreExp     acc aenv slix                       -- slice value specification-              -> PreOpenAcc acc aenv (Array sl e)--  -- Apply the given unary function to all elements of the given array-  Map         :: (Shape sh, Elt e, Elt e')-              => PreFun     acc aenv (e -> e')-              -> acc            aenv (Array sh e)-              -> PreOpenAcc acc aenv (Array sh e')--  -- Apply a given binary function pairwise to all elements of the given arrays.-  -- The length of the result is the length of the shorter of the two argument-  -- arrays.-  ZipWith     :: (Shape sh, Elt e1, Elt e2, Elt e3)-              => PreFun     acc aenv (e1 -> e2 -> e3)-              -> acc            aenv (Array sh e1)-              -> acc            aenv (Array sh e2)-              -> PreOpenAcc acc aenv (Array sh e3)--  -- Fold along the innermost dimension of an array with a given /associative/ function.-  Fold        :: (Shape sh, Elt e)-              => PreFun     acc aenv (e -> e -> e)              -- combination function-              -> PreExp     acc aenv e                          -- default value-              -> acc            aenv (Array (sh:.Int) e)        -- folded array-              -> PreOpenAcc acc aenv (Array sh e)--  -- 'Fold' without a default value-  Fold1       :: (Shape sh, Elt e)-              => PreFun     acc aenv (e -> e -> e)              -- combination function-              -> acc            aenv (Array (sh:.Int) e)        -- folded array-              -> PreOpenAcc acc aenv (Array sh e)--  -- Segmented fold along the innermost dimension of an array with a given /associative/ function-  FoldSeg     :: (Shape sh, Elt e, Elt i, IsIntegral i)-              => PreFun     acc aenv (e -> e -> e)              -- combination function-              -> PreExp     acc aenv e                          -- default value-              -> acc            aenv (Array (sh:.Int) e)        -- folded array-              -> acc            aenv (Segments i)               -- segment descriptor-              -> PreOpenAcc acc aenv (Array (sh:.Int) e)--  -- 'FoldSeg' without a default value-  Fold1Seg    :: (Shape sh, Elt e, Elt i, IsIntegral i)-              => PreFun     acc aenv (e -> e -> e)              -- combination function-              -> acc            aenv (Array (sh:.Int) e)        -- folded array-              -> acc            aenv (Segments i)               -- segment descriptor-              -> PreOpenAcc acc aenv (Array (sh:.Int) e)--  -- 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       :: (Shape sh, Elt e)-              => PreFun     acc aenv (e -> e -> e)              -- combination function-              -> PreExp     acc aenv e                          -- initial value-              -> acc            aenv (Array (sh:.Int) e)-              -> PreOpenAcc acc aenv (Array (sh:.Int) e)--  -- 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'      :: (Shape sh, Elt e)-              => PreFun     acc aenv (e -> e -> e)              -- combination function-              -> PreExp     acc aenv e                          -- initial value-              -> acc            aenv (Array (sh:.Int) e)-              -> PreOpenAcc acc aenv (Array (sh:.Int) e, Array sh e)--  -- Haskell-style scan without an initial value-  Scanl1      :: (Shape sh, Elt e)-              => PreFun     acc aenv (e -> e -> e)              -- combination function-              -> acc            aenv (Array (sh:.Int) e)-              -> PreOpenAcc acc aenv (Array (sh:.Int) e)--  -- Right-to-left version of 'Scanl'-  Scanr       :: (Shape sh, Elt e)-              => PreFun     acc aenv (e -> e -> e)              -- combination function-              -> PreExp     acc aenv e                          -- initial value-              -> acc            aenv (Array (sh:.Int) e)-              -> PreOpenAcc acc aenv (Array (sh:.Int) e)--  -- Right-to-left version of 'Scanl\''-  Scanr'      :: (Shape sh, Elt e)-              => PreFun     acc aenv (e -> e -> e)              -- combination function-              -> PreExp     acc aenv e                          -- initial value-              -> acc            aenv (Array (sh:.Int) e)-              -> PreOpenAcc acc aenv (Array (sh:.Int) e, Array sh e)--  -- Right-to-left version of 'Scanl1'-  Scanr1      :: (Shape sh, Elt e)-              => PreFun     acc aenv (e -> e -> e)              -- combination function-              -> 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-  -- the output. The permutation can be between arrays of varying shape and-  -- dimensionality.-  ---  -- Other characteristics of the permutation function 'f':-  ---  --   1. 'f' is a partial function: if it evaluates to the magic value 'ignore'-  --      (i.e. a tuple of -1 values) then those elements of the domain are-  --      dropped.-  ---  --   2. 'f' is not surjective: positions in the target array need not be-  --      picked up by the permutation function, so the target array must first-  --      be initialised from an array of default values.-  ---  --   3. 'f' is not injective: distinct elements of the domain may map to the-  --      same position in the target array. In this case the combination-  --      function is used to combine elements, which needs to be /associative/-  --      and /commutative/.-  ---  Permute     :: (Shape sh, Shape sh', Elt e)-              => PreFun     acc aenv (e -> e -> e)              -- combination function-              -> acc            aenv (Array sh' e)              -- default values-              -> PreFun     acc aenv (sh -> sh')                -- permutation function-              -> acc            aenv (Array sh e)               -- source array-              -> PreOpenAcc acc aenv (Array sh' e)--  -- Generalised multi-dimensional backwards permutation; the permutation can-  -- be between arrays of varying shape; the permutation function must be total-  Backpermute :: (Shape sh, Shape sh', Elt e)-              => PreExp     acc aenv sh'                        -- dimensions of the result-              -> PreFun     acc aenv (sh' -> sh)                -- permutation function-              -> acc            aenv (Array sh e)               -- source array-              -> PreOpenAcc acc aenv (Array sh' e)--  -- Map a stencil over an array.  In contrast to 'map', the domain of a stencil function is an-  -- entire /neighbourhood/ of each array element.-  Stencil     :: (Elt e, Elt e', Stencil sh e stencil)-              => PreFun      acc aenv (stencil -> e')           -- stencil function-              -> PreBoundary acc aenv (Array sh e)              -- boundary condition-              -> acc             aenv (Array sh e)              -- source array-              -> PreOpenAcc  acc aenv (Array sh e')--  -- Map a binary stencil over an array.-  Stencil2    :: (Elt a, Elt b, Elt c, Stencil sh a stencil1, Stencil sh b stencil2)-              => PreFun      acc aenv (stencil1 -> stencil2 -> c) -- stencil function-              -> PreBoundary acc aenv (Array sh a)                -- boundary condition #1-              -> acc             aenv (Array sh a)                -- source array #1-              -> PreBoundary acc aenv (Array sh b)                -- boundary condition #2-              -> acc             aenv (Array sh b)                -- source array #2-              -> PreOpenAcc acc  aenv (Array sh c)--  -- A sequence of operations.-  -- Collect     :: Arrays arrs-  --             => PreOpenSeq acc aenv () arrs-  --             -> PreOpenAcc acc aenv arrs--{---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--  Consumer :: Arrays arrs-           => Consumer acc aenv senv arrs-           -> PreOpenSeq acc aenv senv arrs--  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 Seq = PreOpenSeq OpenAcc () ()---}----- | Vanilla stencil boundary condition----type Boundary = PreBoundary OpenAcc---- | Boundary condition specification for stencil operations----data PreBoundary (acc :: * -> * -> *) aenv t where-  -- Clamp coordinates to the extent of the array-  Clamp     :: PreBoundary acc aenv t--  -- Mirror coordinates beyond the array extent-  Mirror    :: PreBoundary acc aenv t--  -- Wrap coordinates around on each dimension-  Wrap      :: PreBoundary acc aenv t--  -- Use a constant value for outlying coordinates-  Constant  :: Elt e-            => EltRepr e-            -> PreBoundary acc aenv (Array sh e)--  -- Apply the given function to outlying coordinates-  Function  :: (Shape sh, Elt e)-            => PreFun acc aenv (sh -> e)-            -> PreBoundary acc aenv (Array sh e)----- | Operations on stencils----class (Shape sh, Elt e, IsTuple stencil, Elt stencil) => Stencil sh e stencil where-  stencil :: StencilR sh e stencil---- | GADT reifying the 'Stencil' class----data StencilR sh e pat where-  StencilRunit3 :: Elt e => StencilR DIM1 e (e,e,e)-  StencilRunit5 :: Elt e => StencilR DIM1 e (e,e,e,e,e)-  StencilRunit7 :: Elt e => StencilR DIM1 e (e,e,e,e,e,e,e)-  StencilRunit9 :: Elt e => StencilR DIM1 e (e,e,e,e,e,e,e,e,e)--  StencilRtup3  :: (Shape sh, Elt e)-                => StencilR sh e pat1-                -> StencilR sh e pat2-                -> StencilR sh e pat3-                -> StencilR (sh:.Int) e (pat1,pat2,pat3)--  StencilRtup5  :: (Shape sh, Elt e)-                => StencilR sh e pat1-                -> StencilR sh e pat2-                -> StencilR sh e pat3-                -> StencilR sh e pat4-                -> StencilR sh e pat5-                -> StencilR (sh:.Int) e (pat1,pat2,pat3,pat4,pat5)--  StencilRtup7  :: (Shape sh, Elt e)-                => StencilR sh e pat1-                -> StencilR sh e pat2-                -> StencilR sh e pat3-                -> StencilR sh e pat4-                -> StencilR sh e pat5-                -> StencilR sh e pat6-                -> StencilR sh e pat7-                -> StencilR (sh:.Int) e (pat1,pat2,pat3,pat4,pat5,pat6,pat7)--  StencilRtup9  :: (Shape sh, Elt e)-                => StencilR sh e pat1-                -> StencilR sh e pat2-                -> StencilR sh e pat3-                -> StencilR sh e pat4-                -> StencilR sh e pat5-                -> StencilR sh e pat6-                -> StencilR sh e pat7-                -> StencilR sh e pat8-                -> StencilR sh e pat9-                -> StencilR (sh:.Int) e (pat1,pat2,pat3,pat4,pat5,pat6,pat7,pat8,pat9)----- Note: [Stencil reification class]------ We cannot start with 'DIM0'.  The 'IsTuple stencil' superclass would at--- 'DIM0' imply that the types of individual array elements are in 'IsTuple'.--- (That would only possible if we could have (degenerate) 1-tuple, but we can't--- as we can't distinguish between a 1-tuple of a pair and a simple pair.)--- Hence, we need to start from 'DIM1' and use 'sh:.Int:.Int' in the recursive--- case (to avoid overlapping instances).---- DIM1-instance Elt e => Stencil DIM1 e (e, e, e) where-  stencil = StencilRunit3--instance Elt e => Stencil DIM1 e (e, e, e, e, e) where-  stencil = StencilRunit5--instance Elt e => Stencil DIM1 e (e, e, e, e, e, e, e) where-  stencil = StencilRunit7--instance Elt e => Stencil DIM1 e (e, e, e, e, e, e, e, e, e) where-  stencil = StencilRunit9---- DIM(n+1), where n>1-instance (Stencil (sh:.Int) a row1,-          Stencil (sh:.Int) a row2,-          Stencil (sh:.Int) a row3) => Stencil (sh:.Int:.Int) a (row1, row2, row3) where-  stencil = StencilRtup3 stencil stencil stencil--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-  stencil = StencilRtup5 stencil stencil stencil stencil stencil--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-  stencil = StencilRtup7 stencil stencil stencil stencil stencil stencil stencil--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-  stencil = StencilRtup9 stencil stencil stencil stencil stencil stencil stencil stencil stencil----- Embedded expressions--- ------------------------ |Parametrised open function abstraction----data PreOpenFun (acc :: * -> * -> *) env aenv t where-  Body :: Elt t => PreOpenExp acc env      aenv t -> PreOpenFun acc env aenv t-  Lam  :: Elt a => PreOpenFun acc (env, a) aenv t -> PreOpenFun acc env aenv (a -> t)---- |Vanilla open function abstraction----type OpenFun = PreOpenFun OpenAcc---- |Parametrised function without free scalar variables----type PreFun acc = PreOpenFun acc ()---- |Vanilla function without free scalar variables----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.------ The data type is parametrised over the surface types (not the representation type).----data PreOpenExp (acc :: * -> * -> *) env aenv t where--  -- Local binding of a scalar expression-  Let           :: (Elt bnd_t, Elt body_t)-                => PreOpenExp acc env          aenv bnd_t-                -> PreOpenExp acc (env, bnd_t) aenv body_t-                -> PreOpenExp acc env          aenv body_t--  -- Variable index, ranging only over tuples or scalars-  Var           :: Elt t-                => Idx env t-                -> PreOpenExp acc env aenv t--  -- Apply a backend-specific foreign function-  Foreign       :: (Foreign asm, Elt x, Elt y)-                => asm           (x -> y)           -- foreign function-                -> PreFun acc () (x -> y)           -- alternate implementation (for other backends)-                -> PreOpenExp acc env aenv x-                -> PreOpenExp acc env aenv y--  -- Tuples-  Tuple         :: (Elt t, IsTuple t)-                => Tuple (PreOpenExp acc env aenv) (TupleRepr t)-                -> PreOpenExp acc env aenv t--  Prj           :: (Elt t, IsTuple t, Elt e)-                => TupleIdx (TupleRepr t) e-                -> PreOpenExp acc env aenv t-                -> PreOpenExp acc env aenv e--  -- Array indices & shapes-  IndexNil      :: PreOpenExp acc env aenv Z--  IndexCons     :: (Slice sl, Elt a)-                => PreOpenExp acc env aenv sl-                -> PreOpenExp acc env aenv a-                -> PreOpenExp acc env aenv (sl:.a)--  IndexHead     :: (Slice sl, Elt a)-                => PreOpenExp acc env aenv (sl:.a)-                -> PreOpenExp acc env aenv a--  IndexTail     :: (Slice sl, Elt a)-                => PreOpenExp acc env aenv (sl:.a)-                -> PreOpenExp acc env aenv sl--  IndexAny      :: Shape sh-                => PreOpenExp acc env aenv (Any sh)--  IndexSlice    :: (Shape sh, Shape sl, Elt slix)-                => SliceIndex (EltRepr slix) (EltRepr sl) co (EltRepr sh)-                -> PreOpenExp acc env aenv slix-                -> PreOpenExp acc env aenv sh-                -> PreOpenExp acc env aenv sl--  IndexFull     :: (Shape sh, Shape sl, Elt slix)-                => SliceIndex (EltRepr slix) (EltRepr sl) co (EltRepr sh)-                -> PreOpenExp acc env aenv slix-                -> PreOpenExp acc env aenv sl-                -> PreOpenExp acc env aenv sh--  -- Shape and index conversion-  ToIndex       :: Shape sh-                => PreOpenExp acc env aenv sh           -- shape of the array-                -> PreOpenExp acc env aenv sh           -- index into the array-                -> PreOpenExp acc env aenv Int--  FromIndex     :: Shape sh-                => PreOpenExp acc env aenv sh           -- shape of the array-                -> PreOpenExp acc env aenv Int          -- index into linear representation-                -> PreOpenExp acc env aenv sh--  -- Conditional expression (non-strict in 2nd and 3rd argument)-  Cond          :: Elt t-                => PreOpenExp acc env aenv Bool-                -> PreOpenExp acc env aenv t-                -> PreOpenExp acc env aenv t-                -> PreOpenExp acc env aenv t--  -- Value recursion-  While         :: Elt a-                => PreOpenFun acc env aenv (a -> Bool)  -- continue while true-                -> PreOpenFun acc env aenv (a -> a)     -- function to iterate-                -> PreOpenExp acc env aenv a            -- initial value-                -> PreOpenExp acc env aenv a--  -- Constant values-  Const         :: Elt t-                => EltRepr t-                -> PreOpenExp acc env aenv t--  PrimConst     :: Elt t-                => PrimConst t-                -> PreOpenExp acc env aenv t--  -- Primitive scalar operations-  PrimApp       :: (Elt a, Elt r)-                => PrimFun (a -> r)-                -> PreOpenExp acc env aenv a-                -> PreOpenExp acc env aenv r--  -- Project a single scalar from an array.-  -- The array expression can not contain any free scalar variables.-  Index         :: (Shape dim, Elt t)-                => acc                aenv (Array dim t)-                -> PreOpenExp acc env aenv dim-                -> PreOpenExp acc env aenv t--  LinearIndex   :: (Shape dim, Elt t)-                => acc                aenv (Array dim t)-                -> PreOpenExp acc env aenv Int-                -> PreOpenExp acc env aenv t--  -- Array shape.-  -- The array expression can not contain any free scalar variables.-  Shape         :: (Shape dim, Elt e)-                => acc                aenv (Array dim e)-                -> PreOpenExp acc env aenv dim--  -- Number of elements of an array given its shape-  ShapeSize     :: Shape dim-                => PreOpenExp acc env aenv dim-                -> PreOpenExp acc env aenv Int--  -- Intersection of two shapes-  Intersect     :: Shape dim-                => PreOpenExp acc env aenv dim-                -> 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--  -- Unsafe operations (may fail or result in undefined behaviour)-  -- An unspecified bit pattern-  Undef         :: Elt t-                => PreOpenExp acc env aenv t--  -- Reinterpret the bits of a value as a different type-  Coerce        :: (Elt a, Elt b)-                => PreOpenExp acc env aenv a-                -> PreOpenExp acc env aenv b----- |Primitive constant values----data PrimConst ty where--  -- constants from Bounded-  PrimMinBound  :: BoundedType a -> PrimConst a-  PrimMaxBound  :: BoundedType a -> PrimConst a--  -- constant from Floating-  PrimPi        :: FloatingType a -> PrimConst a---- |Primitive scalar operations----data PrimFun sig where--  -- operators from Num-  PrimAdd  :: NumType a -> PrimFun ((a, a) -> a)-  PrimSub  :: NumType a -> PrimFun ((a, a) -> a)-  PrimMul  :: NumType a -> PrimFun ((a, a) -> a)-  PrimNeg  :: NumType a -> PrimFun (a      -> a)-  PrimAbs  :: NumType a -> PrimFun (a      -> a)-  PrimSig  :: NumType a -> PrimFun (a      -> a)--  -- 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)-  PrimDivMod   :: IntegralType a -> PrimFun ((a, a)   -> (a, a))--  -- 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)-  PrimCos         :: FloatingType a -> PrimFun (a      -> a)-  PrimTan         :: FloatingType a -> PrimFun (a      -> a)-  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)-  PrimExpFloating :: FloatingType a -> PrimFun (a      -> a)-  PrimSqrt        :: FloatingType a -> PrimFun (a      -> a)-  PrimLog         :: FloatingType a -> PrimFun (a      -> a)-  PrimFPow        :: FloatingType a -> PrimFun ((a, a) -> a)-  PrimLogBase     :: FloatingType a -> PrimFun ((a, a) -> a)--  -- 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-  PrimAtan2          :: FloatingType a -> PrimFun ((a, a) -> a)-  PrimIsNaN          :: FloatingType a -> PrimFun (a -> Bool)-  PrimIsInfinite     :: FloatingType a -> PrimFun (a -> Bool)--  -- relational and equality operators-  PrimLt   :: SingleType a -> PrimFun ((a, a) -> Bool)-  PrimGt   :: SingleType a -> PrimFun ((a, a) -> Bool)-  PrimLtEq :: SingleType a -> PrimFun ((a, a) -> Bool)-  PrimGtEq :: SingleType a -> PrimFun ((a, a) -> Bool)-  PrimEq   :: SingleType a -> PrimFun ((a, a) -> Bool)-  PrimNEq  :: SingleType a -> PrimFun ((a, a) -> Bool)-  PrimMax  :: SingleType a -> PrimFun ((a, a) -> a   )-  PrimMin  :: SingleType a -> PrimFun ((a, a) -> a   )--  -- logical operators-  PrimLAnd :: PrimFun ((Bool, Bool) -> Bool)-  PrimLOr  :: PrimFun ((Bool, Bool) -> Bool)-  PrimLNot :: PrimFun (Bool         -> Bool)--  -- character conversions-  PrimOrd  :: PrimFun (Char -> Int)-  PrimChr  :: PrimFun (Int  -> Char)--  -- 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)----- 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 :: PreBoundary acc aenv' (Array sh e) -> ()-      rnfB = rnfBoundary rnfA-  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 b  `seq` rnfA a-    Stencil2 f b1 a1 b2 a2    -> rnfF f `seq` rnfB b1 `seq` rnfB 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 :: forall acc aenv sh e. NFDataAcc acc -> PreBoundary acc aenv (Array sh e) -> ()-rnfBoundary _    Clamp        = ()-rnfBoundary _    Mirror       = ()-rnfBoundary _    Wrap         = ()-rnfBoundary _    (Constant c) = rnfConst (eltType (undefined::e)) c-rnfBoundary rnfA (Function f) = rnfPreOpenFun rnfA f---{----- 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-    Undef                     -> ()-    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-    Coerce e                  -> rnfE e--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 TypeRunit          ()    = ()-rnfConst (TypeRscalar t)    !_    = rnfScalarType t  -- scalars should have (nf == whnf)-rnfConst (TypeRpair 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 (PrimIsInfinite t)         = rnfFloatingType t-rnfPrimFun (PrimAtan2 t)              = rnfFloatingType t-rnfPrimFun (PrimLt t)                 = rnfSingleType t-rnfPrimFun (PrimGt t)                 = rnfSingleType t-rnfPrimFun (PrimLtEq t)               = rnfSingleType t-rnfPrimFun (PrimGtEq t)               = rnfSingleType t-rnfPrimFun (PrimEq t)                 = rnfSingleType t-rnfPrimFun (PrimNEq t)                = rnfSingleType t-rnfPrimFun (PrimMax t)                = rnfSingleType t-rnfPrimFun (PrimMin t)                = rnfSingleType 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--rnfSliceIndex :: SliceIndex ix slice co sh -> ()-rnfSliceIndex SliceNil        = ()-rnfSliceIndex (SliceAll sh)   = rnfSliceIndex sh-rnfSliceIndex (SliceFixed sh) = rnfSliceIndex sh--rnfScalarType :: ScalarType t -> ()-rnfScalarType (SingleScalarType t) = rnfSingleType t-rnfScalarType (VectorScalarType t) = rnfVectorType t--rnfSingleType :: SingleType t -> ()-rnfSingleType (NumSingleType t)    = rnfNumType t-rnfSingleType (NonNumSingleType t) = rnfNonNumType t--rnfVectorType :: VectorType t -> ()-rnfVectorType (Vector2Type t)  = rnfSingleType t-rnfVectorType (Vector3Type t)  = rnfSingleType t-rnfVectorType (Vector4Type t)  = rnfSingleType t-rnfVectorType (Vector8Type t)  = rnfSingleType t-rnfVectorType (Vector16Type t) = rnfSingleType 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 (TypeHalf    FloatingDict) = ()-rnfFloatingType (TypeFloat   FloatingDict) = ()-rnfFloatingType (TypeDouble  FloatingDict) = ()-rnfFloatingType (TypeCFloat  FloatingDict) = ()-rnfFloatingType (TypeCDouble FloatingDict) = ()----- Template Haskell--- ================--type LiftAcc acc = forall aenv a. acc aenv a -> Q (TExp (acc aenv a))--liftIdx :: Idx env t -> Q (TExp (Idx env t))-liftIdx ZeroIdx      = [|| ZeroIdx ||]-liftIdx (SuccIdx ix) = [|| SuccIdx $$(liftIdx ix) ||]--liftTupleIdx :: TupleIdx t e -> Q (TExp (TupleIdx t e))-liftTupleIdx ZeroTupIdx       = [|| ZeroTupIdx ||]-liftTupleIdx (SuccTupIdx tix) = [|| SuccTupIdx $$(liftTupleIdx tix) ||]---liftPreOpenAfun :: LiftAcc acc -> PreOpenAfun acc aenv t -> Q (TExp (PreOpenAfun acc aenv t))-liftPreOpenAfun liftA (Alam f)  = [|| Alam  $$(liftPreOpenAfun liftA f) ||]-liftPreOpenAfun liftA (Abody b) = [|| Abody $$(liftA b) ||]--liftPreOpenAcc-    :: forall acc aenv a.-       LiftAcc acc-    -> PreOpenAcc acc aenv a-    -> Q (TExp (PreOpenAcc acc aenv a))-liftPreOpenAcc liftA pacc =-  let-      liftE :: PreOpenExp acc env aenv t -> Q (TExp (PreOpenExp acc env aenv t))-      liftE = liftPreOpenExp liftA--      liftF :: PreOpenFun acc env aenv t -> Q (TExp (PreOpenFun acc env aenv t))-      liftF = liftPreOpenFun liftA--      liftAF :: PreOpenAfun acc aenv f -> Q (TExp (PreOpenAfun acc aenv f))-      liftAF = liftPreOpenAfun liftA--      liftB :: PreBoundary acc aenv (Array sh e) -> Q (TExp (PreBoundary acc aenv (Array sh e)))-      liftB = liftBoundary liftA--      liftAtuple :: Atuple (acc aenv) t -> Q (TExp (Atuple (acc aenv) t))-      liftAtuple NilAtup          = [|| NilAtup ||]-      liftAtuple (SnocAtup tup a) = [|| SnocAtup $$(liftAtuple tup) $$(liftA a) ||]-  in-  case pacc of-    Alet bnd body             -> [|| Alet $$(liftA bnd) $$(liftA body) ||]-    Avar ix                   -> [|| Avar $$(liftIdx ix) ||]-    Atuple tup                -> [|| Atuple $$(liftAtuple tup) ||]-    Aprj tix a                -> [|| Aprj $$(liftTupleIdx tix) $$(liftA a) ||]-    Apply f a                 -> [|| Apply $$(liftAF f) $$(liftA a) ||]-    Aforeign asm f a          -> [|| Aforeign $$(liftForeign asm) $$(liftPreOpenAfun liftA f) $$(liftA a) ||]-    Acond p t e               -> [|| Acond $$(liftE p) $$(liftA t) $$(liftA e) ||]-    Awhile p f a              -> [|| Awhile $$(liftAF p) $$(liftAF f) $$(liftA a) ||]-    Use a                     -> [|| Use $$(liftArrays (arrays (undefined::a)) a) ||]-    Unit e                    -> [|| Unit $$(liftE e) ||]-    Reshape sh a              -> [|| Reshape $$(liftE sh) $$(liftA a) ||]-    Generate sh f             -> [|| Generate $$(liftE sh) $$(liftF f) ||]-    Transform sh p f a        -> [|| Transform $$(liftE sh) $$(liftF p) $$(liftF f) $$(liftA a) ||]-    Replicate slix sl a       -> [|| Replicate $$(liftSliceIndex slix) $$(liftE sl) $$(liftA a) ||]-    Slice slix a sh           -> [|| Slice $$(liftSliceIndex slix) $$(liftA a) $$(liftE sh) ||]-    Map f a                   -> [|| Map $$(liftF f) $$(liftA a) ||]-    ZipWith f a b             -> [|| ZipWith $$(liftF f) $$(liftA a) $$(liftA b) ||]-    Fold f z a                -> [|| Fold $$(liftF f) $$(liftE z) $$(liftA a) ||]-    Fold1 f a                 -> [|| Fold1 $$(liftF f) $$(liftA a) ||]-    FoldSeg f z a s           -> [|| FoldSeg $$(liftF f) $$(liftE z) $$(liftA a) $$(liftA s) ||]-    Fold1Seg f a s            -> [|| Fold1Seg $$(liftF f) $$(liftA a) $$(liftA s) ||]-    Scanl f z a               -> [|| Scanl $$(liftF f) $$(liftE z) $$(liftA a) ||]-    Scanl1 f a                -> [|| Scanl1 $$(liftF f) $$(liftA a) ||]-    Scanl' f z a              -> [|| Scanl' $$(liftF f) $$(liftE z) $$(liftA a) ||]-    Scanr f z a               -> [|| Scanr $$(liftF f) $$(liftE z) $$(liftA a) ||]-    Scanr1 f a                -> [|| Scanr1 $$(liftF f) $$(liftA a) ||]-    Scanr' f z a              -> [|| Scanr' $$(liftF f) $$(liftE z) $$(liftA a) ||]-    Permute f d p a           -> [|| Permute $$(liftF f) $$(liftA d) $$(liftF p) $$(liftA a) ||]-    Backpermute sh p a        -> [|| Backpermute $$(liftE sh) $$(liftF p) $$(liftA a) ||]-    Stencil f b a             -> [|| Stencil $$(liftF f) $$(liftB b) $$(liftA a) ||]-    Stencil2 f b1 a1 b2 a2    -> [|| Stencil2 $$(liftF f) $$(liftB b1) $$(liftA a1) $$(liftB b2) $$(liftA a2) ||]---liftPreOpenFun-    :: LiftAcc acc-    -> PreOpenFun acc env aenv t-    -> Q (TExp (PreOpenFun acc env aenv t))-liftPreOpenFun liftA (Lam f)  = [|| Lam  $$(liftPreOpenFun liftA f) ||]-liftPreOpenFun liftA (Body b) = [|| Body $$(liftPreOpenExp liftA b) ||]--liftPreOpenExp-    :: forall acc env aenv t.-       LiftAcc acc-    -> PreOpenExp acc env aenv t-    -> Q (TExp (PreOpenExp acc env aenv t))-liftPreOpenExp liftA pexp =-  let-      liftE :: PreOpenExp acc env aenv e -> Q (TExp (PreOpenExp acc env aenv e))-      liftE = liftPreOpenExp liftA--      liftF :: PreOpenFun acc env aenv f -> Q (TExp (PreOpenFun acc env aenv f))-      liftF = liftPreOpenFun liftA--      liftT :: Tuple (PreOpenExp acc env aenv) e -> Q (TExp (Tuple (PreOpenExp acc env aenv) e))-      liftT NilTup          = [|| NilTup ||]-      liftT (SnocTup tup e) = [|| SnocTup $$(liftT tup) $$(liftE e) ||]-  in-  case pexp of-    Let bnd body              -> [|| Let $$(liftPreOpenExp liftA bnd) $$(liftPreOpenExp liftA body) ||]-    Var ix                    -> [|| Var $$(liftIdx ix) ||]-    Foreign asm f x           -> [|| Foreign $$(liftForeign asm) $$(liftPreOpenFun liftA f) $$(liftE x) ||]-    Const c                   -> [|| Const $$(liftConst (eltType (undefined::t)) c) ||]-    Undef                     -> [|| Undef ||]-    Tuple tup                 -> [|| Tuple $$(liftT tup) ||]-    Prj tix e                 -> [|| Prj $$(liftTupleIdx tix) $$(liftE e) ||]-    IndexNil                  -> [|| IndexNil ||]-    IndexCons sh sz           -> [|| IndexCons $$(liftE sh) $$(liftE sz) ||]-    IndexHead sh              -> [|| IndexHead $$(liftE sh) ||]-    IndexTail sh              -> [|| IndexTail $$(liftE sh) ||]-    IndexAny                  -> [|| IndexAny ||]-    IndexSlice slice slix sh  -> [|| IndexSlice $$(liftSliceIndex slice) $$(liftE slix) $$(liftE sh) ||]-    IndexFull slice slix sl   -> [|| IndexFull $$(liftSliceIndex slice) $$(liftE slix) $$(liftE sl) ||]-    ToIndex sh ix             -> [|| ToIndex $$(liftE sh) $$(liftE ix) ||]-    FromIndex sh ix           -> [|| FromIndex $$(liftE sh) $$(liftE ix) ||]-    Cond p t e                -> [|| Cond $$(liftE p) $$(liftE t) $$(liftE e) ||]-    While p f x               -> [|| While $$(liftF p) $$(liftF f) $$(liftE x) ||]-    PrimConst t               -> [|| PrimConst $$(liftPrimConst t) ||]-    PrimApp f x               -> [|| PrimApp $$(liftPrimFun f) $$(liftE x) ||]-    Index a ix                -> [|| Index $$(liftA a) $$(liftE ix) ||]-    LinearIndex a ix          -> [|| LinearIndex $$(liftA a) $$(liftE ix) ||]-    Shape a                   -> [|| Shape $$(liftA a) ||]-    ShapeSize ix              -> [|| ShapeSize $$(liftE ix) ||]-    Intersect sh1 sh2         -> [|| Intersect $$(liftE sh1) $$(liftE sh2) ||]-    Union sh1 sh2             -> [|| Union $$(liftE sh1) $$(liftE sh2) ||]-    Coerce e                  -> [|| Coerce $$(liftE e) ||]---liftArrays :: ArraysR arr -> arr -> Q (TExp arr)-liftArrays ArraysRunit ()              = [|| () ||]-liftArrays ArraysRarray arr            = [|| $$(liftArray arr) ||]-liftArrays (ArraysRpair r1 r2) (a1,a2) = [|| ($$(liftArrays r1 a1), $$(liftArrays r2 a2)) ||]--liftArray :: forall sh e. Array sh e -> Q (TExp (Array sh e))-liftArray (Array sh adata) =-  [|| Array $$(liftConst (eltType (undefined::sh)) sh) $$(go arrayElt adata) ||] `sigE` typeRepToType (typeOf (undefined::Array sh e))-  where-    sz :: Int-    sz = size sh--    sigE :: Q (TExp t) -> Q TH.Type -> Q (TExp t)-    sigE e t = TH.unsafeTExpCoerce $ TH.sigE (TH.unTypeQ e) t--    typeRepToType :: TypeRep -> Q TH.Type-    typeRepToType trep = do-      let (con, args)     = splitTyConApp trep-          name            = TH.Name (TH.OccName (tyConName con)) (TH.NameG TH.TcClsName (TH.PkgName (tyConPackage con)) (TH.ModName (tyConModule con)))-          ---          appsT x []      = x-          appsT x (y:xs)  = appsT (TH.AppT x y) xs-          ---      resultArgs <- mapM typeRepToType args-      return (appsT (TH.ConT name) resultArgs)--    -- TODO: make sure that the resulting array is 16-byte aligned...-    arr :: forall a. (ArrayElt a, Storable a) => UniqueArray a -> Q (TExp (UniqueArray a))-    arr ua = do-      bytes <- TH.runIO $ peekArray (sizeOf (undefined::a) * sz) (castPtr (unsafeUniqueArrayPtr ua) :: Ptr Word8)-      [|| unsafePerformIO $ do-           fp  <- newForeignPtr_ $$( TH.unsafeTExpCoerce [| Ptr $(TH.litE (TH.StringPrimL bytes)) |] )-           ua' <- newUniqueArray (castForeignPtr fp)-           return ua'-       ||]--    go :: ArrayEltR e' -> ArrayData e' -> Q (TExp (ArrayData e'))-    go ArrayEltRunit         AD_Unit         = [|| AD_Unit ||]-    go ArrayEltRint          (AD_Int ua)     = [|| AD_Int $$(arr ua) ||]-    go ArrayEltRint8         (AD_Int8 ua)    = [|| AD_Int8 $$(arr ua) ||]-    go ArrayEltRint16        (AD_Int16 ua)   = [|| AD_Int16 $$(arr ua) ||]-    go ArrayEltRint32        (AD_Int32 ua)   = [|| AD_Int32 $$(arr ua) ||]-    go ArrayEltRint64        (AD_Int64 ua)   = [|| AD_Int64 $$(arr ua) ||]-    go ArrayEltRword         (AD_Word ua)    = [|| AD_Word $$(arr ua) ||]-    go ArrayEltRword8        (AD_Word8 ua)   = [|| AD_Word8 $$(arr ua) ||]-    go ArrayEltRword16       (AD_Word16 ua)  = [|| AD_Word16 $$(arr ua) ||]-    go ArrayEltRword32       (AD_Word32 ua)  = [|| AD_Word32 $$(arr ua) ||]-    go ArrayEltRword64       (AD_Word64 ua)  = [|| AD_Word64 $$(arr ua) ||]-    go ArrayEltRcshort       (AD_CShort ua)  = [|| AD_CShort $$(arr ua) ||]-    go ArrayEltRcushort      (AD_CUShort ua) = [|| AD_CUShort $$(arr ua) ||]-    go ArrayEltRcint         (AD_CInt ua)    = [|| AD_CInt $$(arr ua) ||]-    go ArrayEltRcuint        (AD_CUInt ua)   = [|| AD_CUInt $$(arr ua) ||]-    go ArrayEltRclong        (AD_CLong ua)   = [|| AD_CLong $$(arr ua) ||]-    go ArrayEltRculong       (AD_CULong ua)  = [|| AD_CULong $$(arr ua) ||]-    go ArrayEltRcllong       (AD_CLLong ua)  = [|| AD_CLLong $$(arr ua) ||]-    go ArrayEltRcullong      (AD_CULLong ua) = [|| AD_CULLong $$(arr ua) ||]-    go ArrayEltRhalf         (AD_Half ua)    = [|| AD_Half $$(arr ua) ||]-    go ArrayEltRfloat        (AD_Float ua)   = [|| AD_Float $$(arr ua) ||]-    go ArrayEltRdouble       (AD_Double ua)  = [|| AD_Double $$(arr ua) ||]-    go ArrayEltRcfloat       (AD_CFloat ua)  = [|| AD_CFloat $$(arr ua) ||]-    go ArrayEltRcdouble      (AD_CDouble ua) = [|| AD_CDouble $$(arr ua) ||]-    go ArrayEltRbool         (AD_Bool ua)    = [|| AD_Bool $$(arr ua) ||]-    go ArrayEltRchar         (AD_Char ua)    = [|| AD_Char $$(arr ua) ||]-    go ArrayEltRcchar        (AD_CChar ua)   = [|| AD_CChar $$(arr ua) ||]-    go ArrayEltRcschar       (AD_CSChar ua)  = [|| AD_CSChar $$(arr ua) ||]-    go ArrayEltRcuchar       (AD_CUChar ua)  = [|| AD_CUChar $$(arr ua) ||]-    go (ArrayEltRvec2 r)     (AD_V2 a)       = [|| AD_V2 $$(go r a) ||]-    go (ArrayEltRvec3 r)     (AD_V3 a)       = [|| AD_V3 $$(go r a) ||]-    go (ArrayEltRvec4 r)     (AD_V4 a)       = [|| AD_V4 $$(go r a) ||]-    go (ArrayEltRvec8 r)     (AD_V8 a)       = [|| AD_V8 $$(go r a) ||]-    go (ArrayEltRvec16 r)    (AD_V16 a)      = [|| AD_V16 $$(go r a) ||]-    go (ArrayEltRpair r1 r2) (AD_Pair a1 a2) = [|| AD_Pair $$(go r1 a1) $$(go r2 a2) ||]---liftBoundary-    :: forall acc aenv sh e.-       LiftAcc acc-    -> PreBoundary acc aenv (Array sh e)-    -> Q (TExp (PreBoundary acc aenv (Array sh e)))-liftBoundary _     Clamp        = [|| Clamp ||]-liftBoundary _     Mirror       = [|| Mirror ||]-liftBoundary _     Wrap         = [|| Wrap ||]-liftBoundary _     (Constant v) = [|| Constant $$(liftConst (eltType (undefined::e)) v) ||]-liftBoundary liftA (Function f) = [|| Function $$(liftPreOpenFun liftA f) ||]--liftSliceIndex :: SliceIndex ix slice coSlice sliceDim -> Q (TExp (SliceIndex ix slice coSlice sliceDim))-liftSliceIndex SliceNil          = [|| SliceNil ||]-liftSliceIndex (SliceAll rest)   = [|| SliceAll $$(liftSliceIndex rest) ||]-liftSliceIndex (SliceFixed rest) = [|| SliceFixed $$(liftSliceIndex rest) ||]--liftPrimConst :: PrimConst c -> Q (TExp (PrimConst c))-liftPrimConst (PrimMinBound t) = [|| PrimMinBound $$(liftBoundedType t) ||]-liftPrimConst (PrimMaxBound t) = [|| PrimMaxBound $$(liftBoundedType t) ||]-liftPrimConst (PrimPi t)       = [|| PrimPi $$(liftFloatingType t) ||]--liftPrimFun :: PrimFun f -> Q (TExp (PrimFun f))-liftPrimFun (PrimAdd t)                = [|| PrimAdd $$(liftNumType t) ||]-liftPrimFun (PrimSub t)                = [|| PrimSub $$(liftNumType t) ||]-liftPrimFun (PrimMul t)                = [|| PrimMul $$(liftNumType t) ||]-liftPrimFun (PrimNeg t)                = [|| PrimNeg $$(liftNumType t) ||]-liftPrimFun (PrimAbs t)                = [|| PrimAbs $$(liftNumType t) ||]-liftPrimFun (PrimSig t)                = [|| PrimSig $$(liftNumType t) ||]-liftPrimFun (PrimQuot t)               = [|| PrimQuot $$(liftIntegralType t) ||]-liftPrimFun (PrimRem t)                = [|| PrimRem $$(liftIntegralType t) ||]-liftPrimFun (PrimQuotRem t)            = [|| PrimQuotRem $$(liftIntegralType t) ||]-liftPrimFun (PrimIDiv t)               = [|| PrimIDiv $$(liftIntegralType t) ||]-liftPrimFun (PrimMod t)                = [|| PrimMod $$(liftIntegralType t) ||]-liftPrimFun (PrimDivMod t)             = [|| PrimDivMod $$(liftIntegralType t) ||]-liftPrimFun (PrimBAnd t)               = [|| PrimBAnd $$(liftIntegralType t) ||]-liftPrimFun (PrimBOr t)                = [|| PrimBOr $$(liftIntegralType t) ||]-liftPrimFun (PrimBXor t)               = [|| PrimBXor $$(liftIntegralType t) ||]-liftPrimFun (PrimBNot t)               = [|| PrimBNot $$(liftIntegralType t) ||]-liftPrimFun (PrimBShiftL t)            = [|| PrimBShiftL $$(liftIntegralType t) ||]-liftPrimFun (PrimBShiftR t)            = [|| PrimBShiftR $$(liftIntegralType t) ||]-liftPrimFun (PrimBRotateL t)           = [|| PrimBRotateL $$(liftIntegralType t) ||]-liftPrimFun (PrimBRotateR t)           = [|| PrimBRotateR $$(liftIntegralType t) ||]-liftPrimFun (PrimPopCount t)           = [|| PrimPopCount $$(liftIntegralType t) ||]-liftPrimFun (PrimCountLeadingZeros t)  = [|| PrimCountLeadingZeros $$(liftIntegralType t) ||]-liftPrimFun (PrimCountTrailingZeros t) = [|| PrimCountTrailingZeros $$(liftIntegralType t) ||]-liftPrimFun (PrimFDiv t)               = [|| PrimFDiv $$(liftFloatingType t) ||]-liftPrimFun (PrimRecip t)              = [|| PrimRecip $$(liftFloatingType t) ||]-liftPrimFun (PrimSin t)                = [|| PrimSin $$(liftFloatingType t) ||]-liftPrimFun (PrimCos t)                = [|| PrimCos $$(liftFloatingType t) ||]-liftPrimFun (PrimTan t)                = [|| PrimTan $$(liftFloatingType t) ||]-liftPrimFun (PrimAsin t)               = [|| PrimAsin $$(liftFloatingType t) ||]-liftPrimFun (PrimAcos t)               = [|| PrimAcos $$(liftFloatingType t) ||]-liftPrimFun (PrimAtan t)               = [|| PrimAtan $$(liftFloatingType t) ||]-liftPrimFun (PrimSinh t)               = [|| PrimSinh $$(liftFloatingType t) ||]-liftPrimFun (PrimCosh t)               = [|| PrimCosh $$(liftFloatingType t) ||]-liftPrimFun (PrimTanh t)               = [|| PrimTanh $$(liftFloatingType t) ||]-liftPrimFun (PrimAsinh t)              = [|| PrimAsinh $$(liftFloatingType t) ||]-liftPrimFun (PrimAcosh t)              = [|| PrimAcosh $$(liftFloatingType t) ||]-liftPrimFun (PrimAtanh t)              = [|| PrimAtanh $$(liftFloatingType t) ||]-liftPrimFun (PrimExpFloating t)        = [|| PrimExpFloating $$(liftFloatingType t) ||]-liftPrimFun (PrimSqrt t)               = [|| PrimSqrt $$(liftFloatingType t) ||]-liftPrimFun (PrimLog t)                = [|| PrimLog $$(liftFloatingType t) ||]-liftPrimFun (PrimFPow t)               = [|| PrimFPow $$(liftFloatingType t) ||]-liftPrimFun (PrimLogBase t)            = [|| PrimLogBase $$(liftFloatingType t) ||]-liftPrimFun (PrimTruncate ta tb)       = [|| PrimTruncate $$(liftFloatingType ta) $$(liftIntegralType tb) ||]-liftPrimFun (PrimRound ta tb)          = [|| PrimRound $$(liftFloatingType ta) $$(liftIntegralType tb) ||]-liftPrimFun (PrimFloor ta tb)          = [|| PrimFloor $$(liftFloatingType ta) $$(liftIntegralType tb) ||]-liftPrimFun (PrimCeiling ta tb)        = [|| PrimCeiling $$(liftFloatingType ta) $$(liftIntegralType tb) ||]-liftPrimFun (PrimIsNaN t)              = [|| PrimIsNaN $$(liftFloatingType t) ||]-liftPrimFun (PrimIsInfinite t)         = [|| PrimIsInfinite $$(liftFloatingType t) ||]-liftPrimFun (PrimAtan2 t)              = [|| PrimAtan2 $$(liftFloatingType t) ||]-liftPrimFun (PrimLt t)                 = [|| PrimLt $$(liftSingleType t) ||]-liftPrimFun (PrimGt t)                 = [|| PrimGt $$(liftSingleType t) ||]-liftPrimFun (PrimLtEq t)               = [|| PrimLtEq $$(liftSingleType t) ||]-liftPrimFun (PrimGtEq t)               = [|| PrimGtEq $$(liftSingleType t) ||]-liftPrimFun (PrimEq t)                 = [|| PrimEq $$(liftSingleType t) ||]-liftPrimFun (PrimNEq t)                = [|| PrimNEq $$(liftSingleType t) ||]-liftPrimFun (PrimMax t)                = [|| PrimMax $$(liftSingleType t) ||]-liftPrimFun (PrimMin t)                = [|| PrimMin $$(liftSingleType t) ||]-liftPrimFun PrimLAnd                   = [|| PrimLAnd ||]-liftPrimFun PrimLOr                    = [|| PrimLOr ||]-liftPrimFun PrimLNot                   = [|| PrimLNot ||]-liftPrimFun PrimOrd                    = [|| PrimOrd ||]-liftPrimFun PrimChr                    = [|| PrimChr ||]-liftPrimFun PrimBoolToInt              = [|| PrimBoolToInt ||]-liftPrimFun (PrimFromIntegral ta tb)   = [|| PrimFromIntegral $$(liftIntegralType ta) $$(liftNumType tb) ||]-liftPrimFun (PrimToFloating ta tb)     = [|| PrimToFloating $$(liftNumType ta) $$(liftFloatingType tb) ||]---liftConst :: TupleType t -> t -> Q (TExp t)-liftConst TypeRunit         ()    = [|| () ||]-liftConst (TypeRscalar t)   x     = [|| $$(liftScalar t x) ||]-liftConst (TypeRpair ta tb) (a,b) = [|| ($$(liftConst ta a), $$(liftConst tb b)) ||]--liftScalar :: ScalarType t -> t -> Q (TExp t)-liftScalar (SingleScalarType t) x = liftSingle t x-liftScalar (VectorScalarType t) x = liftVector t x--liftSingle :: SingleType t -> t -> Q (TExp t)-liftSingle (NumSingleType t)    x = liftNum t x-liftSingle (NonNumSingleType t) x = liftNonNum t x--liftVector :: VectorType v -> v -> Q (TExp v)-liftVector (Vector2Type t) (V2 a b)     = [|| V2 $$(liftSingle t a) $$(liftSingle t b) ||]-liftVector (Vector3Type t) (V3 a b c)   = [|| V3 $$(liftSingle t a) $$(liftSingle t b) $$(liftSingle t c) ||]-liftVector (Vector4Type t) (V4 a b c d) = [|| V4 $$(liftSingle t a) $$(liftSingle t b) $$(liftSingle t c) $$(liftSingle t d) ||]-liftVector (Vector8Type t) (V8 a b c d e f g h) =-  [|| V8 $$(liftSingle t a) $$(liftSingle t b) $$(liftSingle t c) $$(liftSingle t d)-         $$(liftSingle t e) $$(liftSingle t f) $$(liftSingle t g) $$(liftSingle t h) ||]-liftVector (Vector16Type t) (V16 a b c d e f g h i j k l m n o p) =-  [|| V16 $$(liftSingle t a) $$(liftSingle t b) $$(liftSingle t c) $$(liftSingle t d)-          $$(liftSingle t e) $$(liftSingle t f) $$(liftSingle t g) $$(liftSingle t h)-          $$(liftSingle t i) $$(liftSingle t j) $$(liftSingle t k) $$(liftSingle t l)-          $$(liftSingle t m) $$(liftSingle t n) $$(liftSingle t o) $$(liftSingle t p) ||]--liftNum :: NumType t -> t -> Q (TExp t)-liftNum (IntegralNumType t) x = liftIntegral t x-liftNum (FloatingNumType t) x = liftFloating t x--liftNonNum :: NonNumType t -> t -> Q (TExp t)-liftNonNum TypeBool{}   x = [|| x ||]-liftNonNum TypeChar{}   x = [|| x ||]-liftNonNum TypeCChar{}  x = return (TH.TExp (TH.LitE (TH.IntegerL (toInteger x))))-liftNonNum TypeCSChar{} x = return (TH.TExp (TH.LitE (TH.IntegerL (toInteger x))))-liftNonNum TypeCUChar{} x = return (TH.TExp (TH.LitE (TH.IntegerL (toInteger x))))--liftIntegral :: IntegralType t -> t -> Q (TExp t)-liftIntegral TypeInt{}     x = [|| x ||]-liftIntegral TypeInt8{}    x = [|| x ||]-liftIntegral TypeInt16{}   x = [|| x ||]-liftIntegral TypeInt32{}   x = [|| x ||]-liftIntegral TypeInt64{}   x = [|| x ||]-#if __GLASGOW_HASKELL__ >= 710-liftIntegral TypeWord{}    x = [|| x ||]-#else-liftIntegral TypeWord{}    x = return (TH.TExp (TH.LitE (TH.IntegerL (toInteger x))))-#endif-liftIntegral TypeWord8{}   x = [|| x ||]-liftIntegral TypeWord16{}  x = [|| x ||]-liftIntegral TypeWord32{}  x = [|| x ||]-liftIntegral TypeWord64{}  x = [|| x ||]-liftIntegral TypeCShort{}  x = return (TH.TExp (TH.LitE (TH.IntegerL (toInteger x))))-liftIntegral TypeCUShort{} x = return (TH.TExp (TH.LitE (TH.IntegerL (toInteger x))))-liftIntegral TypeCInt{}    x = return (TH.TExp (TH.LitE (TH.IntegerL (toInteger x))))-liftIntegral TypeCUInt{}   x = return (TH.TExp (TH.LitE (TH.IntegerL (toInteger x))))-liftIntegral TypeCLong{}   x = return (TH.TExp (TH.LitE (TH.IntegerL (toInteger x))))-liftIntegral TypeCULong{}  x = return (TH.TExp (TH.LitE (TH.IntegerL (toInteger x))))-liftIntegral TypeCLLong{}  x = return (TH.TExp (TH.LitE (TH.IntegerL (toInteger x))))-liftIntegral TypeCULLong{} x = return (TH.TExp (TH.LitE (TH.IntegerL (toInteger x))))--liftFloating :: FloatingType t -> t -> Q (TExp t)-liftFloating TypeHalf{}    x = [|| Half $$( liftIntegral integralType (getHalf x)) ||]-liftFloating TypeFloat{}   x = [|| x ||]-liftFloating TypeDouble{}  x = [|| x ||]-liftFloating TypeCFloat{}  x = return (TH.TExp (TH.LitE (TH.RationalL (toRational x))))-liftFloating TypeCDouble{} x = return (TH.TExp (TH.LitE (TH.RationalL (toRational x))))---liftIntegralType :: IntegralType t -> Q (TExp (IntegralType t))-liftIntegralType TypeInt{}     = [|| TypeInt IntegralDict ||]-liftIntegralType TypeInt8{}    = [|| TypeInt8 IntegralDict ||]-liftIntegralType TypeInt16{}   = [|| TypeInt16 IntegralDict ||]-liftIntegralType TypeInt32{}   = [|| TypeInt32 IntegralDict ||]-liftIntegralType TypeInt64{}   = [|| TypeInt64 IntegralDict ||]-liftIntegralType TypeWord{}    = [|| TypeWord IntegralDict ||]-liftIntegralType TypeWord8{}   = [|| TypeWord8 IntegralDict ||]-liftIntegralType TypeWord16{}  = [|| TypeWord16 IntegralDict ||]-liftIntegralType TypeWord32{}  = [|| TypeWord32 IntegralDict ||]-liftIntegralType TypeWord64{}  = [|| TypeWord64 IntegralDict ||]-liftIntegralType TypeCShort{}  = [|| TypeCShort IntegralDict ||]-liftIntegralType TypeCUShort{} = [|| TypeCUShort IntegralDict ||]-liftIntegralType TypeCInt{}    = [|| TypeCInt IntegralDict ||]-liftIntegralType TypeCUInt{}   = [|| TypeCUInt IntegralDict ||]-liftIntegralType TypeCLong{}   = [|| TypeCLong IntegralDict ||]-liftIntegralType TypeCULong{}  = [|| TypeCULong IntegralDict ||]-liftIntegralType TypeCLLong{}  = [|| TypeCLLong IntegralDict ||]-liftIntegralType TypeCULLong{} = [|| TypeCULLong IntegralDict ||]--liftFloatingType :: FloatingType t -> Q (TExp (FloatingType t))-liftFloatingType TypeHalf{}    = [|| TypeHalf FloatingDict ||]-liftFloatingType TypeFloat{}   = [|| TypeFloat FloatingDict ||]-liftFloatingType TypeDouble{}  = [|| TypeDouble FloatingDict ||]-liftFloatingType TypeCFloat{}  = [|| TypeCFloat FloatingDict ||]-liftFloatingType TypeCDouble{} = [|| TypeCDouble FloatingDict ||]--liftNonNumType :: NonNumType t -> Q (TExp (NonNumType t))-liftNonNumType TypeBool{}   = [|| TypeBool NonNumDict ||]-liftNonNumType TypeChar{}   = [|| TypeChar NonNumDict ||]-liftNonNumType TypeCChar{}  = [|| TypeCChar NonNumDict ||]-liftNonNumType TypeCSChar{} = [|| TypeCSChar NonNumDict ||]-liftNonNumType TypeCUChar{} = [|| TypeCUChar NonNumDict ||]--liftNumType :: NumType t -> Q (TExp (NumType t))-liftNumType (IntegralNumType t) = [|| IntegralNumType $$(liftIntegralType t) ||]-liftNumType (FloatingNumType t) = [|| FloatingNumType $$(liftFloatingType t) ||]--liftBoundedType :: BoundedType t -> Q (TExp (BoundedType t))-liftBoundedType (IntegralBoundedType t) = [|| IntegralBoundedType $$(liftIntegralType t) ||]-liftBoundedType (NonNumBoundedType t)   = [|| NonNumBoundedType $$(liftNonNumType t) ||]---- liftScalarType :: ScalarType t -> Q (TExp (ScalarType t))--- liftScalarType (SingleScalarType t) = [|| SingleScalarType $$(liftSingleType t) ||]--- liftScalarType (VectorScalarType t) = [|| VectorScalarType $$(liftVectorType t) ||]--liftSingleType :: SingleType t -> Q (TExp (SingleType t))-liftSingleType (NumSingleType t)    = [|| NumSingleType $$(liftNumType t) ||]-liftSingleType (NonNumSingleType t) = [|| NonNumSingleType $$(liftNonNumType t) ||]---- liftVectorType :: VectorType t -> Q (TExp (VectorType t))--- liftVectorType (Vector2Type t)  = [|| Vector2Type $$(liftSingleType t) ||]--- liftVectorType (Vector3Type t)  = [|| Vector3Type $$(liftSingleType t) ||]--- liftVectorType (Vector4Type t)  = [|| Vector4Type $$(liftSingleType t) ||]--- liftVectorType (Vector8Type t)  = [|| Vector8Type $$(liftSingleType t) ||]--- liftVectorType (Vector16Type t) = [|| Vector16Type $$(liftSingleType t) ||]----- Debugging--- =========--showPreAccOp :: forall acc aenv arrs. PreOpenAcc acc aenv arrs -> String-showPreAccOp Alet{}             = "Alet"-showPreAccOp (Avar ix)          = "Avar a" ++ show (idxToInt ix)-showPreAccOp (Use a)            = "Use "  ++ showArrays (toArr a :: arrs)-showPreAccOp Apply{}            = "Apply"-showPreAccOp Aforeign{}         = "Aforeign"-showPreAccOp Acond{}            = "Acond"-showPreAccOp Awhile{}           = "Awhile"-showPreAccOp Atuple{}           = "Atuple"-showPreAccOp Aprj{}             = "Aprj"-showPreAccOp Unit{}             = "Unit"-showPreAccOp Generate{}         = "Generate"-showPreAccOp Transform{}        = "Transform"-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 Collect{}          = "Collect"--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 :: forall acc env aenv t. PreOpenExp acc env aenv t -> String-showPreExpOp Let{}              = "Let"-showPreExpOp (Var ix)           = "Var x" ++ show (idxToInt ix)-showPreExpOp (Const c)          = "Const " ++ show (toElt c :: t)-showPreExpOp Undef              = "Undef"-showPreExpOp Foreign{}          = "Foreign"-showPreExpOp Tuple{}            = "Tuple"-showPreExpOp Prj{}              = "Prj"-showPreExpOp IndexNil           = "IndexNil"-showPreExpOp IndexCons{}        = "IndexCons"-showPreExpOp IndexHead{}        = "IndexHead"-showPreExpOp IndexTail{}        = "IndexTail"-showPreExpOp IndexAny           = "IndexAny"-showPreExpOp IndexSlice{}       = "IndexSlice"-showPreExpOp IndexFull{}        = "IndexFull"-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 Coerce{}           = "Coerce"+{-# LANGUAGE FlexibleContexts      #-}+{-# LANGUAGE FlexibleInstances     #-}+{-# LANGUAGE GADTs                 #-}+{-# LANGUAGE LambdaCase            #-}+{-# LANGUAGE RankNTypes            #-}+{-# LANGUAGE ScopedTypeVariables   #-}+{-# LANGUAGE TemplateHaskell       #-}+{-# LANGUAGE TypeFamilies          #-}+{-# LANGUAGE TypeOperators         #-}+{-# OPTIONS_HADDOCK hide #-}+-- |+-- Module      : Data.Array.Accelerate.AST+-- Copyright   : [2008..2020] The Accelerate Team+-- License     : BSD3+--+-- Maintainer  : Trevor L. McDonell <trevor.mcdonell@gmail.com>+-- Stability   : experimental+-- Portability : non-portable (GHC extensions)+--+-- /Scalar versus collective operations/+--+-- The embedded array processing language is a two-level language.  It+-- combines a language of scalar expressions and functions with a language of+-- collective array operations.  Scalar expressions are used to compute+-- arguments for collective operations and scalar functions are used to+-- parametrise higher-order, collective array operations.  The two-level+-- structure, in particular, ensures that collective operations cannot be+-- parametrised with collective operations; hence, we are following a flat+-- data-parallel model.  The collective operations manipulate+-- multi-dimensional arrays whose shape is explicitly tracked in their types.+-- In fact, collective operations cannot produce any values other than+-- multi-dimensional arrays; when they yield a scalar, this is in the form of+-- a 0-dimensional, singleton array.  Similarly, scalar expression can -as+-- their name indicates- only produce tuples of scalar, but not arrays.+--+-- There are, however, two expression forms that take arrays as arguments.  As+-- a result scalar and array expressions are recursively dependent.  As we+-- cannot and don't want to compute arrays in the middle of scalar+-- computations, array computations will always be hoisted out of scalar+-- expressions.  So that this is always possible, these array expressions may+-- not contain any free scalar variables.  To express that condition in the+-- type structure, we use separate environments for scalar and array variables.+--+-- /Programs/+--+-- Collective array programs comprise closed expressions of array operations.+-- There is no explicit sharing in the initial AST form, but sharing is+-- introduced subsequently by common subexpression elimination and floating+-- of array computations.+--+-- /Functions/+--+-- The array expression language is first-order and only provides limited+-- control structures to ensure that it can be efficiently executed on+-- compute-acceleration hardware, such as GPUs.  To restrict functions to+-- first-order, we separate function abstraction from the main expression+-- type.  Functions are represented using de Bruijn indices.+--+-- /Parametric and ad-hoc polymorphism/+--+-- The array language features paramatric polymophism (e.g., pairing and+-- projections) as well as ad-hoc polymorphism (e.g., arithmetic operations).+-- All ad-hoc polymorphic constructs include reified dictionaries (c.f.,+-- module 'Types').  Reified dictionaries also ensure that constants+-- (constructor 'Const') are representable on compute acceleration hardware.+--+-- The AST contains both reified dictionaries and type class constraints.+-- Type classes are used for array-related functionality that is uniformly+-- available for all supported types.  In contrast, reified dictionaries are+-- used for functionality that is only available for certain types, such as+-- arithmetic operations.+--++module Data.Array.Accelerate.AST (++  -- * Internal AST+  -- ** Array computations+  Afun, PreAfun, OpenAfun, PreOpenAfun(..),+  Acc, OpenAcc(..), PreOpenAcc(..), Direction(..),+  ALeftHandSide, ArrayVar, ArrayVars,++  -- ** Scalar expressions+  ELeftHandSide, ExpVar, ExpVars, expVars,+  Fun, OpenFun(..),+  Exp, OpenExp(..),+  Boundary(..),+  PrimConst(..),+  PrimFun(..),+  PrimBool,+  PrimMaybe,++  -- ** Extracting type information+  HasArraysR(..), arrayR,+  expType,+  primConstType,+  primFunType,++  -- ** Normal-form+  NFDataAcc,+  rnfOpenAfun, rnfPreOpenAfun,+  rnfOpenAcc, rnfPreOpenAcc,+  rnfALeftHandSide,+  rnfArrayVar,+  rnfOpenFun,+  rnfOpenExp,+  rnfELeftHandSide,+  rnfExpVar,+  rnfBoundary,+  rnfConst,+  rnfPrimConst,+  rnfPrimFun,++  -- ** Template Haskell+  LiftAcc,+  liftPreOpenAfun,+  liftPreOpenAcc,+  liftALeftHandSide,+  liftArrayVar,+  liftOpenFun,+  liftOpenExp,+  liftELeftHandSide,+  liftExpVar,+  liftBoundary,+  liftPrimConst,+  liftPrimFun,++  -- ** Miscellaneous+  showPreAccOp,+  showExpOp,++) where++import Data.Array.Accelerate.AST.Idx+import Data.Array.Accelerate.AST.LeftHandSide+import Data.Array.Accelerate.AST.Var+import Data.Array.Accelerate.Error+import Data.Array.Accelerate.Representation.Array+import Data.Array.Accelerate.Representation.Elt+import Data.Array.Accelerate.Representation.Shape+import Data.Array.Accelerate.Representation.Slice+import Data.Array.Accelerate.Representation.Stencil+import Data.Array.Accelerate.Representation.Tag+import Data.Array.Accelerate.Representation.Type+import Data.Array.Accelerate.Representation.Vec+import Data.Array.Accelerate.Sugar.Foreign+import Data.Array.Accelerate.Type+import Data.Primitive.Vec++import Control.DeepSeq+import Data.Kind+import Language.Haskell.TH                                          ( Q, TExp )+import Prelude++import GHC.TypeLits+++-- Array expressions+-- -----------------++-- | Function abstraction over parametrised array computations+--+data PreOpenAfun acc aenv t where+  Abody ::                               acc             aenv  t -> PreOpenAfun acc aenv t+  Alam  :: ALeftHandSide a aenv aenv' -> PreOpenAfun acc aenv' t -> PreOpenAfun acc aenv (a -> t)++-- Function abstraction over vanilla open array computations+--+type OpenAfun = PreOpenAfun OpenAcc++-- | Parametrised array-computation function without free array variables+--+type PreAfun acc = PreOpenAfun acc ()++-- | Vanilla array-computation function without free array variables+--+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 ()++-- Types for array binders+--+type ALeftHandSide  = LeftHandSide ArrayR+type ArrayVar       = Var ArrayR+type ArrayVars aenv = Vars ArrayR aenv++-- Bool is not a primitive type+type PrimBool    = TAG+type PrimMaybe a = (TAG, ((), a))+++-- | Collective array computations parametrised over array variables+-- represented with de Bruijn indices.+--+-- * Scalar functions and expressions embedded in well-formed array+--   computations cannot contain free scalar variable indices. The latter+--   cannot be bound in array computations, and hence, cannot appear in any+--   well-formed program.+--+-- * The let-form is used to represent the sharing discovered by common+--   subexpression elimination as well as to control evaluation order. (We+--   need to hoist array expressions out of scalar expressions---they occur+--   in scalar indexing and in determining an arrays shape.)+--+-- The data type is parameterised over the surface types (not the+-- representation type).+--+-- We use a non-recursive variant parametrised over the recursive closure,+-- to facilitate attribute calculation in the backend.+--+data PreOpenAcc (acc :: Type -> Type -> Type) aenv a where++  -- Local non-recursive binding to represent sharing and demand+  -- explicitly. Note this is an eager binding!+  --+  Alet        :: ALeftHandSide bndArrs aenv aenv'+              -> acc            aenv  bndArrs         -- bound expression+              -> acc            aenv' bodyArrs        -- the bound expression scope+              -> PreOpenAcc acc aenv  bodyArrs++  -- Variable bound by a 'Let', represented by a de Bruijn index+  --+  Avar        :: ArrayVar       aenv (Array sh e)+              -> PreOpenAcc acc aenv (Array sh e)++  -- Tuples of arrays+  --+  Apair       :: acc            aenv as+              -> acc            aenv bs+              -> PreOpenAcc acc aenv (as, bs)++  Anil        :: PreOpenAcc acc aenv ()++  -- Array-function application.+  --+  -- The array function is not closed at the core level because we need access+  -- to free variables introduced by 'run1' style evaluators. See Issue#95.+  --+  Apply       :: ArraysR arrs2+              -> PreOpenAfun acc aenv (arrs1 -> arrs2)+              -> acc             aenv arrs1+              -> PreOpenAcc  acc aenv arrs2++  -- 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    :: Foreign asm+              => ArraysR bs+              -> 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       :: Exp            aenv PrimBool+              -> acc            aenv arrs+              -> acc            aenv arrs+              -> PreOpenAcc acc aenv arrs++  -- Value-recursion for array-level computations+  --+  Awhile      :: PreOpenAfun acc aenv (arrs -> Scalar PrimBool) -- continue iteration while true+              -> PreOpenAfun acc aenv (arrs -> arrs)            -- function to iterate+              -> acc             aenv arrs                      -- initial value+              -> PreOpenAcc  acc aenv arrs+++  -- Array inlet. Triggers (possibly) asynchronous host->device transfer if+  -- necessary.+  --+  Use         :: ArrayR (Array sh e)+              -> Array sh e+              -> PreOpenAcc acc aenv (Array sh e)++  -- Capture a scalar (or a tuple of scalars) in a singleton array+  --+  Unit        :: TypeR e+              -> Exp            aenv e+              -> PreOpenAcc acc aenv (Scalar e)++  -- Change the shape of an array without altering its contents.+  -- Precondition (this may not be checked!):+  --+  -- > dim == size dim'+  --+  Reshape     :: ShapeR sh+              -> Exp            aenv sh                         -- new shape+              -> acc            aenv (Array sh' e)              -- array to be reshaped+              -> PreOpenAcc acc aenv (Array sh e)++  -- Construct a new array by applying a function to each index.+  --+  Generate    :: ArrayR (Array sh e)+              -> Exp            aenv sh                         -- output shape+              -> Fun            aenv (sh -> e)                  -- representation function+              -> PreOpenAcc acc aenv (Array sh e)++  -- Hybrid map/backpermute, where we separate the index and value+  -- transformations.+  --+  Transform   :: ArrayR (Array sh' b)+              -> Exp            aenv sh'                        -- dimension of the result+              -> Fun            aenv (sh' -> sh)                -- index permutation function+              -> Fun            aenv (a   -> b)                 -- function to apply at each element+              ->            acc aenv (Array sh  a)              -- source array+              -> PreOpenAcc acc aenv (Array sh' b)++  -- Replicate an array across one or more dimensions as given by the first+  -- argument+  --+  Replicate   :: SliceIndex slix sl co sh                       -- slice type specification+              -> Exp            aenv slix                       -- slice value specification+              -> acc            aenv (Array sl e)               -- data to be replicated+              -> PreOpenAcc acc aenv (Array sh e)++  -- Index a sub-array out of an array; i.e., the dimensions not indexed+  -- are returned whole+  --+  Slice       :: SliceIndex slix sl co sh                       -- slice type specification+              -> acc            aenv (Array sh e)               -- array to be indexed+              -> Exp            aenv slix                       -- slice value specification+              -> PreOpenAcc acc aenv (Array sl e)++  -- Apply the given unary function to all elements of the given array+  --+  Map         :: TypeR e'+              -> Fun            aenv (e -> e')+              -> acc            aenv (Array sh e)+              -> PreOpenAcc acc aenv (Array sh e')++  -- Apply a given binary function pairwise to all elements of the given+  -- arrays. The length of the result is the length of the shorter of the+  -- two argument arrays.+  --+  ZipWith     :: TypeR e3+              -> Fun            aenv (e1 -> e2 -> e3)+              -> acc            aenv (Array sh e1)+              -> acc            aenv (Array sh e2)+              -> PreOpenAcc acc aenv (Array sh e3)++  -- Fold along the innermost dimension of an array with a given+  -- /associative/ function.+  --+  Fold        :: Fun            aenv (e -> e -> e)              -- combination function+              -> Maybe     (Exp aenv e)                         -- default value+              -> acc            aenv (Array (sh, Int) e)        -- folded array+              -> PreOpenAcc acc aenv (Array sh e)++  -- Segmented fold along the innermost dimension of an array with a given+  -- /associative/ function+  --+  FoldSeg     :: IntegralType i+              -> Fun            aenv (e -> e -> e)              -- combination function+              -> Maybe     (Exp aenv e)                         -- default value+              -> acc            aenv (Array (sh, Int) e)        -- folded array+              -> acc            aenv (Segments i)               -- segment descriptor+              -> PreOpenAcc acc aenv (Array (sh, Int) e)++  -- Haskell-style scan of a linear array with a given+  -- /associative/ function and optionally an initial element+  -- (which does not need to be the neutral of the associative operations)+  -- If no initial value is given, this is a scan1+  --+  Scan        :: Direction+              -> Fun            aenv (e -> e -> e)              -- combination function+              -> Maybe     (Exp aenv e)                         -- initial value+              -> acc            aenv (Array (sh, Int) e)+              -> PreOpenAcc acc aenv (Array (sh, Int) e)++  -- Like 'Scan', but produces a rightmost (in case of a left-to-right scan)+  -- 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)+  --+  Scan'       :: Direction+              -> Fun            aenv (e -> e -> e)              -- combination function+              -> Exp            aenv e                          -- initial value+              -> acc            aenv (Array (sh, Int) e)+              -> PreOpenAcc acc aenv (Array (sh, Int) e, Array sh e)++  -- Generalised forward permutation is characterised by a permutation function+  -- that determines for each element of the source array where it should go in+  -- the output. The permutation can be between arrays of varying shape and+  -- dimensionality.+  --+  -- Other characteristics of the permutation function 'f':+  --+  --   1. 'f' is a partial function: if it evaluates to the magic value 'ignore'+  --      (i.e. a tuple of -1 values) then those elements of the domain are+  --      dropped.+  --+  --   2. 'f' is not surjective: positions in the target array need not be+  --      picked up by the permutation function, so the target array must first+  --      be initialised from an array of default values.+  --+  --   3. 'f' is not injective: distinct elements of the domain may map to the+  --      same position in the target array. In this case the combination+  --      function is used to combine elements, which needs to be /associative/+  --      and /commutative/.+  --+  Permute     :: Fun            aenv (e -> e -> e)              -- combination function+              -> acc            aenv (Array sh' e)              -- default values+              -> Fun            aenv (sh -> PrimMaybe sh')      -- permutation function+              -> acc            aenv (Array sh e)               -- source array+              -> PreOpenAcc acc aenv (Array sh' e)++  -- Generalised multi-dimensional backwards permutation; the permutation can+  -- be between arrays of varying shape; the permutation function must be total+  --+  Backpermute :: ShapeR sh'+              -> Exp            aenv sh'                        -- dimensions of the result+              -> Fun            aenv (sh' -> sh)                -- permutation function+              -> acc            aenv (Array sh e)               -- source array+              -> PreOpenAcc acc aenv (Array sh' e)++  -- Map a stencil over an array.  In contrast to 'map', the domain of+  -- a stencil function is an entire /neighbourhood/ of each array element.+  --+  Stencil     :: StencilR sh e stencil+              -> TypeR e'+              -> Fun             aenv (stencil -> e')           -- stencil function+              -> Boundary        aenv (Array sh e)              -- boundary condition+              -> acc             aenv (Array sh e)              -- source array+              -> PreOpenAcc  acc aenv (Array sh e')++  -- Map a binary stencil over an array.+  --+  Stencil2    :: StencilR sh a stencil1+              -> StencilR sh b stencil2+              -> TypeR c+              -> Fun             aenv (stencil1 -> stencil2 -> c) -- stencil function+              -> Boundary        aenv (Array sh a)                -- boundary condition #1+              -> acc             aenv (Array sh a)                -- source array #1+              -> Boundary        aenv (Array sh b)                -- boundary condition #2+              -> acc             aenv (Array sh b)                -- source array #2+              -> PreOpenAcc acc  aenv (Array sh c)+++data Direction = LeftToRight | RightToLeft+  deriving Eq+++-- | Vanilla boundary condition specification for stencil operations+--+data Boundary aenv t where+  -- Clamp coordinates to the extent of the array+  Clamp     :: Boundary aenv t++  -- Mirror coordinates beyond the array extent+  Mirror    :: Boundary aenv t++  -- Wrap coordinates around on each dimension+  Wrap      :: Boundary aenv t++  -- Use a constant value for outlying coordinates+  Constant  :: e+            -> Boundary aenv (Array sh e)++  -- Apply the given function to outlying coordinates+  Function  :: Fun aenv (sh -> e)+            -> Boundary aenv (Array sh e)+++-- Embedded expressions+-- --------------------++-- | Vanilla open function abstraction+--+data OpenFun env aenv t where+  Body ::                             OpenExp env  aenv t -> OpenFun env aenv t+  Lam  :: ELeftHandSide a env env' -> OpenFun env' aenv t -> OpenFun env aenv (a -> t)++-- | Vanilla function without free scalar variables+--+type Fun = OpenFun ()++-- | Vanilla expression without free scalar variables+--+type Exp = OpenExp ()++-- Types for scalar bindings+--+type ELeftHandSide = LeftHandSide ScalarType+type ExpVar        = Var ScalarType+type ExpVars env   = Vars ScalarType env++expVars :: ExpVars env t -> OpenExp env aenv t+expVars TupRunit         = Nil+expVars (TupRsingle var) = Evar var+expVars (TupRpair v1 v2) = expVars v1 `Pair` expVars v2+++-- | Vanilla 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.+--+-- The data type is parametrised over the representation type (not the+-- surface types).+--+data OpenExp env aenv t where++  -- Local binding of a scalar expression+  Let           :: ELeftHandSide bnd_t env env'+                -> OpenExp env  aenv bnd_t+                -> OpenExp env' aenv body_t+                -> OpenExp env  aenv body_t++  -- Variable index, ranging only over tuples or scalars+  Evar          :: ExpVar env t+                -> OpenExp env aenv t++  -- Apply a backend-specific foreign function+  Foreign       :: Foreign asm+                => TypeR y+                -> asm    (x -> y)    -- foreign function+                -> Fun () (x -> y)    -- alternate implementation (for other backends)+                -> OpenExp env aenv x+                -> OpenExp env aenv y++  -- Tuples+  Pair          :: OpenExp env aenv t1+                -> OpenExp env aenv t2+                -> OpenExp env aenv (t1, t2)++  Nil           :: OpenExp env aenv ()++  -- SIMD vectors+  VecPack       :: KnownNat n+                => VecR n s tup+                -> OpenExp env aenv tup+                -> OpenExp env aenv (Vec n s)++  VecUnpack     :: KnownNat n+                => VecR n s tup+                -> OpenExp env aenv (Vec n s)+                -> OpenExp env aenv tup++  -- Array indices & shapes+  IndexSlice    :: SliceIndex slix sl co sh+                -> OpenExp env aenv slix+                -> OpenExp env aenv sh+                -> OpenExp env aenv sl++  IndexFull     :: SliceIndex slix sl co sh+                -> OpenExp env aenv slix+                -> OpenExp env aenv sl+                -> OpenExp env aenv sh++  -- Shape and index conversion+  ToIndex       :: ShapeR sh+                -> OpenExp env aenv sh           -- shape of the array+                -> OpenExp env aenv sh           -- index into the array+                -> OpenExp env aenv Int++  FromIndex     :: ShapeR sh+                -> OpenExp env aenv sh           -- shape of the array+                -> OpenExp env aenv Int          -- index into linear representation+                -> OpenExp env aenv sh++  -- Case statement+  Case          :: OpenExp env aenv TAG+                -> [(TAG, OpenExp env aenv b)]      -- list of equations+                -> Maybe (OpenExp env aenv b)       -- default case+                -> OpenExp env aenv b++  -- Conditional expression (non-strict in 2nd and 3rd argument)+  Cond          :: OpenExp env aenv PrimBool+                -> OpenExp env aenv t+                -> OpenExp env aenv t+                -> OpenExp env aenv t++  -- Value recursion+  While         :: OpenFun env aenv (a -> PrimBool) -- continue while true+                -> OpenFun env aenv (a -> a)        -- function to iterate+                -> OpenExp env aenv a               -- initial value+                -> OpenExp env aenv a++  -- Constant values+  Const         :: ScalarType t+                -> t+                -> OpenExp env aenv t++  PrimConst     :: PrimConst t+                -> OpenExp env aenv t++  -- Primitive scalar operations+  PrimApp       :: PrimFun (a -> r)+                -> OpenExp env aenv a+                -> OpenExp env aenv r++  -- Project a single scalar from an array.+  -- The array expression can not contain any free scalar variables.+  Index         :: ArrayVar    aenv (Array dim t)+                -> OpenExp env aenv dim+                -> OpenExp env aenv t++  LinearIndex   :: ArrayVar    aenv (Array dim t)+                -> OpenExp env aenv Int+                -> OpenExp env aenv t++  -- Array shape.+  -- The array expression can not contain any free scalar variables.+  Shape         :: ArrayVar    aenv (Array dim e)+                -> OpenExp env aenv dim++  -- Number of elements of an array given its shape+  ShapeSize     :: ShapeR dim+                -> OpenExp env aenv dim+                -> OpenExp env aenv Int++  -- Unsafe operations (may fail or result in undefined behaviour)+  -- An unspecified bit pattern+  Undef         :: ScalarType t+                -> OpenExp env aenv t++  -- Reinterpret the bits of a value as a different type+  Coerce        :: BitSizeEq a b+                => ScalarType a+                -> ScalarType b+                -> OpenExp env aenv a+                -> OpenExp env aenv b++-- |Primitive constant values+--+data PrimConst ty where++  -- constants from Bounded+  PrimMinBound  :: BoundedType a -> PrimConst a+  PrimMaxBound  :: BoundedType a -> PrimConst a++  -- constant from Floating+  PrimPi        :: FloatingType a -> PrimConst a+++-- |Primitive scalar operations+--+data PrimFun sig where++  -- operators from Num+  PrimAdd  :: NumType a -> PrimFun ((a, a) -> a)+  PrimSub  :: NumType a -> PrimFun ((a, a) -> a)+  PrimMul  :: NumType a -> PrimFun ((a, a) -> a)+  PrimNeg  :: NumType a -> PrimFun (a      -> a)+  PrimAbs  :: NumType a -> PrimFun (a      -> a)+  PrimSig  :: NumType a -> PrimFun (a      -> a)++  -- 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)+  PrimDivMod   :: IntegralType a -> PrimFun ((a, a)   -> (a, a))++  -- 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)+  PrimCos         :: FloatingType a -> PrimFun (a      -> a)+  PrimTan         :: FloatingType a -> PrimFun (a      -> a)+  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)+  PrimExpFloating :: FloatingType a -> PrimFun (a      -> a)+  PrimSqrt        :: FloatingType a -> PrimFun (a      -> a)+  PrimLog         :: FloatingType a -> PrimFun (a      -> a)+  PrimFPow        :: FloatingType a -> PrimFun ((a, a) -> a)+  PrimLogBase     :: FloatingType a -> PrimFun ((a, a) -> a)++  -- 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+  PrimAtan2      :: FloatingType a -> PrimFun ((a, a) -> a)+  PrimIsNaN      :: FloatingType a -> PrimFun (a -> PrimBool)+  PrimIsInfinite :: FloatingType a -> PrimFun (a -> PrimBool)++  -- relational and equality operators+  PrimLt   :: SingleType a -> PrimFun ((a, a) -> PrimBool)+  PrimGt   :: SingleType a -> PrimFun ((a, a) -> PrimBool)+  PrimLtEq :: SingleType a -> PrimFun ((a, a) -> PrimBool)+  PrimGtEq :: SingleType a -> PrimFun ((a, a) -> PrimBool)+  PrimEq   :: SingleType a -> PrimFun ((a, a) -> PrimBool)+  PrimNEq  :: SingleType a -> PrimFun ((a, a) -> PrimBool)+  PrimMax  :: SingleType a -> PrimFun ((a, a) -> a)+  PrimMin  :: SingleType a -> PrimFun ((a, a) -> a)++  -- logical operators+  --+  -- Note that these operators are strict in both arguments. That is, the+  -- second argument of PrimLAnd is always evaluated even when the first+  -- argument is false.+  --+  -- We define (surface level) (&&) and (||) using if-then-else to enable+  -- short-circuiting, while (&&!) and (||!) are strict versions of these+  -- operators, which are defined using PrimLAnd and PrimLOr.+  --+  PrimLAnd :: PrimFun ((PrimBool, PrimBool) -> PrimBool)+  PrimLOr  :: PrimFun ((PrimBool, PrimBool) -> PrimBool)+  PrimLNot :: PrimFun (PrimBool             -> PrimBool)++  -- general conversion between types+  PrimFromIntegral :: IntegralType a -> NumType b -> PrimFun (a -> b)+  PrimToFloating   :: NumType a -> FloatingType b -> PrimFun (a -> b)+++-- Type utilities+-- --------------++class HasArraysR f where+  arraysR :: f aenv a -> ArraysR a++instance HasArraysR OpenAcc where+  arraysR (OpenAcc a) = arraysR a++arrayR :: HasArraysR f => f aenv (Array sh e) -> ArrayR (Array sh e)+arrayR a = case arraysR a of+  TupRsingle aR -> aR++instance HasArraysR acc => HasArraysR (PreOpenAcc acc) where+  arraysR (Alet _ _ body)             = arraysR body+  arraysR (Avar (Var aR _))           = TupRsingle aR+  arraysR (Apair as bs)               = TupRpair (arraysR as) (arraysR bs)+  arraysR Anil                        = TupRunit+  arraysR (Apply aR _ _)              = aR+  arraysR (Aforeign r _ _ _)          = r+  arraysR (Acond _ a _)               = arraysR a+  arraysR (Awhile _ (Alam lhs _) _)   = lhsToTupR lhs+  arraysR Awhile{}                    = error "I want my, I want my MTV!"+  arraysR (Use aR _)                  = TupRsingle aR+  arraysR (Unit tR _)                 = arraysRarray ShapeRz tR+  arraysR (Reshape sh _ a)            = let ArrayR _ tR = arrayR a+                                         in arraysRarray sh tR+  arraysR (Generate aR _ _)           = TupRsingle aR+  arraysR (Transform aR _ _ _ _)      = TupRsingle aR+  arraysR (Replicate slice _ a)       = let ArrayR _ tR = arrayR a+                                         in arraysRarray (sliceDomainR slice) tR+  arraysR (Slice slice a _)           = let ArrayR _ tR = arrayR a+                                         in arraysRarray (sliceShapeR slice) tR+  arraysR (Map tR _ a)                = let ArrayR sh _ = arrayR a+                                         in arraysRarray sh tR+  arraysR (ZipWith tR _ a _)          = let ArrayR sh _ = arrayR a+                                         in arraysRarray sh tR+  arraysR (Fold _ _ a)                = let ArrayR (ShapeRsnoc sh) tR = arrayR a+                                         in arraysRarray sh tR+  arraysR (FoldSeg _ _ _ a _)         = arraysR a+  arraysR (Scan _ _ _ a)              = arraysR a+  arraysR (Scan' _ _ _ a)             = let aR@(ArrayR (ShapeRsnoc sh) tR) = arrayR a+                                         in TupRsingle aR `TupRpair` TupRsingle (ArrayR sh tR)+  arraysR (Permute _ a _ _)           = arraysR a+  arraysR (Backpermute sh _ _ a)      = let ArrayR _ tR = arrayR a+                                         in arraysRarray sh tR+  arraysR (Stencil _ tR _ _ a)        = let ArrayR sh _ = arrayR a+                                         in arraysRarray sh tR+  arraysR (Stencil2 _ _ tR _ _ a _ _) = let ArrayR sh _ = arrayR a+                                         in arraysRarray sh tR++expType :: HasCallStack => OpenExp aenv env t -> TypeR t+expType = \case+  Let _ _ body                 -> expType body+  Evar (Var tR _)              -> TupRsingle tR+  Foreign tR _ _ _             -> tR+  Pair e1 e2                   -> TupRpair (expType e1) (expType e2)+  Nil                          -> TupRunit+  VecPack   vecR _             -> TupRsingle $ VectorScalarType $ vecRvector vecR+  VecUnpack vecR _             -> vecRtuple vecR+  IndexSlice si _ _            -> shapeType $ sliceShapeR si+  IndexFull  si _ _            -> shapeType $ sliceDomainR si+  ToIndex{}                    -> TupRsingle scalarTypeInt+  FromIndex shr _ _            -> shapeType shr+  Case _ ((_,e):_) _           -> expType e+  Case _ [] (Just e)           -> expType e+  Case{}                       -> internalError "empty case encountered"+  Cond _ e _                   -> expType e+  While _ (Lam lhs _) _        -> lhsToTupR lhs+  While{}                      -> error "What's the matter, you're running in the shadows"+  Const tR _                   -> TupRsingle tR+  PrimConst c                  -> TupRsingle $ SingleScalarType $ primConstType c+  PrimApp f _                  -> snd $ primFunType f+  Index (Var repr _) _         -> arrayRtype repr+  LinearIndex (Var repr _) _   -> arrayRtype repr+  Shape (Var repr _)           -> shapeType $ arrayRshape repr+  ShapeSize{}                  -> TupRsingle scalarTypeInt+  Undef tR                     -> TupRsingle tR+  Coerce _ tR _                -> TupRsingle tR++primConstType :: PrimConst a -> SingleType a+primConstType = \case+  PrimMinBound t -> bounded t+  PrimMaxBound t -> bounded t+  PrimPi       t -> floating t+  where+    bounded :: BoundedType a -> SingleType a+    bounded (IntegralBoundedType t) = NumSingleType $ IntegralNumType t++    floating :: FloatingType t -> SingleType t+    floating = NumSingleType . FloatingNumType++primFunType :: PrimFun (a -> b) -> (TypeR a, TypeR b)+primFunType = \case+  -- Num+  PrimAdd t                 -> binary' $ num t+  PrimSub t                 -> binary' $ num t+  PrimMul t                 -> binary' $ num t+  PrimNeg t                 -> unary'  $ num t+  PrimAbs t                 -> unary'  $ num t+  PrimSig t                 -> unary'  $ num t++  -- Integral+  PrimQuot t                -> binary' $ integral t+  PrimRem  t                -> binary' $ integral t+  PrimQuotRem t             -> unary' $ integral t `TupRpair` integral t+  PrimIDiv t                -> binary' $ integral t+  PrimMod  t                -> binary' $ integral t+  PrimDivMod t              -> unary' $ integral t `TupRpair` integral t++  -- Bits & FiniteBits+  PrimBAnd t                -> binary' $ integral t+  PrimBOr t                 -> binary' $ integral t+  PrimBXor t                -> binary' $ integral t+  PrimBNot t                -> unary' $ integral t+  PrimBShiftL t             -> (integral t `TupRpair` int, integral t)+  PrimBShiftR t             -> (integral t `TupRpair` int, integral t)+  PrimBRotateL t            -> (integral t `TupRpair` int, integral t)+  PrimBRotateR t            -> (integral t `TupRpair` int, integral t)+  PrimPopCount t            -> unary (integral t) int+  PrimCountLeadingZeros t   -> unary (integral t) int+  PrimCountTrailingZeros t  -> unary (integral t) int++  -- Fractional, Floating+  PrimFDiv t                -> binary' $ floating t+  PrimRecip t               -> unary'  $ floating t+  PrimSin t                 -> unary'  $ floating t+  PrimCos t                 -> unary'  $ floating t+  PrimTan t                 -> unary'  $ floating t+  PrimAsin t                -> unary'  $ floating t+  PrimAcos t                -> unary'  $ floating t+  PrimAtan t                -> unary'  $ floating t+  PrimSinh t                -> unary'  $ floating t+  PrimCosh t                -> unary'  $ floating t+  PrimTanh t                -> unary'  $ floating t+  PrimAsinh t               -> unary'  $ floating t+  PrimAcosh t               -> unary'  $ floating t+  PrimAtanh t               -> unary'  $ floating t+  PrimExpFloating t         -> unary'  $ floating t+  PrimSqrt t                -> unary'  $ floating t+  PrimLog t                 -> unary'  $ floating t+  PrimFPow t                -> binary' $ floating t+  PrimLogBase t             -> binary' $ floating t++  -- RealFrac+  PrimTruncate a b          -> unary (floating a) (integral b)+  PrimRound a b             -> unary (floating a) (integral b)+  PrimFloor a b             -> unary (floating a) (integral b)+  PrimCeiling a b           -> unary (floating a) (integral b)++  -- RealFloat+  PrimAtan2 t               -> binary' $ floating t+  PrimIsNaN t               -> unary (floating t) bool+  PrimIsInfinite t          -> unary (floating t) bool++  -- Relational and equality+  PrimLt t                  -> compare' t+  PrimGt t                  -> compare' t+  PrimLtEq t                -> compare' t+  PrimGtEq t                -> compare' t+  PrimEq t                  -> compare' t+  PrimNEq t                 -> compare' t+  PrimMax t                 -> binary' $ single t+  PrimMin t                 -> binary' $ single t++  -- Logical+  PrimLAnd                  -> binary' bool+  PrimLOr                   -> binary' bool+  PrimLNot                  -> unary' bool++  -- general conversion between types+  PrimFromIntegral a b      -> unary (integral a) (num b)+  PrimToFloating   a b      -> unary (num a) (floating b)++  where+    unary a b  = (a, b)+    unary' a   = unary a a+    binary a b = (a `TupRpair` a, b)+    binary' a  = binary a a+    compare' a = binary (single a) bool++    single   = TupRsingle . SingleScalarType+    num      = TupRsingle . SingleScalarType . NumSingleType+    integral = num . IntegralNumType+    floating = num . FloatingNumType++    bool     = TupRsingle scalarTypeWord8+    int      = TupRsingle scalarTypeInt+++-- Normal form data+-- ================++instance NFData (OpenAfun aenv f) where+  rnf = rnfOpenAfun++instance NFData (OpenAcc aenv t) where+  rnf = rnfOpenAcc++instance NFData (OpenExp env aenv t) where+  rnf = rnfOpenExp++instance NFData (OpenFun env aenv t) where+  rnf = rnfOpenFun+++type NFDataAcc acc = forall aenv t. acc aenv t -> ()++rnfOpenAfun :: OpenAfun aenv t -> ()+rnfOpenAfun = rnfPreOpenAfun rnfOpenAcc++rnfPreOpenAfun :: NFDataAcc acc -> PreOpenAfun acc aenv t -> ()+rnfPreOpenAfun rnfA (Abody b) = rnfA b+rnfPreOpenAfun rnfA (Alam lhs f) = rnfALeftHandSide lhs `seq` rnfPreOpenAfun rnfA f++rnfOpenAcc :: OpenAcc aenv t -> ()+rnfOpenAcc (OpenAcc pacc) = rnfPreOpenAcc rnfOpenAcc pacc++rnfPreOpenAcc :: forall acc aenv t. HasArraysR acc => NFDataAcc acc -> PreOpenAcc acc aenv t -> ()+rnfPreOpenAcc rnfA pacc =+  let+      rnfAF :: PreOpenAfun acc aenv' t' -> ()+      rnfAF = rnfPreOpenAfun rnfA++      rnfE :: OpenExp env' aenv' t' -> ()+      rnfE = rnfOpenExp++      rnfF :: OpenFun env' aenv' t' -> ()+      rnfF = rnfOpenFun++      rnfB :: ArrayR (Array sh e) -> Boundary aenv' (Array sh e) -> ()+      rnfB = rnfBoundary+  in+  case pacc of+    Alet lhs bnd body         -> rnfALeftHandSide lhs `seq` rnfA bnd `seq` rnfA body+    Avar var                  -> rnfArrayVar var+    Apair as bs               -> rnfA as `seq` rnfA bs+    Anil                      -> ()+    Apply repr afun acc       -> rnfTupR rnfArrayR repr `seq` rnfAF afun `seq` rnfA acc+    Aforeign repr asm afun a  -> rnfTupR rnfArrayR repr `seq` 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 repr arr              -> rnfArray repr arr+    Unit tp x                 -> rnfTypeR tp `seq` rnfE x+    Reshape shr sh a          -> rnfShapeR shr `seq` rnfE sh `seq` rnfA a+    Generate repr sh f        -> rnfArrayR repr `seq` rnfE sh `seq` rnfF f+    Transform repr sh p f a   -> rnfArrayR repr `seq` 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 tp f a                -> rnfTypeR tp `seq` rnfF f `seq` rnfA a+    ZipWith tp f a1 a2        -> rnfTypeR tp `seq` rnfF f `seq` rnfA a1 `seq` rnfA a2+    Fold f z a                -> rnfF f `seq` rnfMaybe rnfE z `seq` rnfA a+    FoldSeg i f z a s         -> rnfIntegralType i `seq` rnfF f `seq` rnfMaybe rnfE z `seq` rnfA a `seq` rnfA s+    Scan d f z a              -> d `seq` rnfF f `seq` rnfMaybe rnfE z `seq` rnfA a+    Scan' d f z a             -> d `seq` 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 shr sh f a    -> rnfShapeR shr `seq` rnfE sh `seq` rnfF f `seq` rnfA a+    Stencil sr tp f b a       ->+      let+        TupRsingle (ArrayR shr _) = arraysR a+        repr                      = ArrayR shr $ stencilEltR sr+      in rnfStencilR sr `seq` rnfTupR rnfScalarType tp `seq` rnfF f `seq` rnfB repr b  `seq` rnfA a+    Stencil2 sr1 sr2 tp f b1 a1 b2 a2 ->+      let+        TupRsingle (ArrayR shr _) = arraysR a1+        repr1 = ArrayR shr $ stencilEltR sr1+        repr2 = ArrayR shr $ stencilEltR sr2+      in rnfStencilR sr1 `seq` rnfStencilR sr2 `seq` rnfTupR rnfScalarType tp `seq` rnfF f `seq` rnfB repr1 b1 `seq` rnfB repr2 b2 `seq` rnfA a1 `seq` rnfA a2++rnfArrayVar :: ArrayVar aenv a -> ()+rnfArrayVar = rnfVar rnfArrayR++rnfALeftHandSide :: ALeftHandSide arrs aenv aenv' -> ()+rnfALeftHandSide = rnfLeftHandSide rnfArrayR++rnfBoundary :: forall aenv sh e. ArrayR (Array sh e) -> Boundary aenv (Array sh e) -> ()+rnfBoundary _             Clamp        = ()+rnfBoundary _             Mirror       = ()+rnfBoundary _             Wrap         = ()+rnfBoundary (ArrayR _ tR) (Constant c) = rnfConst tR c+rnfBoundary _             (Function f) = rnfOpenFun f++rnfMaybe :: (a -> ()) -> Maybe a -> ()+rnfMaybe _ Nothing  = ()+rnfMaybe f (Just x) = f x++rnfList :: (a -> ()) -> [a] -> ()+rnfList r = go+  where+    go []     = ()+    go (x:xs) = r x `seq` go xs++rnfOpenFun :: OpenFun env aenv t -> ()+rnfOpenFun (Body b)    = rnfOpenExp b+rnfOpenFun (Lam lhs f) = rnfELeftHandSide lhs `seq` rnfOpenFun f++rnfOpenExp :: forall env aenv t. OpenExp env aenv t -> ()+rnfOpenExp topExp =+  let+      rnfF :: OpenFun env' aenv' t' -> ()+      rnfF = rnfOpenFun++      rnfE :: OpenExp env' aenv' t' -> ()+      rnfE = rnfOpenExp+  in+  case topExp of+    Let lhs bnd body          -> rnfELeftHandSide lhs `seq` rnfE bnd `seq` rnfE body+    Evar v                    -> rnfExpVar v+    Foreign tp asm f x        -> rnfTypeR tp `seq` rnf (strForeign asm) `seq` rnfF f `seq` rnfE x+    Const tp c                -> c `seq` rnfScalarType tp -- scalars should have (nf == whnf)+    Undef tp                  -> rnfScalarType tp+    Pair a b                  -> rnfE a `seq` rnfE b+    Nil                       -> ()+    VecPack   vecr e          -> rnfVecR vecr `seq` rnfE e+    VecUnpack vecr e          -> rnfVecR vecr `seq` rnfE e+    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 shr sh ix         -> rnfShapeR shr `seq` rnfE sh `seq` rnfE ix+    FromIndex shr sh ix       -> rnfShapeR shr `seq` rnfE sh `seq` rnfE ix+    Case e rhs def            -> rnfE e `seq` rnfList (\(t,c) -> t `seq` rnfE c) rhs `seq` rnfMaybe rnfE def+    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                -> rnfArrayVar a `seq` rnfE ix+    LinearIndex a ix          -> rnfArrayVar a `seq` rnfE ix+    Shape a                   -> rnfArrayVar a+    ShapeSize shr sh          -> rnfShapeR shr `seq` rnfE sh+    Coerce t1 t2 e            -> rnfScalarType t1 `seq` rnfScalarType t2 `seq` rnfE e++rnfExpVar :: ExpVar env t -> ()+rnfExpVar = rnfVar rnfScalarType++rnfELeftHandSide :: ELeftHandSide t env env' -> ()+rnfELeftHandSide= rnfLeftHandSide rnfScalarType++rnfConst :: TypeR t -> t -> ()+rnfConst TupRunit          ()    = ()+rnfConst (TupRsingle t)    !_    = rnfScalarType t  -- scalars should have (nf == whnf)+rnfConst (TupRpair 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 (PrimIsInfinite t)         = rnfFloatingType t+rnfPrimFun (PrimAtan2 t)              = rnfFloatingType t+rnfPrimFun (PrimLt t)                 = rnfSingleType t+rnfPrimFun (PrimGt t)                 = rnfSingleType t+rnfPrimFun (PrimLtEq t)               = rnfSingleType t+rnfPrimFun (PrimGtEq t)               = rnfSingleType t+rnfPrimFun (PrimEq t)                 = rnfSingleType t+rnfPrimFun (PrimNEq t)                = rnfSingleType t+rnfPrimFun (PrimMax t)                = rnfSingleType t+rnfPrimFun (PrimMin t)                = rnfSingleType t+rnfPrimFun PrimLAnd                   = ()+rnfPrimFun PrimLOr                    = ()+rnfPrimFun PrimLNot                   = ()+rnfPrimFun (PrimFromIntegral i n)     = rnfIntegralType i `seq` rnfNumType n+rnfPrimFun (PrimToFloating n f)       = rnfNumType n `seq` rnfFloatingType f+++-- Template Haskell+-- ================++type LiftAcc acc = forall aenv a. acc aenv a -> Q (TExp (acc aenv a))++liftPreOpenAfun :: LiftAcc acc -> PreOpenAfun acc aenv t -> Q (TExp (PreOpenAfun acc aenv t))+liftPreOpenAfun liftA (Alam lhs f) = [|| Alam $$(liftALeftHandSide lhs) $$(liftPreOpenAfun liftA f) ||]+liftPreOpenAfun liftA (Abody b)    = [|| Abody $$(liftA b) ||]++liftPreOpenAcc+    :: forall acc aenv a.+       HasArraysR acc+    => LiftAcc acc+    -> PreOpenAcc acc aenv a+    -> Q (TExp (PreOpenAcc acc aenv a))+liftPreOpenAcc liftA pacc =+  let+      liftE :: OpenExp env aenv t -> Q (TExp (OpenExp env aenv t))+      liftE = liftOpenExp++      liftF :: OpenFun env aenv t -> Q (TExp (OpenFun env aenv t))+      liftF = liftOpenFun++      liftAF :: PreOpenAfun acc aenv f -> Q (TExp (PreOpenAfun acc aenv f))+      liftAF = liftPreOpenAfun liftA++      liftB :: ArrayR (Array sh e) -> Boundary aenv (Array sh e) -> Q (TExp (Boundary aenv (Array sh e)))+      liftB = liftBoundary++  in+  case pacc of+    Alet lhs bnd body         -> [|| Alet $$(liftALeftHandSide lhs) $$(liftA bnd) $$(liftA body) ||]+    Avar var                  -> [|| Avar $$(liftArrayVar var) ||]+    Apair as bs               -> [|| Apair $$(liftA as) $$(liftA bs) ||]+    Anil                      -> [|| Anil ||]+    Apply repr f a            -> [|| Apply $$(liftArraysR repr) $$(liftAF f) $$(liftA a) ||]+    Aforeign repr asm f a     -> [|| Aforeign $$(liftArraysR repr) $$(liftForeign asm) $$(liftPreOpenAfun liftA f) $$(liftA a) ||]+    Acond p t e               -> [|| Acond $$(liftE p) $$(liftA t) $$(liftA e) ||]+    Awhile p f a              -> [|| Awhile $$(liftAF p) $$(liftAF f) $$(liftA a) ||]+    Use repr a                -> [|| Use $$(liftArrayR repr) $$(liftArray repr a) ||]+    Unit tp e                 -> [|| Unit $$(liftTypeR tp) $$(liftE e) ||]+    Reshape shr sh a          -> [|| Reshape $$(liftShapeR shr) $$(liftE sh) $$(liftA a) ||]+    Generate repr sh f        -> [|| Generate $$(liftArrayR repr) $$(liftE sh) $$(liftF f) ||]+    Transform repr sh p f a   -> [|| Transform $$(liftArrayR repr) $$(liftE sh) $$(liftF p) $$(liftF f) $$(liftA a) ||]+    Replicate slix sl a       -> [|| Replicate $$(liftSliceIndex slix) $$(liftE sl) $$(liftA a) ||]+    Slice slix a sh           -> [|| Slice $$(liftSliceIndex slix) $$(liftA a) $$(liftE sh) ||]+    Map tp f a                -> [|| Map $$(liftTypeR tp) $$(liftF f) $$(liftA a) ||]+    ZipWith tp f a b          -> [|| ZipWith $$(liftTypeR tp) $$(liftF f) $$(liftA a) $$(liftA b) ||]+    Fold f z a                -> [|| Fold $$(liftF f) $$(liftMaybe liftE z) $$(liftA a) ||]+    FoldSeg i f z a s         -> [|| FoldSeg $$(liftIntegralType i) $$(liftF f) $$(liftMaybe liftE z) $$(liftA a) $$(liftA s) ||]+    Scan d f z a              -> [|| Scan  $$(liftDirection d) $$(liftF f) $$(liftMaybe liftE z) $$(liftA a) ||]+    Scan' d f z a             -> [|| Scan' $$(liftDirection d) $$(liftF f) $$(liftE z) $$(liftA a) ||]+    Permute f d p a           -> [|| Permute $$(liftF f) $$(liftA d) $$(liftF p) $$(liftA a) ||]+    Backpermute shr sh p a    -> [|| Backpermute $$(liftShapeR shr) $$(liftE sh) $$(liftF p) $$(liftA a) ||]+    Stencil sr tp f b a       ->+      let+        TupRsingle (ArrayR shr _) = arraysR a+        repr = ArrayR shr $ stencilEltR sr+      in [|| Stencil $$(liftStencilR sr) $$(liftTypeR tp) $$(liftF f) $$(liftB repr b) $$(liftA a) ||]+    Stencil2 sr1 sr2 tp f b1 a1 b2 a2 ->+      let+        TupRsingle (ArrayR shr _) = arraysR a1+        repr1 = ArrayR shr $ stencilEltR sr1+        repr2 = ArrayR shr $ stencilEltR sr2+      in [|| Stencil2 $$(liftStencilR sr1) $$(liftStencilR sr2) $$(liftTypeR tp) $$(liftF f) $$(liftB repr1 b1) $$(liftA a1) $$(liftB repr2 b2) $$(liftA a2) ||]+++liftALeftHandSide :: ALeftHandSide arrs aenv aenv' -> Q (TExp (ALeftHandSide arrs aenv aenv'))+liftALeftHandSide = liftLeftHandSide liftArrayR++liftArrayVar :: ArrayVar aenv a -> Q (TExp (ArrayVar aenv a))+liftArrayVar = liftVar liftArrayR++liftDirection :: Direction -> Q (TExp Direction)+liftDirection LeftToRight = [|| LeftToRight ||]+liftDirection RightToLeft = [|| RightToLeft ||]++liftMaybe :: (a -> Q (TExp a)) -> Maybe a -> Q (TExp (Maybe a))+liftMaybe _ Nothing  = [|| Nothing ||]+liftMaybe f (Just x) = [|| Just $$(f x) ||]++liftList :: (a -> Q (TExp a)) -> [a] -> Q (TExp [a])+liftList _ []     = [|| [] ||]+liftList f (x:xs) = [|| $$(f x) : $$(liftList f xs) ||]++liftOpenFun+    :: OpenFun env aenv t+    -> Q (TExp (OpenFun env aenv t))+liftOpenFun (Lam lhs f)  = [|| Lam $$(liftELeftHandSide lhs) $$(liftOpenFun f) ||]+liftOpenFun (Body b)     = [|| Body $$(liftOpenExp b) ||]++liftOpenExp+    :: forall env aenv t.+       OpenExp env aenv t+    -> Q (TExp (OpenExp env aenv t))+liftOpenExp pexp =+  let+      liftE :: OpenExp env aenv e -> Q (TExp (OpenExp env aenv e))+      liftE = liftOpenExp++      liftF :: OpenFun env aenv f -> Q (TExp (OpenFun env aenv f))+      liftF = liftOpenFun+  in+  case pexp of+    Let lhs bnd body          -> [|| Let $$(liftELeftHandSide lhs) $$(liftOpenExp bnd) $$(liftOpenExp body) ||]+    Evar var                  -> [|| Evar $$(liftExpVar var) ||]+    Foreign repr asm f x      -> [|| Foreign $$(liftTypeR repr) $$(liftForeign asm) $$(liftOpenFun f) $$(liftE x) ||]+    Const tp c                -> [|| Const $$(liftScalarType tp) $$(liftElt (TupRsingle tp) c) ||]+    Undef tp                  -> [|| Undef $$(liftScalarType tp) ||]+    Pair a b                  -> [|| Pair $$(liftE a) $$(liftE b) ||]+    Nil                       -> [|| Nil ||]+    VecPack   vecr e          -> [|| VecPack   $$(liftVecR vecr) $$(liftE e) ||]+    VecUnpack vecr e          -> [|| VecUnpack $$(liftVecR vecr) $$(liftE e) ||]+    IndexSlice slice slix sh  -> [|| IndexSlice $$(liftSliceIndex slice) $$(liftE slix) $$(liftE sh) ||]+    IndexFull slice slix sl   -> [|| IndexFull $$(liftSliceIndex slice) $$(liftE slix) $$(liftE sl) ||]+    ToIndex shr sh ix         -> [|| ToIndex $$(liftShapeR shr) $$(liftE sh) $$(liftE ix) ||]+    FromIndex shr sh ix       -> [|| FromIndex $$(liftShapeR shr) $$(liftE sh) $$(liftE ix) ||]+    Case p rhs def            -> [|| Case $$(liftE p) $$(liftList (\(t,c) -> [|| (t, $$(liftE c)) ||]) rhs) $$(liftMaybe liftE def) ||]+    Cond p t e                -> [|| Cond $$(liftE p) $$(liftE t) $$(liftE e) ||]+    While p f x               -> [|| While $$(liftF p) $$(liftF f) $$(liftE x) ||]+    PrimConst t               -> [|| PrimConst $$(liftPrimConst t) ||]+    PrimApp f x               -> [|| PrimApp $$(liftPrimFun f) $$(liftE x) ||]+    Index a ix                -> [|| Index $$(liftArrayVar a) $$(liftE ix) ||]+    LinearIndex a ix          -> [|| LinearIndex $$(liftArrayVar a) $$(liftE ix) ||]+    Shape a                   -> [|| Shape $$(liftArrayVar a) ||]+    ShapeSize shr ix          -> [|| ShapeSize $$(liftShapeR shr) $$(liftE ix) ||]+    Coerce t1 t2 e            -> [|| Coerce $$(liftScalarType t1) $$(liftScalarType t2) $$(liftE e) ||]++liftELeftHandSide :: ELeftHandSide t env env' -> Q (TExp (ELeftHandSide t env env'))+liftELeftHandSide = liftLeftHandSide liftScalarType++liftExpVar :: ExpVar env t -> Q (TExp (ExpVar env t))+liftExpVar = liftVar liftScalarType++liftBoundary+    :: forall aenv sh e.+       ArrayR (Array sh e)+    -> Boundary aenv (Array sh e)+    -> Q (TExp (Boundary aenv (Array sh e)))+liftBoundary _             Clamp        = [|| Clamp ||]+liftBoundary _             Mirror       = [|| Mirror ||]+liftBoundary _             Wrap         = [|| Wrap ||]+liftBoundary (ArrayR _ tp) (Constant v) = [|| Constant $$(liftElt tp v) ||]+liftBoundary _             (Function f) = [|| Function $$(liftOpenFun f) ||]++liftPrimConst :: PrimConst c -> Q (TExp (PrimConst c))+liftPrimConst (PrimMinBound t) = [|| PrimMinBound $$(liftBoundedType t) ||]+liftPrimConst (PrimMaxBound t) = [|| PrimMaxBound $$(liftBoundedType t) ||]+liftPrimConst (PrimPi t)       = [|| PrimPi $$(liftFloatingType t) ||]++liftPrimFun :: PrimFun f -> Q (TExp (PrimFun f))+liftPrimFun (PrimAdd t)                = [|| PrimAdd $$(liftNumType t) ||]+liftPrimFun (PrimSub t)                = [|| PrimSub $$(liftNumType t) ||]+liftPrimFun (PrimMul t)                = [|| PrimMul $$(liftNumType t) ||]+liftPrimFun (PrimNeg t)                = [|| PrimNeg $$(liftNumType t) ||]+liftPrimFun (PrimAbs t)                = [|| PrimAbs $$(liftNumType t) ||]+liftPrimFun (PrimSig t)                = [|| PrimSig $$(liftNumType t) ||]+liftPrimFun (PrimQuot t)               = [|| PrimQuot $$(liftIntegralType t) ||]+liftPrimFun (PrimRem t)                = [|| PrimRem $$(liftIntegralType t) ||]+liftPrimFun (PrimQuotRem t)            = [|| PrimQuotRem $$(liftIntegralType t) ||]+liftPrimFun (PrimIDiv t)               = [|| PrimIDiv $$(liftIntegralType t) ||]+liftPrimFun (PrimMod t)                = [|| PrimMod $$(liftIntegralType t) ||]+liftPrimFun (PrimDivMod t)             = [|| PrimDivMod $$(liftIntegralType t) ||]+liftPrimFun (PrimBAnd t)               = [|| PrimBAnd $$(liftIntegralType t) ||]+liftPrimFun (PrimBOr t)                = [|| PrimBOr $$(liftIntegralType t) ||]+liftPrimFun (PrimBXor t)               = [|| PrimBXor $$(liftIntegralType t) ||]+liftPrimFun (PrimBNot t)               = [|| PrimBNot $$(liftIntegralType t) ||]+liftPrimFun (PrimBShiftL t)            = [|| PrimBShiftL $$(liftIntegralType t) ||]+liftPrimFun (PrimBShiftR t)            = [|| PrimBShiftR $$(liftIntegralType t) ||]+liftPrimFun (PrimBRotateL t)           = [|| PrimBRotateL $$(liftIntegralType t) ||]+liftPrimFun (PrimBRotateR t)           = [|| PrimBRotateR $$(liftIntegralType t) ||]+liftPrimFun (PrimPopCount t)           = [|| PrimPopCount $$(liftIntegralType t) ||]+liftPrimFun (PrimCountLeadingZeros t)  = [|| PrimCountLeadingZeros $$(liftIntegralType t) ||]+liftPrimFun (PrimCountTrailingZeros t) = [|| PrimCountTrailingZeros $$(liftIntegralType t) ||]+liftPrimFun (PrimFDiv t)               = [|| PrimFDiv $$(liftFloatingType t) ||]+liftPrimFun (PrimRecip t)              = [|| PrimRecip $$(liftFloatingType t) ||]+liftPrimFun (PrimSin t)                = [|| PrimSin $$(liftFloatingType t) ||]+liftPrimFun (PrimCos t)                = [|| PrimCos $$(liftFloatingType t) ||]+liftPrimFun (PrimTan t)                = [|| PrimTan $$(liftFloatingType t) ||]+liftPrimFun (PrimAsin t)               = [|| PrimAsin $$(liftFloatingType t) ||]+liftPrimFun (PrimAcos t)               = [|| PrimAcos $$(liftFloatingType t) ||]+liftPrimFun (PrimAtan t)               = [|| PrimAtan $$(liftFloatingType t) ||]+liftPrimFun (PrimSinh t)               = [|| PrimSinh $$(liftFloatingType t) ||]+liftPrimFun (PrimCosh t)               = [|| PrimCosh $$(liftFloatingType t) ||]+liftPrimFun (PrimTanh t)               = [|| PrimTanh $$(liftFloatingType t) ||]+liftPrimFun (PrimAsinh t)              = [|| PrimAsinh $$(liftFloatingType t) ||]+liftPrimFun (PrimAcosh t)              = [|| PrimAcosh $$(liftFloatingType t) ||]+liftPrimFun (PrimAtanh t)              = [|| PrimAtanh $$(liftFloatingType t) ||]+liftPrimFun (PrimExpFloating t)        = [|| PrimExpFloating $$(liftFloatingType t) ||]+liftPrimFun (PrimSqrt t)               = [|| PrimSqrt $$(liftFloatingType t) ||]+liftPrimFun (PrimLog t)                = [|| PrimLog $$(liftFloatingType t) ||]+liftPrimFun (PrimFPow t)               = [|| PrimFPow $$(liftFloatingType t) ||]+liftPrimFun (PrimLogBase t)            = [|| PrimLogBase $$(liftFloatingType t) ||]+liftPrimFun (PrimTruncate ta tb)       = [|| PrimTruncate $$(liftFloatingType ta) $$(liftIntegralType tb) ||]+liftPrimFun (PrimRound ta tb)          = [|| PrimRound $$(liftFloatingType ta) $$(liftIntegralType tb) ||]+liftPrimFun (PrimFloor ta tb)          = [|| PrimFloor $$(liftFloatingType ta) $$(liftIntegralType tb) ||]+liftPrimFun (PrimCeiling ta tb)        = [|| PrimCeiling $$(liftFloatingType ta) $$(liftIntegralType tb) ||]+liftPrimFun (PrimIsNaN t)              = [|| PrimIsNaN $$(liftFloatingType t) ||]+liftPrimFun (PrimIsInfinite t)         = [|| PrimIsInfinite $$(liftFloatingType t) ||]+liftPrimFun (PrimAtan2 t)              = [|| PrimAtan2 $$(liftFloatingType t) ||]+liftPrimFun (PrimLt t)                 = [|| PrimLt $$(liftSingleType t) ||]+liftPrimFun (PrimGt t)                 = [|| PrimGt $$(liftSingleType t) ||]+liftPrimFun (PrimLtEq t)               = [|| PrimLtEq $$(liftSingleType t) ||]+liftPrimFun (PrimGtEq t)               = [|| PrimGtEq $$(liftSingleType t) ||]+liftPrimFun (PrimEq t)                 = [|| PrimEq $$(liftSingleType t) ||]+liftPrimFun (PrimNEq t)                = [|| PrimNEq $$(liftSingleType t) ||]+liftPrimFun (PrimMax t)                = [|| PrimMax $$(liftSingleType t) ||]+liftPrimFun (PrimMin t)                = [|| PrimMin $$(liftSingleType t) ||]+liftPrimFun PrimLAnd                   = [|| PrimLAnd ||]+liftPrimFun PrimLOr                    = [|| PrimLOr ||]+liftPrimFun PrimLNot                   = [|| PrimLNot ||]+liftPrimFun (PrimFromIntegral ta tb)   = [|| PrimFromIntegral $$(liftIntegralType ta) $$(liftNumType tb) ||]+liftPrimFun (PrimToFloating ta tb)     = [|| PrimToFloating $$(liftNumType ta) $$(liftFloatingType tb) ||]+++showPreAccOp :: forall acc aenv arrs. PreOpenAcc acc aenv arrs -> String+showPreAccOp Alet{}              = "Alet"+showPreAccOp (Avar (Var _ ix))   = "Avar a" ++ show (idxToInt ix)+showPreAccOp (Use aR a)          = "Use " ++ showArrayShort 5 (showsElt (arrayRtype aR)) aR a+showPreAccOp Apply{}             = "Apply"+showPreAccOp Aforeign{}          = "Aforeign"+showPreAccOp Acond{}             = "Acond"+showPreAccOp Awhile{}            = "Awhile"+showPreAccOp Apair{}             = "Apair"+showPreAccOp Anil                = "Anil"+showPreAccOp Unit{}              = "Unit"+showPreAccOp Generate{}          = "Generate"+showPreAccOp Transform{}         = "Transform"+showPreAccOp Reshape{}           = "Reshape"+showPreAccOp Replicate{}         = "Replicate"+showPreAccOp Slice{}             = "Slice"+showPreAccOp Map{}               = "Map"+showPreAccOp ZipWith{}           = "ZipWith"+showPreAccOp (Fold _ z _)        = "Fold" ++ maybe "1" (const "") z+showPreAccOp (FoldSeg _ _ z _ _) = "Fold" ++ maybe "1" (const "") z ++ "Seg"+showPreAccOp (Scan d _ z _)      = "Scan" ++ showsDirection d (maybe "1" (const "") z)+showPreAccOp (Scan' d _ _ _)     = "Scan" ++ showsDirection d "'"+showPreAccOp Permute{}           = "Permute"+showPreAccOp Backpermute{}       = "Backpermute"+showPreAccOp Stencil{}           = "Stencil"+showPreAccOp Stencil2{}          = "Stencil2"++showsDirection :: Direction -> ShowS+showsDirection LeftToRight = ('l':)+showsDirection RightToLeft = ('r':)++showExpOp :: forall aenv env t. OpenExp aenv env t -> String+showExpOp Let{}             = "Let"+showExpOp (Evar (Var _ ix)) = "Var x" ++ show (idxToInt ix)+showExpOp (Const tp c)      = "Const " ++ showElt (TupRsingle tp) c+showExpOp Undef{}           = "Undef"+showExpOp Foreign{}         = "Foreign"+showExpOp Pair{}            = "Pair"+showExpOp Nil{}             = "Nil"+showExpOp VecPack{}         = "VecPack"+showExpOp VecUnpack{}       = "VecUnpack"+showExpOp IndexSlice{}      = "IndexSlice"+showExpOp IndexFull{}       = "IndexFull"+showExpOp ToIndex{}         = "ToIndex"+showExpOp FromIndex{}       = "FromIndex"+showExpOp Case{}            = "Case"+showExpOp Cond{}            = "Cond"+showExpOp While{}           = "While"+showExpOp PrimConst{}       = "PrimConst"+showExpOp PrimApp{}         = "PrimApp"+showExpOp Index{}           = "Index"+showExpOp LinearIndex{}     = "LinearIndex"+showExpOp Shape{}           = "Shape"+showExpOp ShapeSize{}       = "ShapeSize"+showExpOp Coerce{}          = "Coerce" 
+ src/Data/Array/Accelerate/AST/Environment.hs view
@@ -0,0 +1,90 @@+{-# LANGUAGE EmptyCase           #-}+{-# LANGUAGE GADTs               #-}+{-# LANGUAGE LambdaCase          #-}+{-# LANGUAGE RankNTypes          #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TypeOperators       #-}+{-# OPTIONS_HADDOCK hide #-}+-- |+-- Module      : Data.Array.Accelerate.AST.Environment+-- Copyright   : [2008..2020] The Accelerate Team+-- License     : BSD3+--+-- Maintainer  : Trevor L. McDonell <trevor.mcdonell@gmail.com>+-- Stability   : experimental+-- Portability : non-portable (GHC extensions)+--++module Data.Array.Accelerate.AST.Environment+  where++import Data.Array.Accelerate.AST.Idx+import Data.Array.Accelerate.AST.LeftHandSide+import Data.Array.Accelerate.Error+++-- Valuation for an environment+--+data Val env where+  Empty :: Val ()+  Push  :: Val env -> t -> Val (env, t)++-- Push a set of variables into an environment+--+push :: Val env -> (LeftHandSide s t env env', t) -> Val env'+push env (LeftHandSideWildcard _, _     ) = env+push env (LeftHandSideSingle _  , a     ) = env `Push` a+push env (LeftHandSidePair l1 l2, (a, b)) = push env (l1, a) `push` (l2, b)++-- Projection of a value from a valuation using a de Bruijn index+--+prj :: Idx env t -> Val env -> t+prj ZeroIdx       (Push _   v) = v+prj (SuccIdx idx) (Push val _) = prj idx val+++-- The type of shifting terms from one context into another+--+-- This is defined as a newtype, as a type synonym containing a forall+-- quantifier may give issues with impredicative polymorphism, which GHC+-- does not support.+--+newtype env :> env' = Weaken { (>:>) :: forall t'. Idx env t' -> Idx env' t' } -- Weak or Weaken++weakenId :: env :> env+weakenId = Weaken id++weakenSucc' :: env :> env' -> env :> (env', t)+weakenSucc' (Weaken f) = Weaken (SuccIdx . f)++weakenSucc :: (env, t) :> env' -> env :> env'+weakenSucc (Weaken f) = Weaken (f . SuccIdx)++weakenEmpty :: () :> env'+weakenEmpty = Weaken $ \case { }++sink :: forall env env' t. env :> env' -> (env, t) :> (env', t)+sink (Weaken f) = Weaken g+  where+    g :: Idx (env, t) t' -> Idx (env', t) t'+    g ZeroIdx      = ZeroIdx+    g (SuccIdx ix) = SuccIdx $ f ix++infixr 9 .>+(.>) :: env2 :> env3 -> env1 :> env2 -> env1 :> env3+(.>) (Weaken f) (Weaken g) = Weaken (f . g)++sinkWithLHS :: HasCallStack => LeftHandSide s t env1 env1' -> LeftHandSide s t env2 env2' -> env1 :> env2 -> env1' :> env2'+sinkWithLHS (LeftHandSideWildcard _) (LeftHandSideWildcard _) k = k+sinkWithLHS (LeftHandSideSingle _)   (LeftHandSideSingle _)   k = sink k+sinkWithLHS (LeftHandSidePair a1 b1) (LeftHandSidePair a2 b2) k = sinkWithLHS b1 b2 $ sinkWithLHS a1 a2 k+sinkWithLHS _ _ _ = internalError "left hand sides do not match"++weakenWithLHS :: forall s t env env'. LeftHandSide s t env env' -> env :> env'+weakenWithLHS = go weakenId+  where+    go :: env2 :> env' -> LeftHandSide s arrs env1 env2 -> env1 :> env'+    go k (LeftHandSideWildcard _) = k+    go k (LeftHandSideSingle _)   = weakenSucc k+    go k (LeftHandSidePair l1 l2) = go (go k l2) l1+
+ src/Data/Array/Accelerate/AST/Idx.hs view
@@ -0,0 +1,44 @@+{-# LANGUAGE GADTs           #-}+{-# LANGUAGE TemplateHaskell #-}+{-# OPTIONS_HADDOCK hide #-}+-- |+-- Module      : Data.Array.Accelerate.AST.Idx+-- Copyright   : [2008..2020] The Accelerate Team+-- License     : BSD3+--+-- Maintainer  : Trevor L. McDonell <trevor.mcdonell@gmail.com>+-- Stability   : experimental+-- Portability : non-portable (GHC extensions)+--+-- Typed de Bruijn indices+--++module Data.Array.Accelerate.AST.Idx+  where++import Language.Haskell.TH++-- De Bruijn variable index projecting a specific type from a type+-- environment.  Type environments are nested pairs (..((), t1), t2, ..., tn).+--+data Idx env t where+  ZeroIdx ::              Idx (env, t) t+  SuccIdx :: Idx env t -> Idx (env, s) t++data PairIdx p a where+  PairIdxLeft  :: PairIdx (a, b) a+  PairIdxRight :: PairIdx (a, b) b+++idxToInt :: Idx env t -> Int+idxToInt ZeroIdx       = 0+idxToInt (SuccIdx idx) = 1 + idxToInt idx++rnfIdx :: Idx env t -> ()+rnfIdx ZeroIdx      = ()+rnfIdx (SuccIdx ix) = rnfIdx ix++liftIdx :: Idx env t -> Q (TExp (Idx env t))+liftIdx ZeroIdx      = [|| ZeroIdx ||]+liftIdx (SuccIdx ix) = [|| SuccIdx $$(liftIdx ix) ||]+
+ src/Data/Array/Accelerate/AST/LeftHandSide.hs view
@@ -0,0 +1,62 @@+{-# LANGUAGE GADTs           #-}+{-# LANGUAGE KindSignatures  #-}+{-# LANGUAGE PatternSynonyms #-}+{-# LANGUAGE RankNTypes      #-}+{-# LANGUAGE TemplateHaskell #-}+{-# OPTIONS_HADDOCK hide #-}+-- |+-- Module      : Data.Array.Accelerate.AST.LeftHandSide+-- Copyright   : [2008..2020] The Accelerate Team+-- License     : BSD3+--+-- Maintainer  : Trevor L. McDonell <trevor.mcdonell@gmail.com>+-- Stability   : experimental+-- Portability : non-portable (GHC extensions)+--++module Data.Array.Accelerate.AST.LeftHandSide+  where++import Data.Array.Accelerate.Representation.Type++import Language.Haskell.TH+++data Exists f where+  Exists :: f a -> Exists f++data LeftHandSide s v env env' where+  LeftHandSideSingle+    :: s v+    -> LeftHandSide s v env (env, v)++  LeftHandSideWildcard+    :: TupR s v+    -> LeftHandSide s v env env++  LeftHandSidePair+    :: LeftHandSide s v1       env  env'+    -> LeftHandSide s v2       env' env''+    -> LeftHandSide s (v1, v2) env  env''++pattern LeftHandSideUnit+    :: ()                   -- required+    => (env' ~ env, v ~ ()) -- provided+    => LeftHandSide s v env env'+pattern LeftHandSideUnit = LeftHandSideWildcard TupRunit++lhsToTupR :: LeftHandSide s v env env' -> TupR s v+lhsToTupR (LeftHandSideSingle s)   = TupRsingle s+lhsToTupR (LeftHandSideWildcard r) = r+lhsToTupR (LeftHandSidePair as bs) = TupRpair (lhsToTupR as) (lhsToTupR bs)++rnfLeftHandSide :: (forall b. s b -> ()) -> LeftHandSide s v env env' -> ()+rnfLeftHandSide f (LeftHandSideWildcard r) = rnfTupR f r+rnfLeftHandSide f (LeftHandSideSingle s)   = f s+rnfLeftHandSide f (LeftHandSidePair as bs) = rnfLeftHandSide f as `seq` rnfLeftHandSide f bs++liftLeftHandSide :: (forall u. s u -> Q (TExp (s u))) -> LeftHandSide s v env env' -> Q (TExp (LeftHandSide s v env env'))+liftLeftHandSide f (LeftHandSideSingle s)   = [|| LeftHandSideSingle $$(f s) ||]+liftLeftHandSide f (LeftHandSideWildcard r) = [|| LeftHandSideWildcard $$(liftTupR f r) ||]+liftLeftHandSide f (LeftHandSidePair as bs) = [|| LeftHandSidePair $$(liftLeftHandSide f as) $$(liftLeftHandSide f bs) ||]+
+ src/Data/Array/Accelerate/AST/Var.hs view
@@ -0,0 +1,44 @@+{-# LANGUAGE GADTs           #-}+{-# LANGUAGE RankNTypes      #-}+{-# LANGUAGE TemplateHaskell #-}+{-# OPTIONS_HADDOCK hide #-}+-- |+-- Module      : Data.Array.Accelerate.AST.Var+-- Copyright   : [2008..2020] The Accelerate Team+-- License     : BSD3+--+-- Maintainer  : Trevor L. McDonell <trevor.mcdonell@gmail.com>+-- Stability   : experimental+-- Portability : non-portable (GHC extensions)+--++module Data.Array.Accelerate.AST.Var+  where++import Data.Array.Accelerate.Representation.Type+import Data.Array.Accelerate.AST.Idx++import Language.Haskell.TH+++data Var  s env t = Var (s t) (Idx env t)+type Vars s env   = TupR (Var s env)++varsType :: Vars s env t -> TupR s t+varsType TupRunit               = TupRunit+varsType (TupRsingle (Var t _)) = TupRsingle t+varsType (TupRpair a b)         = TupRpair (varsType a) (varsType b)+++rnfVar :: (forall b. s b -> ()) -> Var s env t -> ()+rnfVar f (Var t idx) = f t `seq` rnfIdx idx++rnfVars :: (forall b. s b -> ()) -> Vars s env t -> ()+rnfVars f = rnfTupR (rnfVar f)++liftVar :: (forall b. s b -> Q (TExp (s b))) -> Var s env t -> Q (TExp (Var s env t))+liftVar f (Var s idx) = [|| Var $$(f s) $$(liftIdx idx) ||]++liftVars :: (forall b. s b -> Q (TExp (s b))) -> Vars s env t -> Q (TExp (Vars s env t))+liftVars f = liftTupR (liftVar f)+
src/Data/Array/Accelerate/Analysis/Hash.hs view
@@ -1,15 +1,18 @@+{-# LANGUAGE AllowAmbiguousTypes #-} {-# LANGUAGE GADTs               #-}+{-# LANGUAGE MagicHash           #-} {-# LANGUAGE PatternGuards       #-} {-# LANGUAGE RankNTypes          #-} {-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE TemplateHaskell     #-}+{-# LANGUAGE TypeApplications    #-} {-# OPTIONS_HADDOCK hide #-} -- | -- Module      : Data.Array.Accelerate.Analysis.Hash--- Copyright   : [2017] Manuel M T Chakravarty, Gabriele Keller, Trevor L. McDonell+-- Copyright   : [2017..2020] The Accelerate Team -- License     : BSD3 ----- Maintainer  : Trevor L. McDonell <tmcdonell@cse.unsw.edu.au>+-- Maintainer  : Trevor L. McDonell <trevor.mcdonell@gmail.com> -- Stability   : experimental -- Portability : non-portable (GHC extensions) --@@ -18,32 +21,38 @@    -- hashing expressions   Hash,-  hashPreOpenAcc,-  hashPreOpenFun,-  hashPreOpenExp,+  HashOptions(..), defaultHashOptions,+  hashPreOpenAcc, hashPreOpenAccWith,+  hashOpenFun, hashOpenExp,    -- auxiliary   EncodeAcc,-  encodePreOpenAcc, encodeOpenAcc,-  encodePreOpenExp, encodeOpenExp,-  encodePreOpenFun,+  encodePreOpenAcc,+  encodeOpenExp,+  encodeOpenFun,+  encodeArraysType,   hashQ,  ) where  import Data.Array.Accelerate.AST+import Data.Array.Accelerate.AST.Idx+import Data.Array.Accelerate.AST.LeftHandSide+import Data.Array.Accelerate.AST.Var import Data.Array.Accelerate.Analysis.Hash.TH-import Data.Array.Accelerate.Array.Sugar-import Data.Array.Accelerate.Array.Representation                   ( SliceIndex(..) )-import Data.Array.Accelerate.Product+import Data.Array.Accelerate.Representation.Array+import Data.Array.Accelerate.Representation.Shape+import Data.Array.Accelerate.Representation.Slice+import Data.Array.Accelerate.Representation.Stencil+import Data.Array.Accelerate.Representation.Type import Data.Array.Accelerate.Type+import Data.Primitive.Vec  import Crypto.Hash-import Data.Bits import Data.ByteString.Builder import Data.ByteString.Builder.Extra+import Data.ByteString.Short.Internal                               ( ShortByteString(..) ) import Data.Monoid-import Foreign.C.Types import System.IO.Unsafe                                             ( unsafePerformIO ) import System.Mem.StableName                                        ( hashStableName, makeStableName ) import Prelude                                                      hiding ( exp )@@ -54,107 +63,157 @@  type Hash = Digest SHA3_256 -hashPreOpenAcc :: EncodeAcc acc -> PreOpenAcc acc aenv a -> Hash-hashPreOpenAcc encodeAcc = hashlazy . toLazyByteString . encodePreOpenAcc encodeAcc+data HashOptions = HashOptions+  { perfect :: Bool+    -- ^ Should the hash function include _all_ substructure, recursively?+    --+    -- Set to true (the default) if you want a truly unique fingerprint for+    -- the entire expression:+    --+    -- Example:+    --+    -- xs, ys :: Acc (Vector Float)+    -- xs = fill (constant (Z:.10)) 1.0+    -- ys = fill (constant (Z:.20)) 1.0+    --+    -- with perfect=True:+    --+    --   hash xs = 2e1f91aca4c476d13b36f22462e73c15bbdd9fcacb0d4996280f6004058e9732+    --   hash ys = 2fce5c849b6c652192b09aaeafdc8029e57b9f006c1ecd79ccf9114f349aaf9e+    --+    -- However, for a code generating backend the object code used to+    -- evaluate both of these expressions is likely to be identical.+    --+    -- Setting perfect=False results in:+    --+    --   hash xs = hash ys = f97944b0ec64ab8aa989fd60c8b50e7ec3eff759d22d2b340039d837d74dfc3c+    --+    -- Note that to be useful the provided 'EncodeAcc' function must also+    -- understand this option, and the consumer of the hash value must be+    -- agnostic to the elided details.+  }+  deriving Show -hashPreOpenFun :: EncodeAcc acc -> PreOpenFun acc env aenv f -> Hash-hashPreOpenFun encodeAcc = hashlazy . toLazyByteString . encodePreOpenFun encodeAcc+defaultHashOptions :: HashOptions+defaultHashOptions = HashOptions True -hashPreOpenExp :: EncodeAcc acc -> PreOpenExp acc env aenv t -> Hash-hashPreOpenExp encodeAcc = hashlazy . toLazyByteString . encodePreOpenExp encodeAcc +{-# INLINEABLE hashPreOpenAcc #-}+hashPreOpenAcc :: HasArraysR acc => EncodeAcc acc -> PreOpenAcc acc aenv a -> Hash+hashPreOpenAcc = hashPreOpenAccWith defaultHashOptions +{-# INLINEABLE hashPreOpenAccWith #-}+hashPreOpenAccWith :: HasArraysR acc => HashOptions -> EncodeAcc acc -> PreOpenAcc acc aenv a -> Hash+hashPreOpenAccWith options encodeAcc+  = hashlazy+  . toLazyByteString+  . encodePreOpenAcc options encodeAcc++{-# INLINEABLE hashOpenFun #-}+hashOpenFun :: OpenFun env aenv f -> Hash+hashOpenFun+  = hashlazy+  . toLazyByteString+  . encodeOpenFun++{-# INLINEABLE hashOpenExp #-}+hashOpenExp :: OpenExp env aenv t -> Hash+hashOpenExp+  = hashlazy+  . toLazyByteString+  . encodeOpenExp++ -- Array computations -- ------------------ -type EncodeAcc acc = forall aenv a. acc aenv a -> Builder--{-# INLINE encodeOpenAcc #-}-encodeOpenAcc :: OpenAcc aenv arrs -> Builder-encodeOpenAcc (OpenAcc pacc) = encodePreOpenAcc encodeOpenAcc pacc+type EncodeAcc acc = forall aenv a. HashOptions -> acc aenv a -> Builder -{-# INLINE encodePreOpenAcc #-}+{-# INLINEABLE encodePreOpenAcc #-} encodePreOpenAcc-    :: forall acc aenv arrs.-       EncodeAcc acc+    :: forall acc aenv arrs. HasArraysR acc+    => HashOptions+    -> EncodeAcc acc     -> PreOpenAcc acc aenv arrs     -> Builder-encodePreOpenAcc encodeAcc pacc =+encodePreOpenAcc options encodeAcc pacc =   let-      {-# INLINE travA #-}-      travA :: forall aenv' a. Arrays a => acc aenv' a -> Builder-      travA a = encodeArraysType (arrays (undefined::a)) <> encodeAcc a+      travA :: forall aenv' a. acc aenv' a -> Builder+      travA = encodeAcc options -      {-# INLINE travE #-}-      travE :: PreOpenExp acc env' aenv' e -> Builder-      travE = encodePreOpenExp encodeAcc+      travAF :: PreOpenAfun acc aenv' f -> Builder+      travAF = encodePreOpenAfun options encodeAcc -      {-# INLINE travF #-}-      travF :: PreOpenFun acc env' aenv' f -> Builder-      travF = encodePreOpenFun encodeAcc+      travE :: OpenExp env' aenv' e -> Builder+      travE = encodeOpenExp -      {-# INLINE travB #-}-      travB :: PreBoundary acc aenv' (Array sh e) -> Builder-      travB = encodePreBoundary encodeAcc+      travF :: OpenFun env' aenv' f -> Builder+      travF = encodeOpenFun -      {-# INLINE nacl #-}-      nacl :: Arrays arrs => Builder-      nacl = encodeArraysType (arrays (undefined::arrs))+      travD :: Direction -> Builder+      travD LeftToRight = intHost $(hashQ "L")+      travD RightToLeft = intHost $(hashQ "R")++      deep :: Builder -> Builder+      deep | perfect options = id+           | otherwise       = const mempty++      deepE :: forall env' aenv' e. OpenExp env' aenv' e -> Builder+      deepE e+        | perfect options = travE e+        | otherwise       = encodeTypeR $ expType e   in   case pacc of-    Alet bnd body               -> intHost $(hashQ "Alet")        <> travA bnd <> travA body-    Avar v                      -> intHost $(hashQ "Avar")        <> nacl <> encodeIdx v-    Atuple t                    -> intHost $(hashQ "Atuple")      <> nacl <> encodeAtuple encodeAcc t-    Aprj ix a                   -> intHost $(hashQ "Aprj")        <> nacl <> encodeTupleIdx ix <> travA a-    Apply f a                   -> intHost $(hashQ "Apply")       <> nacl <> encodePreOpenAfun encodeAcc f <> travA a-    Aforeign _ f a              -> intHost $(hashQ "Aforeign")    <> nacl <> encodePreOpenAfun encodeAcc f <> travA a-    Use a                       -> intHost $(hashQ "Use")         <> encodeArrays (arrays (undefined::arrs)) a-    Awhile p f a                -> intHost $(hashQ "Awhile")      <> encodePreOpenAfun encodeAcc f <> encodePreOpenAfun encodeAcc p <> travA a-    Unit e                      -> intHost $(hashQ "Unit")        <> travE e-    Generate e f                -> intHost $(hashQ "Generate")    <> travE e  <> travF f-    Acond e a1 a2               -> intHost $(hashQ "Acond")       <> travE e  <> travA a1 <> travA a2-    Reshape sh a                -> intHost $(hashQ "Reshape")     <> travE sh <> travA a-    Transform sh f1 f2 a        -> intHost $(hashQ "Transform")   <> travE sh <> travF f1 <> travF f2 <> travA a-    Replicate spec ix a         -> intHost $(hashQ "Replicate")   <> travE ix <> travA a  <> encodeSliceIndex spec-    Slice spec a ix             -> intHost $(hashQ "Slice")       <> travE ix <> travA a  <> encodeSliceIndex spec-    Map f a                     -> intHost $(hashQ "Map")         <> travF f  <> travA a-    ZipWith f a1 a2             -> intHost $(hashQ "ZipWith")     <> travF f  <> travA a1 <> travA a2-    Fold f e a                  -> intHost $(hashQ "Fold")        <> travF f  <> travE e  <> travA a-    Fold1 f a                   -> intHost $(hashQ "Fold1")       <> travF f  <> travA a-    FoldSeg f e a s             -> intHost $(hashQ "FoldSeg")     <> travF f  <> travE e  <> travA a  <> travA s-    Fold1Seg f a s              -> intHost $(hashQ "Fold1Seg")    <> travF f  <> travA a  <> travA s-    Scanl f e a                 -> intHost $(hashQ "Scanl")       <> travF f  <> travE e  <> travA a-    Scanl' f e a                -> intHost $(hashQ "Scanl'")      <> travF f  <> travE e  <> travA a-    Scanl1 f a                  -> intHost $(hashQ "Scanl1")      <> travF f  <> travA a-    Scanr f e a                 -> intHost $(hashQ "Scanr")       <> travF f  <> travE e  <> travA a-    Scanr' f e a                -> intHost $(hashQ "Scanr'")      <> travF f  <> travE e  <> travA a-    Scanr1 f a                  -> intHost $(hashQ "Scanr1")      <> travF f  <> travA a-    Backpermute sh f a          -> intHost $(hashQ "Backpermute") <> travF f  <> travE sh <> travA a-    Permute f1 a1 f2 a2         -> intHost $(hashQ "Permute")     <> travF f1 <> travA a1 <> travF f2 <> travA a2-    Stencil f b a               -> intHost $(hashQ "Stencil")     <> travF f  <> travB b  <> travA a-    Stencil2 f b1 a1 b2 a2      -> intHost $(hashQ "Stencil2")    <> travF f  <> travB b1 <> travA a1 <> travB b2 <> travA a2+    Alet lhs bnd body            -> intHost $(hashQ "Alet")        <> encodeLeftHandSide encodeArrayType lhs <> travA bnd <> travA body+    Avar (Var repr v)            -> intHost $(hashQ "Avar")        <> encodeArrayType repr <> deep (encodeIdx v)+    Apair a1 a2                  -> intHost $(hashQ "Apair")       <> travA a1 <> travA a2+    Anil                         -> intHost $(hashQ "Anil")+    Apply _ f a                  -> intHost $(hashQ "Apply")       <> travAF f <> travA a+    Aforeign _ _ f a             -> intHost $(hashQ "Aforeign")    <> travAF f <> travA a+    Use repr a                   -> intHost $(hashQ "Use")         <> encodeArrayType repr <> deep (encodeArray a)+    Awhile p f a                 -> intHost $(hashQ "Awhile")      <> travAF f <> travAF p <> travA a+    Unit _ e                     -> intHost $(hashQ "Unit")        <> travE e+    Generate _ e f               -> intHost $(hashQ "Generate")    <> deepE e <> travF f+    -- We don't need to encode the type of 'e' when perfect is False, as 'e' is an expression of type Bool.+    -- We thus use `deep (travE e)` instead of `deepE e`.+    Acond e a1 a2                -> intHost $(hashQ "Acond")       <> deep (travE e) <> travA a1 <> travA a2+    Reshape _ sh a               -> intHost $(hashQ "Reshape")     <> deepE sh <> travA a+    Backpermute _ sh f a         -> intHost $(hashQ "Backpermute") <> deepE sh <> travF f  <> travA a+    Transform _ sh f1 f2 a       -> intHost $(hashQ "Transform")   <> deepE sh <> travF f1 <> travF f2 <> travA a+    Replicate spec ix a          -> intHost $(hashQ "Replicate")   <> deepE ix <> travA a  <> encodeSliceIndex spec+    Slice spec a ix              -> intHost $(hashQ "Slice")       <> deepE ix <> travA a  <> encodeSliceIndex spec+    Map _ f a                    -> intHost $(hashQ "Map")         <> travF f  <> travA a+    ZipWith _ f a1 a2            -> intHost $(hashQ "ZipWith")     <> travF f  <> travA a1 <> travA a2+    Fold f e a                   -> intHost $(hashQ "Fold")        <> travF f  <> encodeMaybe travE e  <> travA a+    FoldSeg _ f e a s            -> intHost $(hashQ "FoldSeg")     <> travF f  <> encodeMaybe travE e  <> travA a  <> travA s+    Scan  d f e a                -> intHost $(hashQ "Scan")        <> travD d  <> travF f  <> encodeMaybe travE e  <> travA a+    Scan' d f e a                -> intHost $(hashQ "Scan'")       <> travD d  <> travF f  <>           travE e  <> travA a+    Permute f1 a1 f2 a2          -> intHost $(hashQ "Permute")     <> travF f1 <> travA a1 <> travF f2 <> travA a2+    Stencil s _ f b a            -> intHost $(hashQ "Stencil")     <> travF f  <> encodeBoundary (stencilEltR s) b  <> travA a+    Stencil2 s1 s2 _ f b1 a1 b2 a2 -> intHost $(hashQ "Stencil2")  <> travF f  <> encodeBoundary (stencilEltR s1) b1 <> travA a1 <> encodeBoundary (stencilEltR s2) b2 <> travA a2  {--+{-# INLINEABLE encodePreOpenSeq #-} encodePreOpenSeq :: forall acc aenv senv arrs. EncodeAcc acc -> PreOpenSeq acc aenv senv arrs -> Int encodePreOpenSeq encodeAcc s =   let       travA :: acc aenv' a -> Builder       travA = encodeAcc -- XXX: plus type information? -      travE :: PreOpenExp acc env' aenv' e -> Builder-      travE = encodePreOpenExp encodeAcc+      travE :: OpenExp env' aenv' e -> Builder+      travE = encodeOpenExp encodeAcc        travAF :: PreOpenAfun acc aenv' f -> Builder       travAF = encodePreOpenAfun encodeAcc -      travF :: PreOpenFun acc env' aenv' f -> Builder-      travF = encodePreOpenFun encodeAcc+      travF :: OpenFun env' aenv' f -> Builder+      travF = encodeOpenFun encodeAcc        travS :: PreOpenSeq acc aenv senv' arrs' -> Builder       travS = encodePreOpenSeq encodeAcc        travV :: forall a. Arrays a => Idx senv' a -> Builder-      travV v = encodeArraysType (arrays (undefined::a)) <> encodeIdx v+      travV v = encodeArraysType (arrays @a) <> encodeIdx v        travP :: Producer acc aenv senv a -> Builder       travP p =@@ -179,61 +238,57 @@     Reify ix      -> intHost $(hashQ "Reify")      <> travV ix --} -{-# INLINE encodeIdx #-} encodeIdx :: Idx env t -> Builder encodeIdx = intHost . idxToInt -{-# INLINE encodeTupleIdx #-}-encodeTupleIdx :: TupleIdx tup e -> Builder-encodeTupleIdx = intHost . tupleIdxToInt+encodeArray :: Array sh e -> Builder+encodeArray ad = intHost . unsafePerformIO $! hashStableName <$> makeStableName ad -{-# INLINE encodeArrays #-}-encodeArrays :: ArraysR a -> a -> Builder-encodeArrays ArraysRunit         ()       = mempty-encodeArrays (ArraysRpair r1 r2) (a1, a2) = encodeArrays r1 a1 <> encodeArrays r2 a2-encodeArrays ArraysRarray        ad       = intHost . unsafePerformIO $! hashStableName `fmap` makeStableName ad+encodeTupR :: (forall b. s b -> Builder) -> TupR s a -> Builder+encodeTupR _ TupRunit         = intHost $(hashQ "TupRunit")+encodeTupR f (TupRpair r1 r2) = intHost $(hashQ "TupRpair")   <> encodeTupR f r1 <> encodeTupR f r2+encodeTupR f (TupRsingle s)   = intHost $(hashQ "TupRsingle") <> f s -{-# INLINE encodeArraysType #-}-encodeArraysType :: forall a. ArraysR a -> Builder-encodeArraysType ArraysRunit         = intHost $(hashQ "ArraysRunit")-encodeArraysType (ArraysRpair r1 r2) = intHost $(hashQ "ArraysRpair")  <> encodeArraysType r1 <> encodeArraysType r2-encodeArraysType ArraysRarray        = intHost $(hashQ "ArraysRarray") <> encodeArrayType (undefined::a)-  where-    {-# INLINE encodeArrayType #-}-    encodeArrayType :: forall sh e. (Shape sh, Elt e) => Array sh e -> Builder-    encodeArrayType _ = encodeTupleType (eltType (undefined::sh)) <> encodeTupleType (eltType (undefined::e))+encodeLeftHandSide :: (forall b. s b -> Builder) -> LeftHandSide s a env env' -> Builder+encodeLeftHandSide f (LeftHandSideWildcard r) = intHost $(hashQ "LeftHandSideWildcard") <> encodeTupR f r+encodeLeftHandSide f (LeftHandSidePair r1 r2) = intHost $(hashQ "LeftHandSidePair")     <> encodeLeftHandSide f r1 <> encodeLeftHandSide f r2+encodeLeftHandSide f (LeftHandSideSingle s)   = intHost $(hashQ "LeftHandSideArray")    <> f s -{-# INLINE encodeAtuple #-}-encodeAtuple :: EncodeAcc acc -> Atuple (acc aenv) a -> Builder-encodeAtuple _     NilAtup        = intHost $(hashQ "NilAtup")-encodeAtuple travA (SnocAtup t a) = intHost $(hashQ "SnocAtup") <> encodeAtuple travA t <> travA a+encodeArrayType :: ArrayR a -> Builder+encodeArrayType (ArrayR shr tp) = encodeShapeR shr <> encodeTypeR tp -{-# INLINE encodePreOpenAfun #-}-encodePreOpenAfun :: forall acc aenv f. EncodeAcc acc -> PreOpenAfun acc aenv f -> Builder-encodePreOpenAfun travA afun =-  let-      {-# INLINE travB #-}-      travB :: forall aenv' a. Arrays a => acc aenv' a -> Builder-      travB b = encodeArraysType (arrays (undefined::a)) <> travA b+encodeArraysType :: ArraysR arrs -> Builder+encodeArraysType = encodeTupR encodeArrayType -      {-# INLINE travL #-}-      travL :: forall aenv' a b. Arrays a => PreOpenAfun acc (aenv',a) b -> Builder-      travL l = encodeArraysType (arrays (undefined::a)) <> encodePreOpenAfun travA l+encodeShapeR :: ShapeR sh -> Builder+encodeShapeR = intHost . rank++encodePreOpenAfun+    :: forall acc aenv f.+       HashOptions+    -> EncodeAcc acc+    -> PreOpenAfun acc aenv f+    -> Builder+encodePreOpenAfun options travA afun =+  let+      travL :: forall aenv1 aenv2 a b. ALeftHandSide a aenv1 aenv2 -> PreOpenAfun acc aenv2 b -> Builder+      travL lhs l = encodeLeftHandSide encodeArrayType lhs <> encodePreOpenAfun options travA l   in   case afun of-    Abody b -> intHost $(hashQ "Abody") <> travB b-    Alam  l -> intHost $(hashQ "Alam")  <> travL l+    Abody b    -> intHost $(hashQ "Abody") <> travA options b+    Alam lhs l -> intHost $(hashQ "Alam")  <> travL lhs  l  -{-# INLINE encodePreBoundary #-}-encodePreBoundary :: forall acc aenv sh e. EncodeAcc acc -> PreBoundary acc aenv (Array sh e) -> Builder-encodePreBoundary _ Wrap          = intHost $(hashQ "Wrap")-encodePreBoundary _ Clamp         = intHost $(hashQ "Clamp")-encodePreBoundary _ Mirror        = intHost $(hashQ "Mirror")-encodePreBoundary _ (Constant c)  = intHost $(hashQ "Constant") <> encodeConst (eltType (undefined::e)) c-encodePreBoundary h (Function f)  = intHost $(hashQ "Function") <> encodePreOpenFun h f+encodeBoundary+    :: TypeR e+    -> Boundary aenv (Array sh e)+    -> Builder+encodeBoundary _  Wrap          = intHost $(hashQ "Wrap")+encodeBoundary _  Clamp         = intHost $(hashQ "Clamp")+encodeBoundary _  Mirror        = intHost $(hashQ "Mirror")+encodeBoundary tp (Constant c)  = intHost $(hashQ "Constant") <> encodeConst tp c+encodeBoundary _  (Function f)  = intHost $(hashQ "Function") <> encodeOpenFun f -{-# INLINE encodeSliceIndex #-} encodeSliceIndex :: SliceIndex slix sl co sh -> Builder encodeSliceIndex SliceNil         = intHost $(hashQ "SliceNil") encodeSliceIndex (SliceAll r)     = intHost $(hashQ "SliceAll")   <> encodeSliceIndex r@@ -243,168 +298,96 @@ -- Scalar expressions -- ------------------ -{-# INLINE encodeOpenExp #-}-encodeOpenExp :: OpenExp env aenv exp -> Builder-encodeOpenExp = encodePreOpenExp encodeOpenAcc--{-# INLINE encodePreOpenExp #-}-encodePreOpenExp :: forall acc env aenv exp. EncodeAcc acc -> PreOpenExp acc env aenv exp -> Builder-encodePreOpenExp travA exp =+{-# INLINEABLE encodeOpenExp #-}+encodeOpenExp+    :: forall env aenv exp.+       OpenExp env aenv exp+    -> Builder+encodeOpenExp exp =   let-      {-# INLINE travE #-}-      travE :: forall env' aenv' e. Elt e => PreOpenExp acc env' aenv' e -> Builder-      travE e =  encodeTupleType (eltType (undefined::e)) <> encodePreOpenExp travA e--      {-# INLINE travF #-}-      travF :: PreOpenFun acc env' aenv' f -> Builder-      travF = encodePreOpenFun travA+      travE :: forall env' aenv' e. OpenExp env' aenv' e -> Builder+      travE e = encodeOpenExp e -      {-# INLINE nacl #-}-      nacl :: Elt exp => Builder-      nacl = encodeTupleType (eltType (undefined::exp))+      travF :: OpenFun env' aenv' f -> Builder+      travF = encodeOpenFun   in   case exp of-    Let bnd body                -> intHost $(hashQ "Let")         <> travE bnd <> travE body-    Var ix                      -> intHost $(hashQ "Var")         <> nacl <> encodeIdx ix-    Tuple t                     -> intHost $(hashQ "Tuple")       <> nacl <> encodeTuple travA t-    Prj i e                     -> intHost $(hashQ "Prj")         <> nacl <> encodeTupleIdx i <> travE e -- XXX: here multiplied nacl by hashTupleIdx-    Const c                     -> intHost $(hashQ "Const")       <> encodeConst (eltType (undefined::exp)) c-    Undef                       -> intHost $(hashQ "Undef")-    IndexAny                    -> intHost $(hashQ "IndexAny")    <> nacl-    IndexNil                    -> intHost $(hashQ "IndexNil")-    IndexCons sh sz             -> intHost $(hashQ "IndexCons")   <> travE sh <> travE sz-    IndexHead sl                -> intHost $(hashQ "IndexHead")   <> travE sl-    IndexTail sl                -> intHost $(hashQ "IndexTail")   <> travE sl+    Let lhs bnd body            -> intHost $(hashQ "Let")         <> encodeLeftHandSide encodeScalarType lhs <> travE bnd <> travE body+    Evar (Var tp ix)            -> intHost $(hashQ "Evar")        <> encodeScalarType tp <> encodeIdx ix+    Nil                         -> intHost $(hashQ "Nil")+    Pair e1 e2                  -> intHost $(hashQ "Pair")        <> travE e1 <> travE e2+    VecPack   _ e               -> intHost $(hashQ "VecPack")     <> travE e+    VecUnpack _ e               -> intHost $(hashQ "VecUnpack")   <> travE e+    Const tp c                  -> intHost $(hashQ "Const")       <> encodeScalarConst tp c+    Undef tp                    -> intHost $(hashQ "Undef")       <> encodeScalarType tp     IndexSlice spec ix sh       -> intHost $(hashQ "IndexSlice")  <> travE ix <> travE sh <> encodeSliceIndex spec     IndexFull  spec ix sl       -> intHost $(hashQ "IndexFull")   <> travE ix <> travE sl <> encodeSliceIndex spec-    ToIndex sh i                -> intHost $(hashQ "ToIndex")     <> travE sh <> travE i-    FromIndex sh i              -> intHost $(hashQ "FromIndex")   <> travE sh <> travE i+    ToIndex _ sh i              -> intHost $(hashQ "ToIndex")     <> travE sh <> travE i+    FromIndex _ sh i            -> intHost $(hashQ "FromIndex")   <> travE sh <> travE i+    Case e rhs def              -> intHost $(hashQ "Case")        <> travE e  <> mconcat [ word8 t <> travE c | (t,c) <- rhs ] <> encodeMaybe travE def     Cond c t e                  -> intHost $(hashQ "Cond")        <> travE c  <> travE t  <> travE e     While p f x                 -> intHost $(hashQ "While")       <> travF p  <> travF f  <> travE x     PrimApp f x                 -> intHost $(hashQ "PrimApp")     <> encodePrimFun f <> travE x     PrimConst c                 -> intHost $(hashQ "PrimConst")   <> encodePrimConst c-    Index a ix                  -> intHost $(hashQ "Index")       <> travA a  <> travE ix-    LinearIndex a ix            -> intHost $(hashQ "LinearIndex") <> travA a  <> travE ix-    Shape a                     -> intHost $(hashQ "Shape")       <> travA a-    ShapeSize sh                -> intHost $(hashQ "ShapeSize")   <> travE sh-    Intersect sa sb             -> intHost $(hashQ "Intersect")   <> travE sa <> travE sb-    Union sa sb                 -> intHost $(hashQ "Union")       <> travE sa <> travE sb-    Foreign _ f e               -> intHost $(hashQ "Foreign")     <> travF f  <> travE e-    Coerce e                    -> intHost $(hashQ "Coerce")      <> travE e---{-# INLINE encodePreOpenFun #-}-encodePreOpenFun :: forall acc env aenv f. EncodeAcc acc -> PreOpenFun acc env aenv f -> Builder-encodePreOpenFun travA fun =-  let-      travB :: forall env' aenv' e. Elt e => PreOpenExp acc env' aenv' e -> Builder-      travB b = encodeTupleType (eltType (undefined::e)) <> encodePreOpenExp travA b+    Index a ix                  -> intHost $(hashQ "Index")       <> encodeArrayVar a <> travE ix+    LinearIndex a ix            -> intHost $(hashQ "LinearIndex") <> encodeArrayVar a <> travE ix+    Shape a                     -> intHost $(hashQ "Shape")       <> encodeArrayVar a+    ShapeSize _ sh              -> intHost $(hashQ "ShapeSize")   <> travE sh+    Foreign _ _ f e             -> intHost $(hashQ "Foreign")     <> travF f  <> travE e+    Coerce _ tp e               -> intHost $(hashQ "Coerce")      <> encodeScalarType tp <> travE e -      travL :: forall env' aenv' a b. Elt a => PreOpenFun acc (env',a) aenv' b -> Builder-      travL l = encodeTupleType (eltType (undefined::a)) <> encodePreOpenFun travA l-  in-  case fun of-    Body b -> intHost $(hashQ "Body") <> travB b-    Lam l  -> intHost $(hashQ "Lam")  <> travL l+encodeArrayVar :: ArrayVar aenv a -> Builder+encodeArrayVar (Var repr v) = encodeArrayType repr <> encodeIdx v -{-# INLINE encodeTuple #-}-encodeTuple :: EncodeAcc acc -> Tuple (PreOpenExp acc env aenv) e -> Builder-encodeTuple _ NilTup        = intHost $(hashQ "NilTup")-encodeTuple h (SnocTup t e) = intHost $(hashQ "SnocTup") <> encodeTuple h t <> encodePreOpenExp h e+{-# INLINEABLE encodeOpenFun #-}+encodeOpenFun+    :: OpenFun env aenv f+    -> Builder+encodeOpenFun (Body b)    = intHost $(hashQ "Body") <> encodeOpenExp b+encodeOpenFun (Lam lhs l) = intHost $(hashQ "Lam") <> encodeLeftHandSide encodeScalarType lhs <> encodeOpenFun l  -{-# INLINE encodeConst #-}-encodeConst :: TupleType t -> t -> Builder-encodeConst TypeRunit         ()    = mempty-encodeConst (TypeRscalar t)   c     = encodeScalarConst t c-encodeConst (TypeRpair ta tb) (a,b) = encodeConst ta a <> encodeConst tb b+encodeConst :: TypeR t -> t -> Builder+encodeConst TupRunit         ()    = intHost $(hashQ "nil")+encodeConst (TupRsingle t)   c     = encodeScalarConst t c+encodeConst (TupRpair ta tb) (a,b) = intHost $(hashQ "pair") <> encodeConst ta a <> encodeConst tb b -{-# INLINE encodeScalarConst #-} encodeScalarConst :: ScalarType t -> t -> Builder encodeScalarConst (SingleScalarType t) = encodeSingleConst t encodeScalarConst (VectorScalarType t) = encodeVectorConst t -{-# INLINE encodeSingleConst #-} encodeSingleConst :: SingleType t -> t -> Builder-encodeSingleConst (NumSingleType t)    = encodeNumConst t-encodeSingleConst (NonNumSingleType t) = encodeNonNumConst t--{-# INLINE encodeVectorConst #-}-encodeVectorConst :: VectorType t -> t -> Builder-encodeVectorConst (Vector2Type t) (V2 a b)     = intHost $(hashQ "V2") <> encodeSingleConst t a <> encodeSingleConst t b-encodeVectorConst (Vector3Type t) (V3 a b c)   = intHost $(hashQ "V3") <> encodeSingleConst t a <> encodeSingleConst t b <> encodeSingleConst t c-encodeVectorConst (Vector4Type t) (V4 a b c d) = intHost $(hashQ "V4") <> encodeSingleConst t a <> encodeSingleConst t b <> encodeSingleConst t c <> encodeSingleConst t d-encodeVectorConst (Vector8Type t) (V8 a b c d e f g h) =-  intHost $(hashQ "V8") <> encodeSingleConst t a <> encodeSingleConst t b <> encodeSingleConst t c <> encodeSingleConst t d-                        <> encodeSingleConst t e <> encodeSingleConst t f <> encodeSingleConst t g <> encodeSingleConst t h-encodeVectorConst (Vector16Type t) (V16 a b c d e f g h i j k l m n o p) =-  intHost $(hashQ "V16") <> encodeSingleConst t a <> encodeSingleConst t b <> encodeSingleConst t c <> encodeSingleConst t d-                         <> encodeSingleConst t e <> encodeSingleConst t f <> encodeSingleConst t g <> encodeSingleConst t h-                         <> encodeSingleConst t i <> encodeSingleConst t j <> encodeSingleConst t k <> encodeSingleConst t l-                         <> encodeSingleConst t m <> encodeSingleConst t n <> encodeSingleConst t o <> encodeSingleConst t p--{-# INLINE encodeNonNumConst #-}-encodeNonNumConst :: NonNumType t -> t -> Builder-encodeNonNumConst TypeBool{}   x          = intHost $(hashQ "Bool")   <> word8 (fromBool x)-encodeNonNumConst TypeChar{}   x          = intHost $(hashQ "Char")   <> charUtf8 x-encodeNonNumConst TypeCSChar{} (CSChar x) = intHost $(hashQ "CSChar") <> int8 x-encodeNonNumConst TypeCUChar{} (CUChar x) = intHost $(hashQ "CUChar") <> word8 x-encodeNonNumConst TypeCChar{}  (CChar  x) = intHost $(hashQ "CChar")  <> $( case isSigned (undefined::CChar) of-                                                                              True  -> [e| int8  |]-                                                                              False -> [e| word8 |] ) x+encodeSingleConst (NumSingleType t) = encodeNumConst t -{-# INLINE fromBool #-}-fromBool :: Bool -> Word8-fromBool True  = 1-fromBool False = 0+encodeVectorConst :: VectorType (Vec n t) -> Vec n t -> Builder+encodeVectorConst (VectorType n t) (Vec ba#) = intHost $(hashQ "Vec") <> intHost n <> encodeSingleType t <> shortByteString (SBS ba#) -{-# INLINE encodeNumConst #-} encodeNumConst :: NumType t -> t -> Builder encodeNumConst (IntegralNumType t) = encodeIntegralConst t encodeNumConst (FloatingNumType t) = encodeFloatingConst t -{-# INLINE encodeIntegralConst #-} encodeIntegralConst :: IntegralType t -> t -> Builder-encodeIntegralConst TypeInt{}     x           = intHost $(hashQ "Int")     <> intHost x-encodeIntegralConst TypeInt8{}    x           = intHost $(hashQ "Int8")    <> int8 x-encodeIntegralConst TypeInt16{}   x           = intHost $(hashQ "Int16")   <> int16Host x-encodeIntegralConst TypeInt32{}   x           = intHost $(hashQ "Int32")   <> int32Host x-encodeIntegralConst TypeInt64{}   x           = intHost $(hashQ "Int64")   <> int64Host x-encodeIntegralConst TypeWord{}    x           = intHost $(hashQ "Word")    <> wordHost x-encodeIntegralConst TypeWord8{}   x           = intHost $(hashQ "Word8")   <> word8 x-encodeIntegralConst TypeWord16{}  x           = intHost $(hashQ "Word16")  <> word16Host x-encodeIntegralConst TypeWord32{}  x           = intHost $(hashQ "Word32")  <> word32Host x-encodeIntegralConst TypeWord64{}  x           = intHost $(hashQ "Word64")  <> word64Host x-encodeIntegralConst TypeCShort{}  (CShort x)  = intHost $(hashQ "CShort")  <> int16Host x-encodeIntegralConst TypeCUShort{} (CUShort x) = intHost $(hashQ "CUShort") <> word16Host x-encodeIntegralConst TypeCInt{}    (CInt x)    = intHost $(hashQ "CInt")    <> int32Host x-encodeIntegralConst TypeCUInt{}   (CUInt x)   = intHost $(hashQ "CUInt")   <> word32Host x-encodeIntegralConst TypeCLLong{}  (CLLong x)  = intHost $(hashQ "CLLong")  <> int64Host x-encodeIntegralConst TypeCULLong{} (CULLong x) = intHost $(hashQ "CULLong") <> word64Host x-encodeIntegralConst TypeCLong{}   (CLong x)   = intHost $(hashQ "CLong")   <> $( case finiteBitSize (undefined::CLong) of-                                                                                   32 -> [e| int32Host |]-                                                                                   64 -> [e| int64Host |]-                                                                                   _  -> error "I don't know what architecture I am" ) x-encodeIntegralConst TypeCULong{}  (CULong x)  = intHost $(hashQ "CULong")  <> $( case finiteBitSize (undefined::CULong) of-                                                                                   32 -> [e| word32Host |]-                                                                                   64 -> [e| word64Host |]-                                                                                   _  -> error "I don't know what architecture I am" ) x+encodeIntegralConst TypeInt{}    x = intHost $(hashQ "Int")    <> intHost x+encodeIntegralConst TypeInt8{}   x = intHost $(hashQ "Int8")   <> int8 x+encodeIntegralConst TypeInt16{}  x = intHost $(hashQ "Int16")  <> int16Host x+encodeIntegralConst TypeInt32{}  x = intHost $(hashQ "Int32")  <> int32Host x+encodeIntegralConst TypeInt64{}  x = intHost $(hashQ "Int64")  <> int64Host x+encodeIntegralConst TypeWord{}   x = intHost $(hashQ "Word")   <> wordHost x+encodeIntegralConst TypeWord8{}  x = intHost $(hashQ "Word8")  <> word8 x+encodeIntegralConst TypeWord16{} x = intHost $(hashQ "Word16") <> word16Host x+encodeIntegralConst TypeWord32{} x = intHost $(hashQ "Word32") <> word32Host x+encodeIntegralConst TypeWord64{} x = intHost $(hashQ "Word64") <> word64Host x -{-# INLINE encodeFloatingConst #-} encodeFloatingConst :: FloatingType t -> t -> Builder encodeFloatingConst TypeHalf{}    (Half (CUShort x)) = intHost $(hashQ "Half")    <> word16Host x encodeFloatingConst TypeFloat{}   x                  = intHost $(hashQ "Float")   <> floatHost x encodeFloatingConst TypeDouble{}  x                  = intHost $(hashQ "Double")  <> doubleHost x-encodeFloatingConst TypeCFloat{}  (CFloat x)         = intHost $(hashQ "CFloat")  <> floatHost x-encodeFloatingConst TypeCDouble{} (CDouble x)        = intHost $(hashQ "CDouble") <> doubleHost x -{-# INLINE encodePrimConst #-} encodePrimConst :: PrimConst c -> Builder encodePrimConst (PrimMinBound t)  = intHost $(hashQ "PrimMinBound") <> encodeBoundedType t encodePrimConst (PrimMaxBound t)  = intHost $(hashQ "PrimMaxBound") <> encodeBoundedType t encodePrimConst (PrimPi t)        = intHost $(hashQ "PrimPi")       <> encodeFloatingType t -{-# INLINE encodePrimFun #-} encodePrimFun :: PrimFun f -> Builder encodePrimFun (PrimAdd a)                = intHost $(hashQ "PrimAdd")                <> encodeNumType a encodePrimFun (PrimSub a)                = intHost $(hashQ "PrimSub")                <> encodeNumType a@@ -468,86 +451,54 @@ encodePrimFun PrimLAnd                   = intHost $(hashQ "PrimLAnd") encodePrimFun PrimLOr                    = intHost $(hashQ "PrimLOr") encodePrimFun PrimLNot                   = intHost $(hashQ "PrimLNot")-encodePrimFun PrimOrd                    = intHost $(hashQ "PrimOrd")-encodePrimFun PrimChr                    = intHost $(hashQ "PrimChr")-encodePrimFun PrimBoolToInt              = intHost $(hashQ "PrimBoolToInt")  -{-# INLINE encodeTupleType #-}-encodeTupleType :: TupleType t -> Builder-encodeTupleType TypeRunit       = intHost $(hashQ "TypeRunit")-encodeTupleType (TypeRscalar t) = intHost $(hashQ "TypeRscalar") <> encodeScalarType t-encodeTupleType (TypeRpair a b) = intHost $(hashQ "TypeRpair")   <> encodeTupleType a <> intHost (depthTypeR a)-                                                                 <> encodeTupleType b <> intHost (depthTypeR b)+encodeTypeR :: TypeR t -> Builder+encodeTypeR TupRunit       = intHost $(hashQ "TupRunit")+encodeTypeR (TupRsingle t) = intHost $(hashQ "TupRsingle") <> encodeScalarType t+encodeTypeR (TupRpair a b) = intHost $(hashQ "TupRpair")   <> encodeTypeR a <> intHost (depthTypeR a)+                                                           <> encodeTypeR b <> intHost (depthTypeR b) -{-# INLINE depthTypeR #-}-depthTypeR :: TupleType t -> Int-depthTypeR TypeRunit       = 0-depthTypeR TypeRscalar{}   = 1-depthTypeR (TypeRpair a b) = depthTypeR a + depthTypeR b+depthTypeR :: TypeR t -> Int+depthTypeR TupRunit       = 0+depthTypeR TupRsingle{}   = 1+depthTypeR (TupRpair a b) = depthTypeR a + depthTypeR b -{-# INLINE encodeScalarType #-} encodeScalarType :: ScalarType t -> Builder encodeScalarType (SingleScalarType t) = intHost $(hashQ "SingleScalarType") <> encodeSingleType t encodeScalarType (VectorScalarType t) = intHost $(hashQ "VectorScalarType") <> encodeVectorType t -{-# INLINE encodeSingleType #-} encodeSingleType :: SingleType t -> Builder-encodeSingleType (NumSingleType t)    = intHost $(hashQ "NumSingleType")    <> encodeNumType t-encodeSingleType (NonNumSingleType t) = intHost $(hashQ "NonNumSingleType") <> encodeNonNumType t+encodeSingleType (NumSingleType t) = intHost $(hashQ "NumSingleType")    <> encodeNumType t -{-# INLINE encodeVectorType #-}-encodeVectorType :: VectorType t -> Builder-encodeVectorType (Vector2Type t)  = intHost $(hashQ "Vector2Type") <> encodeSingleType t-encodeVectorType (Vector3Type t)  = intHost $(hashQ "Vector3Type") <> encodeSingleType t-encodeVectorType (Vector4Type t)  = intHost $(hashQ "Vector4Type") <> encodeSingleType t-encodeVectorType (Vector8Type t)  = intHost $(hashQ "Vector8Type") <> encodeSingleType t-encodeVectorType (Vector16Type t) = intHost $(hashQ "Vector16Type") <> encodeSingleType t+encodeVectorType :: VectorType (Vec n t) -> Builder+encodeVectorType (VectorType n t) = intHost $(hashQ "VectorType") <> intHost n <> encodeSingleType t -{-# INLINE encodeBoundedType #-} encodeBoundedType :: BoundedType t -> Builder encodeBoundedType (IntegralBoundedType t) = intHost $(hashQ "IntegralBoundedType") <> encodeIntegralType t-encodeBoundedType (NonNumBoundedType t)   = intHost $(hashQ "NonNumBoundedType")   <> encodeNonNumType t -{-# INLINE encodeNonNumType #-}-encodeNonNumType :: NonNumType t -> Builder-encodeNonNumType TypeBool{}   = intHost $(hashQ "Bool")-encodeNonNumType TypeChar{}   = intHost $(hashQ "Char")-encodeNonNumType TypeCChar{}  = intHost $(hashQ "CChar")-encodeNonNumType TypeCSChar{} = intHost $(hashQ "CSChar")-encodeNonNumType TypeCUChar{} = intHost $(hashQ "CUChar")--{-# INLINE encodeNumType #-} encodeNumType :: NumType t -> Builder encodeNumType (IntegralNumType t) = intHost $(hashQ "IntegralNumType") <> encodeIntegralType t encodeNumType (FloatingNumType t) = intHost $(hashQ "FloatingNumType") <> encodeFloatingType t -{-# INLINE encodeIntegralType #-} encodeIntegralType :: IntegralType t -> Builder-encodeIntegralType TypeInt{}     = intHost $(hashQ "Int")-encodeIntegralType TypeInt8{}    = intHost $(hashQ "Int8")-encodeIntegralType TypeInt16{}   = intHost $(hashQ "Int16")-encodeIntegralType TypeInt32{}   = intHost $(hashQ "Int32")-encodeIntegralType TypeInt64{}   = intHost $(hashQ "Int64")-encodeIntegralType TypeWord{}    = intHost $(hashQ "Word")-encodeIntegralType TypeWord8{}   = intHost $(hashQ "Word8")-encodeIntegralType TypeWord16{}  = intHost $(hashQ "Word16")-encodeIntegralType TypeWord32{}  = intHost $(hashQ "Word32")-encodeIntegralType TypeWord64{}  = intHost $(hashQ "Word64")-encodeIntegralType TypeCShort{}  = intHost $(hashQ "CShort")-encodeIntegralType TypeCUShort{} = intHost $(hashQ "CUShort")-encodeIntegralType TypeCInt{}    = intHost $(hashQ "CInt")-encodeIntegralType TypeCUInt{}   = intHost $(hashQ "CUInt")-encodeIntegralType TypeCLong{}   = intHost $(hashQ "CLong")-encodeIntegralType TypeCULong{}  = intHost $(hashQ "CULong")-encodeIntegralType TypeCLLong{}  = intHost $(hashQ "CLLong")-encodeIntegralType TypeCULLong{} = intHost $(hashQ "CULLong")+encodeIntegralType TypeInt{}    = intHost $(hashQ "Int")+encodeIntegralType TypeInt8{}   = intHost $(hashQ "Int8")+encodeIntegralType TypeInt16{}  = intHost $(hashQ "Int16")+encodeIntegralType TypeInt32{}  = intHost $(hashQ "Int32")+encodeIntegralType TypeInt64{}  = intHost $(hashQ "Int64")+encodeIntegralType TypeWord{}   = intHost $(hashQ "Word")+encodeIntegralType TypeWord8{}  = intHost $(hashQ "Word8")+encodeIntegralType TypeWord16{} = intHost $(hashQ "Word16")+encodeIntegralType TypeWord32{} = intHost $(hashQ "Word32")+encodeIntegralType TypeWord64{} = intHost $(hashQ "Word64") -{-# INLINE encodeFloatingType #-} encodeFloatingType :: FloatingType t -> Builder-encodeFloatingType TypeHalf{}    = intHost $(hashQ "Half")-encodeFloatingType TypeFloat{}   = intHost $(hashQ "Float")-encodeFloatingType TypeDouble{}  = intHost $(hashQ "Double")-encodeFloatingType TypeCFloat{}  = intHost $(hashQ "CFloat")-encodeFloatingType TypeCDouble{} = intHost $(hashQ "CDouble")+encodeFloatingType TypeHalf{}   = intHost $(hashQ "Half")+encodeFloatingType TypeFloat{}  = intHost $(hashQ "Float")+encodeFloatingType TypeDouble{} = intHost $(hashQ "Double")++encodeMaybe :: (a -> Builder) -> Maybe a -> Builder+encodeMaybe _ Nothing  = intHost $(hashQ "Nothing")+encodeMaybe f (Just x) = intHost $(hashQ "Just") <> f x 
src/Data/Array/Accelerate/Analysis/Hash/TH.hs view
@@ -1,9 +1,9 @@ -- | -- Module      : Data.Array.Accelerate.Analysis.Hash.TH--- Copyright   : [2017] Manuel M T Chakravarty, Gabriele Keller, Trevor L. McDonell+-- Copyright   : [2017..2020] The Accelerate Team -- License     : BSD3 ----- Maintainer  : Trevor L. McDonell <tmcdonell@cse.unsw.edu.au>+-- Maintainer  : Trevor L. McDonell <trevor.mcdonell@gmail.com> -- Stability   : experimental -- Portability : non-portable (GHC extensions) --
src/Data/Array/Accelerate/Analysis/Match.hs view
@@ -1,15 +1,18 @@+{-# LANGUAGE AllowAmbiguousTypes #-}+{-# LANGUAGE CPP                 #-} {-# LANGUAGE GADTs               #-} {-# LANGUAGE PatternGuards       #-} {-# LANGUAGE RankNTypes          #-} {-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TypeApplications    #-} {-# LANGUAGE TypeOperators       #-} {-# OPTIONS_HADDOCK hide #-} -- | -- Module      : Data.Array.Accelerate.Analysis.Match--- Copyright   : [2012..2017] Manuel M T Chakravarty, Gabriele Keller, Trevor L. McDonell+-- Copyright   : [2012..2020] The Accelerate Team -- License     : BSD3 ----- Maintainer  : Trevor L. McDonell <tmcdonell@cse.unsw.edu.au>+-- Maintainer  : Trevor L. McDonell <trevor.mcdonell@gmail.com> -- Stability   : experimental -- Portability : non-portable (GHC extensions) --@@ -21,32 +24,39 @@   (:~:)(..),   matchPreOpenAcc,   matchPreOpenAfun,-  matchPreOpenExp,-  matchPreOpenFun,+  matchOpenExp,+  matchOpenFun,   matchPrimFun,  matchPrimFun',    -- auxiliary-  matchIdx, matchTupleType,-  matchIntegralType, matchFloatingType, matchNumType, matchScalarType,+  matchIdx, matchVar, matchVars, matchArrayR, matchArraysR, matchTypeR, matchShapeR,+  matchShapeType, matchIntegralType, matchFloatingType, matchNumType, matchScalarType,+  matchLeftHandSide, matchALeftHandSide, matchELeftHandSide, matchSingleType, matchTupR  ) where --- standard library+import Data.Array.Accelerate.AST+import Data.Array.Accelerate.AST.Idx+import Data.Array.Accelerate.AST.LeftHandSide+import Data.Array.Accelerate.AST.Var+import Data.Array.Accelerate.Analysis.Hash+import Data.Array.Accelerate.Representation.Array+import Data.Array.Accelerate.Representation.Shape+import Data.Array.Accelerate.Representation.Slice+import Data.Array.Accelerate.Representation.Stencil+import Data.Array.Accelerate.Representation.Type+import Data.Array.Accelerate.Type+import Data.Primitive.Vec+import qualified Data.Array.Accelerate.Sugar.Shape      as Sugar+ import Data.Maybe import Data.Typeable+import Unsafe.Coerce                                    ( unsafeCoerce ) import System.IO.Unsafe                                 ( unsafePerformIO ) import System.Mem.StableName import Prelude                                          hiding ( exp ) --- friends-import Data.Array.Accelerate.AST-import Data.Array.Accelerate.Analysis.Hash-import Data.Array.Accelerate.Array.Representation       ( SliceIndex(..) )-import Data.Array.Accelerate.Array.Sugar-import Data.Array.Accelerate.Product-import Data.Array.Accelerate.Type - -- The type of matching array computations -- type MatchAcc acc = forall aenv s t. acc aenv s -> acc aenv t -> Maybe (s :~: t)@@ -57,50 +67,50 @@ -- {-# INLINEABLE matchPreOpenAcc #-} matchPreOpenAcc-    :: forall acc aenv s t.-       MatchAcc  acc-    -> EncodeAcc acc+    :: forall acc aenv s t. HasArraysR acc+    => MatchAcc  acc     -> PreOpenAcc acc aenv s     -> PreOpenAcc acc aenv t     -> Maybe (s :~: t)-matchPreOpenAcc matchAcc encodeAcc = match+matchPreOpenAcc matchAcc = match   where-    matchFun :: PreOpenFun acc env' aenv' u -> PreOpenFun acc env' aenv' v -> Maybe (u :~: v)-    matchFun = matchPreOpenFun matchAcc encodeAcc+    matchFun :: OpenFun env' aenv' u -> OpenFun env' aenv' v -> Maybe (u :~: v)+    matchFun = matchOpenFun -    matchExp :: PreOpenExp acc env' aenv' u -> PreOpenExp acc env' aenv' v -> Maybe (u :~: v)-    matchExp = matchPreOpenExp matchAcc encodeAcc+    matchExp :: OpenExp env' aenv' u -> OpenExp env' aenv' v -> Maybe (u :~: v)+    matchExp = matchOpenExp      match :: PreOpenAcc acc aenv s -> PreOpenAcc acc aenv t -> Maybe (s :~: t)-    match (Alet x1 a1) (Alet x2 a2)-      | Just Refl <- matchAcc x1 x2+    match (Alet lhs1 x1 a1) (Alet lhs2 x2 a2)+      | Just Refl <- matchALeftHandSide lhs1 lhs2+      , Just Refl <- matchAcc x1 x2       , Just Refl <- matchAcc a1 a2       = Just Refl      match (Avar v1) (Avar v2)-      = matchIdx v1 v2+      = matchVar v1 v2 -    match (Atuple t1) (Atuple t2)-      | Just Refl <- matchAtuple matchAcc t1 t2-      = gcast Refl  -- surface/representation type+    match (Apair a1 a2) (Apair b1 b2)+      | Just Refl <- matchAcc a1 b1+      , Just Refl <- matchAcc a2 b2+      = Just Refl -    match (Aprj ix1 t1) (Aprj ix2 t2)-      | Just Refl <- matchAcc t1 t2-      , Just Refl <- matchTupleIdx ix1 ix2+    match Anil Anil       = Just Refl -    match (Apply f1 a1) (Apply f2 a2)+    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)+    match (Aforeign _ ff1 f1 a1) (Aforeign _ ff2 f2 a2)       | Just Refl <- matchAcc a1 a2       , unsafePerformIO $ do           sn1 <- makeStableName ff1           sn2 <- makeStableName ff2           return $! hashStableName sn1 == hashStableName sn2-      = gcast Refl+      , Just Refl <- matchPreOpenAfun matchAcc f1 f2+      = Just Refl      match (Acond p1 t1 e1) (Acond p2 t2 e2)       | Just Refl <- matchExp p1 p2@@ -114,47 +124,50 @@       , 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 (Use repr1 a1) (Use repr2 a2)+      | Just Refl <- matchArray repr1 repr2 a1 a2+      = Just Refl -    match (Unit e1) (Unit e2)-      | Just Refl <- matchExp e1 e2+    match (Unit t1 e1) (Unit t2 e2)+      | Just Refl <- matchTypeR t1 t2+      , Just Refl <- matchExp e1 e2       = Just Refl -    match (Reshape sh1 a1) (Reshape sh2 a2)+    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)+    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)+    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+    match (Replicate si1 ix1 a1) (Replicate si2 ix2 a2)+      | Just Refl <- matchSliceIndex si1 si2+      , Just Refl <- matchExp ix1 ix2       , Just Refl <- matchAcc a1  a2-      = gcast Refl  -- slice specification ??+      = Just Refl -    match (Slice _ a1 ix1) (Slice _ a2 ix2)-      | Just Refl <- matchAcc a1  a2+    match (Slice si1 a1 ix1) (Slice si2 a2 ix2)+      | Just Refl <- matchSliceIndex si1 si2+      , Just Refl <- matchAcc a1  a2       , Just Refl <- matchExp ix1 ix2-      = gcast Refl  -- slice specification ??+      = Just Refl -    match (Map f1 a1) (Map f2 a2)+    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)+    match (ZipWith _ f1 a1 b1) (ZipWith _ f2 a2 b2)       | Just Refl <- matchFun f1 f2       , Just Refl <- matchAcc a1 a2       , Just Refl <- matchAcc b1 b2@@ -162,62 +175,31 @@      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+      , matchMaybe matchExp z1 z2       , 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)+    match (FoldSeg _ f1 z1 a1 s1) (FoldSeg _ f2 z2 a2 s2)       | Just Refl <- matchFun f1 f2+      , matchMaybe matchExp z1 z2       , 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+    match (Scan d1 f1 z1 a1) (Scan d2 f2 z2 a2)+      | d1 == d2+      , Just Refl <- matchFun f1 f2+      , matchMaybe matchExp z1 z2       , Just Refl <- matchAcc a1 a2       = Just Refl -    match (Scanr' f1 z1 a1) (Scanr' f2 z2 a2)-      | Just Refl <- matchFun f1 f2+    match (Scan' d1 f1 z1 a1) (Scan' d2 f2 z2 a2)+      | d1 == d2+      , 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@@ -225,24 +207,24 @@       , Just Refl <- matchAcc a1 a2       = Just Refl -    match (Backpermute sh1 ix1 a1) (Backpermute sh2 ix2 a2)+    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) (Stencil f2 b2 a2)+    match (Stencil s1 _ f1 b1 a1) (Stencil _ _ f2 b2 a2)       | Just Refl <- matchFun f1 f2       , Just Refl <- matchAcc a1 a2-      , matchBoundary matchAcc encodeAcc b1 b2+      , matchBoundary (stencilEltR s1) b1 b2       = Just Refl -    match (Stencil2 f1 b1  a1  b2  a2) (Stencil2 f2 b1' a1' b2' a2')+    match (Stencil2 s1 s2 _ f1 b1  a1  b2  a2) (Stencil2 _ _ _ f2 b1' a1' b2' a2')       | Just Refl <- matchFun f1 f2       , Just Refl <- matchAcc a1 a1'       , Just Refl <- matchAcc a2 a2'-      , matchBoundary matchAcc encodeAcc b1 b1'-      , matchBoundary matchAcc encodeAcc b2 b2'+      , matchBoundary (stencilEltR s1) b1 b1'+      , matchBoundary (stencilEltR s2) b2 b2'       = Just Refl      -- match (Collect s1) (Collect s2)@@ -251,24 +233,6 @@     match _ _       = Nothing ---- Array tuples----{-# INLINEABLE matchAtuple #-}-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 -- {-# INLINEABLE matchPreOpenAfun #-}@@ -277,44 +241,72 @@     -> PreOpenAfun acc aenv s     -> PreOpenAfun acc aenv t     -> Maybe (s :~: t)-matchPreOpenAfun m (Alam s) (Alam t)-  | Just Refl <- matchEnvTop        s t+matchPreOpenAfun m (Alam lhs1 s) (Alam lhs2 t)+  | Just Refl <- matchALeftHandSide lhs1 lhs2   , 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+matchPreOpenAfun _ _           _           = Nothing +matchALeftHandSide+    :: forall aenv aenv1 aenv2 t1 t2.+       ALeftHandSide t1 aenv aenv1+    -> ALeftHandSide t2 aenv aenv2+    -> Maybe (ALeftHandSide t1 aenv aenv1 :~: ALeftHandSide t2 aenv aenv2)+matchALeftHandSide = matchLeftHandSide matchArrayR +matchELeftHandSide+    :: forall env env1 env2 t1 t2.+       ELeftHandSide t1 env env1+    -> ELeftHandSide t2 env env2+    -> Maybe (ELeftHandSide t1 env env1 :~: ELeftHandSide t2 env env2)+matchELeftHandSide = matchLeftHandSide matchScalarType++matchLeftHandSide+    :: forall s env env1 env2 t1 t2.+      (forall x y. s x -> s y -> Maybe (x :~: y))+    -> LeftHandSide s t1 env env1+    -> LeftHandSide s t2 env env2+    -> Maybe (LeftHandSide s t1 env env1 :~: LeftHandSide s t2 env env2)+matchLeftHandSide f (LeftHandSideWildcard repr1) (LeftHandSideWildcard repr2)+  | Just Refl <- matchTupR f repr1 repr2+  = Just Refl+matchLeftHandSide f (LeftHandSideSingle x) (LeftHandSideSingle y)+  | Just Refl <- f x y+  = Just Refl+matchLeftHandSide f (LeftHandSidePair a1 a2) (LeftHandSidePair b1 b2)+  | Just Refl <- matchLeftHandSide f a1 b1+  , Just Refl <- matchLeftHandSide f a2 b2+  = Just Refl+matchLeftHandSide _ _ _ = Nothing+ -- Match stencil boundaries ---{-# INLINEABLE matchBoundary #-} matchBoundary-    :: forall acc aenv sh t. Elt t-    => MatchAcc  acc-    -> EncodeAcc acc-    -> PreBoundary acc aenv (Array sh t)-    -> PreBoundary acc aenv (Array sh t)+    :: TypeR t+    -> Boundary aenv (Array sh t)+    -> Boundary aenv (Array sh t)     -> Bool-matchBoundary _ _ Clamp        Clamp        = True-matchBoundary _ _ Mirror       Mirror       = True-matchBoundary _ _ Wrap         Wrap         = True-matchBoundary _ _ (Constant s) (Constant t) = matchConst (eltType (undefined::t)) s t-matchBoundary m h (Function f) (Function g)-  | Just Refl <- matchPreOpenFun m h f g+matchBoundary _  Clamp        Clamp        = True+matchBoundary _  Mirror       Mirror       = True+matchBoundary _  Wrap         Wrap         = True+matchBoundary tp (Constant s) (Constant t) = matchConst tp s t+matchBoundary _  (Function f) (Function g)+  | Just Refl <- matchOpenFun f g   = True-matchBoundary _ _ _ _+matchBoundary _ _ _   = False +matchMaybe :: (s1 -> s2 -> Maybe (t1 :~: t2)) -> Maybe s1 -> Maybe s2 -> Bool+matchMaybe _ Nothing  Nothing  = True+matchMaybe f (Just x) (Just y)+  | Just Refl <- f x y         = True+matchMaybe _ _        _        = False  {-- -- Match sequences ---{-# INLINEABLE matchSeq #-} matchSeq     :: forall acc aenv senv s t.        MatchAcc  acc@@ -324,11 +316,11 @@     -> 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+    matchFun :: OpenFun env' aenv' u -> OpenFun env' aenv' v -> Maybe (u :~: v)+    matchFun = matchOpenFun m h -    matchExp :: PreOpenExp acc env' aenv' u -> PreOpenExp acc env' aenv' v -> Maybe (u :~: v)-    matchExp = matchPreOpenExp m h+    matchExp :: OpenExp env' aenv' u -> OpenExp env' aenv' v -> Maybe (u :~: v)+    matchExp = matchOpenExp m h      match :: PreOpenSeq acc aenv senv' u -> PreOpenSeq acc aenv senv' v -> Maybe (u :~: v)     match (Producer p1 s1)   (Producer p2 s2)@@ -395,27 +387,40 @@ -- As a convenience, we are just comparing the stable names, but we could also -- walk the structure comparing the underlying ptrsOfArrayData. ---{-# INLINEABLE matchArrays #-}-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+matchArray :: ArrayR (Array sh1 e1)+           -> ArrayR (Array sh2 e2)+           -> Array sh1 e1+           -> Array sh2 e2+           -> Maybe (Array sh1 e1 :~: Array sh2 e2)+matchArray repr1 repr2 (Array _ ad1) (Array _ ad2)+  | Just Refl <- matchArrayR repr1 repr2+  , unsafePerformIO $ do       sn1 <- makeStableName ad1       sn2 <- makeStableName ad2       return $! hashStableName sn1 == hashStableName sn2-  = gcast Refl+  = Just Refl -matchArrays _ _ _ _+matchArray _ _ _ _   = Nothing +matchTupR :: (forall u1 u2. s u1 -> s u2 -> Maybe (u1 :~: u2)) -> TupR s t1 -> TupR s t2 -> Maybe (t1 :~: t2)+matchTupR _ TupRunit         TupRunit         = Just Refl+matchTupR f (TupRsingle x)   (TupRsingle y)   = f x y+matchTupR f (TupRpair x1 x2) (TupRpair y1 y2)+  | Just Refl <- matchTupR f x1 y1+  , Just Refl <- matchTupR f x2 y2            = Just Refl+matchTupR _ _                _                = Nothing +matchArraysR :: ArraysR s -> ArraysR t -> Maybe (s :~: t)+matchArraysR = matchTupR matchArrayR++matchArrayR :: ArrayR s -> ArrayR t -> Maybe (s :~: t)+matchArrayR (ArrayR shr1 tp1) (ArrayR shr2 tp2)+  | Just Refl <- matchShapeR shr1 shr2+  , Just Refl <- matchTypeR tp1 tp2 = Just Refl+matchArrayR _ _ = Nothing++ -- Compute the congruence of two scalar expressions. Two nodes are congruent if -- either: --@@ -425,208 +430,152 @@ -- 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. ---{-# INLINEABLE matchPreOpenExp #-}-matchPreOpenExp-    :: forall acc env aenv s t.-       MatchAcc  acc-    -> EncodeAcc acc-    -> PreOpenExp acc env aenv s-    -> PreOpenExp acc env aenv t+{-# INLINEABLE matchOpenExp #-}+matchOpenExp+    :: forall env aenv s t.+       OpenExp env aenv s+    -> OpenExp env aenv t     -> Maybe (s :~: t)-matchPreOpenExp matchAcc encodeAcc = 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 Undef Undef-      | Just Refl <- matchTupleType (eltType (undefined::s')) (eltType (undefined::t'))-      = gcast Refl--    match (Coerce e1) (Coerce e2)-      | Just Refl <- matchTupleType (eltType (undefined::s')) (eltType (undefined::t'))-      , Just Refl <- match e1 e2-      = gcast Refl--    match (Tuple t1) (Tuple t2)-      | Just Refl <- matchTuple matchAcc encodeAcc 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+matchOpenExp (Let lhs1 x1 e1) (Let lhs2 x2 e2)+  | Just Refl <- matchELeftHandSide lhs1 lhs2+  , Just Refl <- matchOpenExp x1 x2+  , Just Refl <- matchOpenExp e1 e2+  = Just Refl -    match IndexAny IndexAny-      = gcast Refl  -- ???+matchOpenExp (Evar v1) (Evar v2)+  = matchVar v1 v2 -    match IndexNil IndexNil-      = Just Refl+matchOpenExp (Foreign _ ff1 f1 e1) (Foreign _ ff2 f2 e2)+  | Just Refl <- matchOpenExp e1 e2+  , unsafePerformIO $ do+      sn1 <- makeStableName ff1+      sn2 <- makeStableName ff2+      return $! hashStableName sn1 == hashStableName sn2+  , Just Refl <- matchOpenFun f1 f2+  = Just Refl -    match (IndexCons sl1 a1) (IndexCons sl2 a2)-      | Just Refl <- match sl1 sl2-      , Just Refl <- match a1 a2-      = Just Refl+matchOpenExp (Const t1 c1) (Const t2 c2)+  | Just Refl <- matchScalarType t1 t2+  , matchConst (TupRsingle t1) c1 c2+  = Just Refl -    match (IndexHead sl1) (IndexHead sl2)-      | Just Refl <- match sl1 sl2-      = Just Refl+matchOpenExp (Undef t1) (Undef t2) = matchScalarType t1 t2 -    match (IndexTail sl1) (IndexTail sl2)-      | Just Refl <- match sl1 sl2-      = Just Refl+matchOpenExp (Coerce _ t1 e1) (Coerce _ t2 e2)+  | Just Refl <- matchScalarType t1 t2+  , Just Refl <- matchOpenExp e1 e2+  = 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+matchOpenExp (Pair a1 b1) (Pair a2 b2)+  | Just Refl <- matchOpenExp a1 a2+  , Just Refl <- matchOpenExp b1 b2+  = Just Refl -    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+matchOpenExp Nil Nil+  = Just Refl -    match (ToIndex sh1 i1) (ToIndex sh2 i2)-      | Just Refl <- match sh1 sh2-      , Just Refl <- match i1  i2-      = Just Refl+matchOpenExp (IndexSlice sliceIndex1 ix1 sh1) (IndexSlice sliceIndex2 ix2 sh2)+  | Just Refl <- matchOpenExp ix1 ix2+  , Just Refl <- matchOpenExp sh1 sh2+  , Just Refl <- matchSliceIndex sliceIndex1 sliceIndex2+  = Just Refl -    match (FromIndex sh1 i1) (FromIndex sh2 i2)-      | Just Refl <- match i1  i2-      , Just Refl <- match sh1 sh2-      = Just Refl+matchOpenExp (IndexFull sliceIndex1 ix1 sl1) (IndexFull sliceIndex2 ix2 sl2)+  | Just Refl <- matchOpenExp ix1 ix2+  , Just Refl <- matchOpenExp sl1 sl2+  , Just Refl <- matchSliceIndex sliceIndex1 sliceIndex2+  = 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+matchOpenExp (ToIndex _ sh1 i1) (ToIndex _ sh2 i2)+  | Just Refl <- matchOpenExp sh1 sh2+  , Just Refl <- matchOpenExp i1  i2+  = Just Refl -    match (While p1 f1 x1) (While p2 f2 x2)-      | Just Refl <- match x1 x2-      , Just Refl <- matchPreOpenFun matchAcc encodeAcc p1 p2-      , Just Refl <- matchPreOpenFun matchAcc encodeAcc f1 f2-      = Just Refl+matchOpenExp (FromIndex _ sh1 i1) (FromIndex _ sh2 i2)+  | Just Refl <- matchOpenExp i1  i2+  , Just Refl <- matchOpenExp sh1 sh2+  = Just Refl -    match (PrimConst c1) (PrimConst c2)-      = matchPrimConst c1 c2+matchOpenExp (Cond p1 t1 e1) (Cond p2 t2 e2)+  | Just Refl <- matchOpenExp p1 p2+  , Just Refl <- matchOpenExp t1 t2+  , Just Refl <- matchOpenExp e1 e2+  = Just Refl -    match (PrimApp f1 x1) (PrimApp f2 x2)-      | Just x1'  <- commutes encodeAcc f1 x1-      , Just x2'  <- commutes encodeAcc f2 x2-      , Just Refl <- match        x1' x2'-      , Just Refl <- matchPrimFun f1  f2-      = Just Refl+matchOpenExp (While p1 f1 x1) (While p2 f2 x2)+  | Just Refl <- matchOpenExp x1 x2+  , Just Refl <- matchOpenFun p1 p2+  , Just Refl <- matchOpenFun f1 f2+  = Just Refl -      | Just Refl <- match x1 x2-      , Just Refl <- matchPrimFun f1 f2-      = Just Refl+matchOpenExp (PrimConst c1) (PrimConst c2)+  = matchPrimConst c1 c2 -    match (Index a1 x1) (Index a2 x2)-      | Just Refl <- matchAcc a1 a2     -- should only be array indices-      , Just Refl <- match    x1 x2-      = Just Refl+matchOpenExp (PrimApp f1 x1) (PrimApp f2 x2)+  | Just x1'  <- commutes f1 x1+  , Just x2'  <- commutes f2 x2+  , Just Refl <- matchOpenExp x1' x2'+  , Just Refl <- matchPrimFun f1  f2+  = Just Refl -    match (LinearIndex a1 x1) (LinearIndex a2 x2)-      | Just Refl <- matchAcc a1 a2-      , Just Refl <- match    x1 x2-      = Just Refl+  | Just Refl <- matchOpenExp x1 x2+  , Just Refl <- matchPrimFun f1 f2+  = Just Refl -    match (Shape a1) (Shape a2)-      | Just Refl <- matchAcc a1 a2     -- should only be array indices-      = Just Refl+matchOpenExp (Index a1 x1) (Index a2 x2)+  | Just Refl <- matchVar a1 a2+  , Just Refl <- matchOpenExp x1 x2+  = Just Refl -    match (ShapeSize sh1) (ShapeSize sh2)-      | Just Refl <- match sh1 sh2-      = Just Refl+matchOpenExp (LinearIndex a1 x1) (LinearIndex a2 x2)+  | Just Refl <- matchVar a1 a2+  , Just Refl <- matchOpenExp x1 x2+  = Just Refl -    match (Intersect sa1 sb1) (Intersect sa2 sb2)-      | Just Refl <- match sa1 sa2-      , Just Refl <- match sb1 sb2-      = Just Refl+matchOpenExp (Shape a1) (Shape a2)+  | Just Refl <- matchVar a1 a2+  = Just Refl -    match (Union sa1 sb1) (Union sa2 sb2)-      | Just Refl <- match sa1 sa2-      , Just Refl <- match sb1 sb2-      = Just Refl+matchOpenExp (ShapeSize _ sh1) (ShapeSize _ sh2)+  | Just Refl <- matchOpenExp sh1 sh2+  = Just Refl -    match _ _-      = Nothing+matchOpenExp _ _+  = Nothing   -- Match scalar functions ---{-# INLINEABLE matchPreOpenFun #-}-matchPreOpenFun-    :: MatchAcc  acc-    -> EncodeAcc acc-    -> PreOpenFun acc env aenv s-    -> PreOpenFun acc env aenv t+{-# INLINEABLE matchOpenFun #-}+matchOpenFun+    :: OpenFun env aenv s+    -> OpenFun 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+matchOpenFun (Lam lhs1 s) (Lam lhs2 t)+  | Just Refl <- matchELeftHandSide lhs1 lhs2+  , Just Refl <- matchOpenFun 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+matchOpenFun (Body s) (Body t) = matchOpenExp s t+matchOpenFun _        _        = Nothing  -- Matching constants ---{-# INLINEABLE matchConst #-}-matchConst :: TupleType a -> a -> a -> Bool-matchConst TypeRunit         ()      ()      = True-matchConst (TypeRscalar ty)  a       b       = evalEq ty (a,b)-matchConst (TypeRpair ta tb) (a1,b1) (a2,b2) = matchConst ta a1 a2 && matchConst tb b1 b2+matchConst :: TypeR a -> a -> a -> Bool+matchConst TupRunit         ()      ()      = True+matchConst (TupRsingle ty)  a       b       = evalEq ty (a,b)+matchConst (TupRpair ta tb) (a1,b1) (a2,b2) = matchConst ta a1 a2 && matchConst tb b1 b2  evalEq :: ScalarType a -> (a, a) -> Bool evalEq (SingleScalarType t) = evalEqSingle t evalEq (VectorScalarType t) = evalEqVector t  evalEqSingle :: SingleType a -> (a, a) -> Bool-evalEqSingle (NumSingleType t)                                  = evalEqNum t-evalEqSingle (NonNumSingleType t) | NonNumDict <- nonNumDict t  = uncurry (==)+evalEqSingle (NumSingleType t) = evalEqNum t  evalEqVector :: VectorType a -> (a, a) -> Bool-evalEqVector (Vector2Type t) (V2 a1 b1, V2 a2 b2)             = evalEqSingle t (a1,a2) && evalEqSingle t (b1,b2)-evalEqVector (Vector3Type t) (V3 a1 b1 c1, V3 a2 b2 c2)       = evalEqSingle t (a1,a2) && evalEqSingle t (b1,b2) && evalEqSingle t (c1,c2)-evalEqVector (Vector4Type t) (V4 a1 b1 c1 d1, V4 a2 b2 c2 d2) = evalEqSingle t (a1,a2) && evalEqSingle t (b1,b2) && evalEqSingle t (c1,c2) && evalEqSingle t (d1,d2)-evalEqVector (Vector8Type t) ( V8 a1 b1 c1 d1 e1 f1 g1 h1-                             , V8 a2 b2 c2 d2 e2 f2 g2 h2 ) =-  evalEqSingle t (a1,a2) && evalEqSingle t (b1,b2) && evalEqSingle t (c1,c2) && evalEqSingle t (d1,d2) &&-  evalEqSingle t (e1,e2) && evalEqSingle t (f1,f2) && evalEqSingle t (g1,g2) && evalEqSingle t (h1,h2)-evalEqVector (Vector16Type t) ( V16 a1 b1 c1 d1 e1 f1 g1 h1 i1 j1 k1 l1 m1 n1 o1 p1-                              , V16 a2 b2 c2 d2 e2 f2 g2 h2 i2 j2 k2 l2 m2 n2 o2 p2 ) =-  evalEqSingle t (a1,a2) && evalEqSingle t (b1,b2) && evalEqSingle t (c1,c2) && evalEqSingle t (d1,d2) &&-  evalEqSingle t (e1,e2) && evalEqSingle t (f1,f2) && evalEqSingle t (g1,g2) && evalEqSingle t (h1,h2) &&-  evalEqSingle t (i1,i2) && evalEqSingle t (j1,j2) && evalEqSingle t (k1,k2) && evalEqSingle t (l1,l2) &&-  evalEqSingle t (m1,m2) && evalEqSingle t (n1,n2) && evalEqSingle t (o1,o2) && evalEqSingle t (p1,p2)+evalEqVector VectorType{} = uncurry (==)  evalEqNum :: NumType a -> (a, a) -> Bool evalEqNum (IntegralNumType t) | IntegralDict <- integralDict t  = uncurry (==)@@ -641,79 +590,40 @@ 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.----{-# INLINEABLE matchTupleIdx #-}-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----{-# INLINEABLE matchTuple #-}-matchTuple-    :: MatchAcc  acc-    -> EncodeAcc 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+{-# INLINEABLE matchVar #-}+matchVar :: Var s env t1 -> Var s env t2 -> Maybe (t1 :~: t2)+matchVar (Var _ v1) (Var _ v2) = matchIdx v1 v2 -matchTuple _ _ _               _                = Nothing+{-# INLINEABLE matchVars #-}+matchVars :: Vars s env t1 -> Vars s env t2 -> Maybe (t1 :~: t2)+matchVars TupRunit         TupRunit = Just Refl+matchVars (TupRsingle v1) (TupRsingle v2)+  | Just Refl <- matchVar v1 v2 = Just Refl+matchVars (TupRpair v w) (TupRpair x y)+  | Just Refl <- matchVars v x+  , Just Refl <- matchVars w y  = Just Refl+matchVars _ _ = Nothing   -- Slice specifications ---{-# INLINEABLE matchSliceRestrict #-}-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---{-# INLINEABLE matchSliceExtend #-}-matchSliceExtend-    :: SliceIndex slix sl co  s-    -> SliceIndex slix sl co' t-    -> Maybe (s :~: t)-matchSliceExtend SliceNil SliceNil+matchSliceIndex :: SliceIndex slix1 sl1 co1 sh1 -> SliceIndex slix2 sl2 co2 sh2 -> Maybe (SliceIndex slix1 sl1 co1 sh1 :~: SliceIndex slix2 sl2 co2 sh2)+matchSliceIndex SliceNil SliceNil   = Just Refl -matchSliceExtend (SliceAll   sl1) (SliceAll   sl2)-  | Just Refl <- matchSliceExtend sl1 sl2+matchSliceIndex (SliceAll   sl1) (SliceAll   sl2)+  | Just Refl <- matchSliceIndex sl1 sl2   = Just Refl -matchSliceExtend (SliceFixed sl1) (SliceFixed sl2)-  | Just Refl <- matchSliceExtend sl1 sl2+matchSliceIndex (SliceFixed sl1) (SliceFixed sl2)+  | Just Refl <- matchSliceIndex sl1 sl2   = Just Refl -matchSliceExtend _ _+matchSliceIndex _ _   = Nothing - -- Primitive constants and functions ---{-# INLINEABLE matchPrimConst #-} matchPrimConst :: PrimConst s -> PrimConst t -> Maybe (s :~: t) matchPrimConst (PrimMinBound s) (PrimMinBound t) = matchBoundedType s t matchPrimConst (PrimMaxBound s) (PrimMaxBound t) = matchBoundedType s t@@ -724,7 +634,7 @@ -- Covariant function matching -- {-# INLINEABLE matchPrimFun #-}-matchPrimFun :: (Typeable s, Typeable t) => PrimFun (a -> s) -> PrimFun (a -> t) -> Maybe (s :~: t)+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@@ -787,9 +697,6 @@ 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@@ -798,7 +705,7 @@ -- Contravariant function matching -- {-# INLINEABLE matchPrimFun' #-}-matchPrimFun' :: (Typeable s, Typeable t) => PrimFun (s -> a) -> PrimFun (t -> a) -> Maybe (s :~: t)+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@@ -855,9 +762,6 @@ 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 <- matchSingleType s t@@ -889,19 +793,40 @@  -- Match reified types ---{-# INLINEABLE matchTupleType #-}-matchTupleType :: TupleType s -> TupleType t -> Maybe (s :~: t)-matchTupleType TypeRunit         TypeRunit         = Just Refl-matchTupleType (TypeRscalar s)   (TypeRscalar t)   = matchScalarType s t-matchTupleType (TypeRpair s1 s2) (TypeRpair t1 t2)-  | Just Refl <- matchTupleType s1 t1-  , Just Refl <- matchTupleType s2 t2-  = Just Refl+{-# INLINEABLE matchTypeR #-}+matchTypeR :: TypeR s -> TypeR t -> Maybe (s :~: t)+matchTypeR = matchTupR matchScalarType -matchTupleType _ _++-- Match shapes (dimensionality)+--+-- XXX: Matching shapes is sort of a special case because the representation+-- types really are isomorphic to the surface type. However, 'gcast' does not+-- inline here, meaning that it will always do the fingerprint check, even if+-- the dimensions are known statically and thus the check could be elided as+-- a known branch.+--+{-# INLINEABLE matchShapeType #-}+matchShapeType :: forall s t. (Sugar.Shape s, Sugar.Shape t) => Maybe (s :~: t)+matchShapeType+  | Just Refl <- matchShapeR (Sugar.shapeR @s) (Sugar.shapeR @t)+#ifdef ACCELERATE_INTERNAL_CHECKS+  = gcast Refl+#else+  = Just (unsafeCoerce Refl)+#endif+  | otherwise   = Nothing +{-# INLINEABLE matchShapeR #-}+matchShapeR :: forall s t. ShapeR s -> ShapeR t -> Maybe (s :~: t)+matchShapeR ShapeRz ShapeRz = Just Refl+matchShapeR (ShapeRsnoc shr1) (ShapeRsnoc shr2)+  | Just Refl <- matchShapeR shr1 shr2+  = Just Refl+matchShapeR _ _ = Nothing + -- Match reified type dictionaries -- {-# INLINEABLE matchScalarType #-}@@ -912,26 +837,15 @@  {-# INLINEABLE matchSingleType #-} matchSingleType :: SingleType s -> SingleType t -> Maybe (s :~: t)-matchSingleType (NumSingleType s)    (NumSingleType t)    = matchNumType s t-matchSingleType (NonNumSingleType s) (NonNumSingleType t) = matchNonNumType s t-matchSingleType _                    _                    = Nothing+matchSingleType (NumSingleType s) (NumSingleType t) = matchNumType s t  {-# INLINEABLE matchVectorType #-}-matchVectorType :: VectorType s -> VectorType t -> Maybe (s :~: t)-matchVectorType (Vector2Type s) (Vector2Type t)-  | Just Refl <- matchSingleType s t-  = Just Refl-matchVectorType (Vector3Type s) (Vector3Type t)-  | Just Refl <- matchSingleType s t-  = Just Refl-matchVectorType (Vector4Type s) (Vector4Type t)-  | Just Refl <- matchSingleType s t-  = Just Refl-matchVectorType (Vector8Type s) (Vector8Type t)-  | Just Refl <- matchSingleType s t-  = Just Refl-matchVectorType (Vector16Type s) (Vector16Type t)-  | Just Refl <- matchSingleType s t+matchVectorType :: forall m n s t. VectorType (Vec n s) -> VectorType (Vec m t) -> Maybe (Vec n s :~: Vec m t)+matchVectorType (VectorType n s) (VectorType m t)+  | Just Refl <- if n == m+                   then Just (unsafeCoerce Refl :: n :~: m) -- XXX: we don't have an embedded KnownNat constraint, but+                   else Nothing                             -- this implementation is the same as 'GHC.TypeLits.sameNat'+  , Just Refl <- matchSingleType s t   = Just Refl matchVectorType _ _   = Nothing@@ -945,48 +859,27 @@ {-# INLINEABLE matchBoundedType #-} 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  {-# INLINEABLE matchIntegralType #-} 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+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 _            _            = Nothing  {-# INLINEABLE matchFloatingType #-} matchFloatingType :: FloatingType s -> FloatingType t -> Maybe (s :~: t)-matchFloatingType TypeHalf{}    TypeHalf{}    = Just Refl-matchFloatingType TypeFloat{}   TypeFloat{}   = Just Refl-matchFloatingType TypeDouble{}  TypeDouble{}  = Just Refl-matchFloatingType TypeCFloat{}  TypeCFloat{}  = Just Refl-matchFloatingType TypeCDouble{} TypeCDouble{} = Just Refl-matchFloatingType _             _             = Nothing--{-# INLINEABLE matchNonNumType #-}-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+matchFloatingType TypeHalf   TypeHalf   = Just Refl+matchFloatingType TypeFloat  TypeFloat  = Just Refl+matchFloatingType TypeDouble TypeDouble = Just Refl+matchFloatingType _            _            = Nothing   -- Auxiliary@@ -997,12 +890,11 @@ -- commutativity. -- commutes-    :: forall acc env aenv a r.-       EncodeAcc acc-    -> PrimFun (a -> r)-    -> PreOpenExp acc env aenv a-    -> Maybe (PreOpenExp acc env aenv a)-commutes h f x = case f of+    :: forall env aenv a r.+       PrimFun (a -> r)+    -> OpenExp env aenv a+    -> Maybe (OpenExp env aenv a)+commutes f x = case f of   PrimAdd{}     -> Just (swizzle x)   PrimMul{}     -> Just (swizzle x)   PrimBAnd{}    -> Just (swizzle x)@@ -1016,10 +908,10 @@   PrimLOr       -> Just (swizzle x)   _             -> Nothing   where-    swizzle :: PreOpenExp acc env aenv (a',a') -> PreOpenExp acc env aenv (a',a')+    swizzle :: OpenExp env aenv (a',a') -> OpenExp 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)+      | (a `Pair` b)  <- exp+      , hashOpenExp a > hashOpenExp b = b `Pair` a       --       | otherwise                               = exp 
− src/Data/Array/Accelerate/Analysis/Shape.hs
@@ -1,124 +0,0 @@-{-# LANGUAGE CPP                 #-}-{-# LANGUAGE GADTs               #-}-{-# LANGUAGE RankNTypes          #-}-{-# LANGUAGE ScopedTypeVariables #-}-{-# OPTIONS_HADDOCK hide #-}--- |--- Module      : Data.Array.Accelerate.Analysis.Shape--- 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)-----module Data.Array.Accelerate.Analysis.Shape (--  -- * query AST dimensionality-  AccDim, accDim, delayedDim, preAccDim,-  expDim,--) where--import Data.Array.Accelerate.AST-import Data.Array.Accelerate.Type-import Data.Array.Accelerate.Trafo.Base-import Data.Array.Accelerate.Array.Sugar---type AccDim acc  = forall aenv sh e. acc aenv (Array sh e) -> Int---- |Reify the dimensionality of the result type of an array computation----accDim :: AccDim OpenAcc-accDim (OpenAcc acc) = preAccDim accDim acc--delayedDim :: AccDim DelayedOpenAcc-delayedDim (Manifest acc)   = preAccDim delayedDim acc-delayedDim (Delayed sh _ _) = expDim sh----- |Reify dimensionality of a computation parameterised over a recursive closure----preAccDim :: forall acc aenv sh e. AccDim acc -> PreOpenAcc acc aenv (Array sh e) -> Int-preAccDim k pacc =-  case pacc of-    Alet  _ acc          -> k acc-    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-                              ArraysRarray -> ndim (eltType (undefined::sh))-#if __GLASGOW_HASKELL__ < 800-                              _            -> error "umm, hello"-#endif--    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-                              ArraysRarray -> ndim (eltType (undefined::sh))-#if __GLASGOW_HASKELL__ < 800-                              _            -> error "can we keep him?"-#endif--    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))-    Unit _               -> 0-    Generate _ _         -> ndim (eltType (undefined::sh))-    Transform _ _ _ _    -> ndim (eltType (undefined::sh))-    Reshape _ _          -> ndim (eltType (undefined::sh))-    Replicate _ _ _      -> ndim (eltType (undefined::sh))-    Slice _ _ _          -> ndim (eltType (undefined::sh))-    Map _ acc            -> k acc-    ZipWith _ _ acc      -> k acc-    Fold _ _ acc         -> k acc - 1-    Fold1 _ acc          -> k acc - 1-    FoldSeg _ _ acc _    -> k acc-    Fold1Seg _ acc _     -> k acc-    Scanl _ _ acc        -> k acc-    Scanl1 _ acc         -> k acc-    Scanr _ _ acc        -> k acc-    Scanr1 _ acc         -> k acc-    Permute _ acc _ _    -> k acc-    Backpermute _ _ _    -> ndim (eltType (undefined::sh))-    Stencil _ _ acc      -> k acc-    Stencil2 _ _ acc _ _ -> k acc----- |Reify dimensionality of a scalar expression yielding a shape----expDim :: forall acc env aenv sh. Elt sh => PreOpenExp acc env aenv sh -> Int-expDim _ = ndim (eltType (undefined :: sh))----- Count the number of components to a tuple type----ndim :: TupleType a -> Int-ndim TypeRunit       = 0-ndim TypeRscalar{}   = 1-ndim (TypeRpair a b) = ndim a + ndim b-
− src/Data/Array/Accelerate/Analysis/Stencil.hs
@@ -1,91 +0,0 @@-{-# LANGUAGE GADTs               #-}-{-# LANGUAGE ScopedTypeVariables #-}-{-# LANGUAGE TypeOperators       #-}-{-# OPTIONS_HADDOCK hide #-}--- |--- Module      : Data.Array.Accelerate.Analysis.Stencil--- Copyright   : [2010..2011] Ben Lever---               [2010..2017] 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.Stencil (offsets, offsets2) where--import Data.Array.Accelerate.AST-import Data.Array.Accelerate.Array.Sugar----- |Calculate the offset coordinates for each stencil element relative to the--- focal point. The coordinates are returned as a flattened list from the--- bottom-left element to the top-right. This ordering matches the Var indexing--- order.----offsets :: forall a b sh aenv stencil. Stencil sh a stencil-        => {- dummy -} Fun aenv (stencil -> b)-        -> {- dummy -} OpenAcc aenv (Array sh a)-        -> [sh]-offsets _ _ = positionsR (stencil :: StencilR sh a stencil)--offsets2 :: forall a b c sh aenv stencil1 stencil2. (Stencil sh a stencil1, Stencil sh b stencil2)-         => {- dummy -} Fun aenv (stencil1 -> stencil2 -> c)-         -> {- dummy -} OpenAcc aenv (Array sh a)-         -> {- dummy -} OpenAcc aenv (Array sh b)-         -> ([sh], [sh])-offsets2 _ _ _ =-  ( positionsR (stencil :: StencilR sh a stencil1)-  , positionsR (stencil :: StencilR sh b stencil2) )----- |Position calculation on reified stencil values.----positionsR :: StencilR sh e pat -> [sh]-positionsR StencilRunit3 = map (Z:.) [         -1, 0, 1          ]-positionsR StencilRunit5 = map (Z:.) [      -2,-1, 0, 1, 2       ]-positionsR StencilRunit7 = map (Z:.) [   -3,-2,-1, 0, 1, 2, 3    ]-positionsR StencilRunit9 = map (Z:.) [-4,-3,-2,-1, 0, 1, 2, 3, 4 ]--positionsR (StencilRtup3 c b a) = concat-  [ map (innermost (:. -1)) $ positionsR c-  , map (innermost (:.  0)) $ positionsR b-  , map (innermost (:.  1)) $ positionsR a ]--positionsR (StencilRtup5 e d c b a) = concat-  [ map (innermost (:. -2)) $ positionsR e-  , map (innermost (:. -1)) $ positionsR d-  , map (innermost (:.  0)) $ positionsR c-  , map (innermost (:.  1)) $ positionsR b-  , map (innermost (:.  2)) $ positionsR a ]--positionsR (StencilRtup7 g f e d c b a) = concat-  [ map (innermost (:. -3)) $ positionsR g-  , map (innermost (:. -2)) $ positionsR f-  , map (innermost (:. -1)) $ positionsR e-  , map (innermost (:.  0)) $ positionsR d-  , map (innermost (:.  1)) $ positionsR c-  , map (innermost (:.  2)) $ positionsR b-  , map (innermost (:.  3)) $ positionsR a ]--positionsR (StencilRtup9 i h g f e d c b a) = concat-  [ map (innermost (:. -4)) $ positionsR i-  , map (innermost (:. -3)) $ positionsR h-  , map (innermost (:. -2)) $ positionsR g-  , map (innermost (:. -1)) $ positionsR f-  , map (innermost (:.  0)) $ positionsR e-  , map (innermost (:.  1)) $ positionsR d-  , map (innermost (:.  2)) $ positionsR c-  , map (innermost (:.  3)) $ positionsR b-  , map (innermost (:.  4)) $ positionsR a ]----- Inject a dimension component inner-most----innermost :: Shape sh => (sh -> sh :. Int) -> sh -> sh :. Int-innermost f = invertShape . f . invertShape--invertShape :: Shape sh => sh -> sh-invertShape =  listToShape . reverse . shapeToList-
− src/Data/Array/Accelerate/Analysis/Type.hs
@@ -1,222 +0,0 @@-{-# LANGUAGE CPP                 #-}-{-# LANGUAGE GADTs               #-}-{-# LANGUAGE PatternGuards       #-}-{-# LANGUAGE RankNTypes          #-}-{-# LANGUAGE ScopedTypeVariables #-}-{-# LANGUAGE TypeFamilies        #-}-{-# OPTIONS_HADDOCK hide #-}--- |--- Module      : Data.Array.Accelerate.Analysis.Type--- 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)------ The Accelerate AST does not explicitly store much type information.  Most of--- it is only indirectly through type class constraints -especially, 'Elt'--- constraints- available. This module provides functions that reify that type--- information in the form of a 'TupleType value. This is, for example, needed--- to emit type information in a backend.-----module Data.Array.Accelerate.Analysis.Type (--  -- * Query AST types-  AccType, arrayType, sizeOf,-  accType, expType, delayedAccType, delayedExpType,-  preAccType, preExpType--) where---- friends-import Data.Array.Accelerate.AST-import Data.Array.Accelerate.Array.Sugar-import Data.Array.Accelerate.Trafo.Base-import Data.Array.Accelerate.Type---- standard library-import qualified Foreign.Storable as F----- |Determine an array type--- ---------------------------- |Reify the element type of an array.----arrayType :: forall sh e. Array sh e -> TupleType (EltRepr e)-arrayType (Array _ _) = eltType (undefined::e)----- |Determine the type of an expressions--- ---------------------------------------type AccType  acc = forall aenv sh e. acc aenv (Array sh e) -> TupleType (EltRepr e)---- |Reify the element type of the result of an array computation.----accType :: AccType OpenAcc-accType (OpenAcc acc) = preAccType accType acc--delayedAccType :: AccType DelayedOpenAcc-delayedAccType (Manifest acc) = preAccType delayedAccType acc-delayedAccType (Delayed _ f _)-  | Lam (Body e) <- f   = delayedExpType e-  | otherwise           = error "my favourite place in the world is wherever you happen to be"----- |Reify the element type of the result of an array computation using the array computation AST--- before tying the knot.----preAccType :: forall acc aenv sh e.-              AccType acc-           -> PreOpenAcc acc aenv (Array sh e)-           -> TupleType (EltRepr e)-preAccType k pacc =-  case pacc of-    Alet  _ acc         -> k acc--    -- The following all contain impossible pattern matches, but GHC's type-    -- checker does no grok that-    ---    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-                             ArraysRarray -> eltType (undefined::e)-#if __GLASGOW_HASKELL__ < 800-                             _            -> error "TRUE STORY."-#endif--    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-                             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-                             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-    Unit _              -> eltType (undefined::e)-    Generate _ _        -> eltType (undefined::e)-    Transform _ _ _ _   -> eltType (undefined::e)-    Reshape _ acc       -> k acc-    Replicate _ _ acc   -> k acc-    Slice _ acc _       -> k acc-    Map _ _             -> eltType (undefined::e)-    ZipWith _ _ _       -> eltType (undefined::e)-    Fold _ _ acc        -> k acc-    FoldSeg _ _ acc _   -> k acc-    Fold1 _ acc         -> k acc-    Fold1Seg _ acc _    -> k acc-    Scanl _ _ acc       -> k acc-    Scanl1 _ acc        -> k acc-    Scanr _ _ acc       -> k acc-    Scanr1 _ acc        -> k acc-    Permute _ _ _ acc   -> k acc-    Backpermute _ _ acc -> k acc-    Stencil _ _ _       -> eltType (undefined::e)-    Stencil2 _ _ _ _ _  -> eltType (undefined::e)----- |Reify the result type of a scalar expression.----expType :: OpenExp env aenv t -> TupleType (EltRepr t)-expType = preExpType accType--delayedExpType :: DelayedOpenExp env aenv t -> TupleType (EltRepr t)-delayedExpType = preExpType delayedAccType---- |Reify the result types of of a scalar expression using the expression AST before tying the--- knot.----preExpType :: forall acc aenv env t.-              AccType acc-           -> PreOpenExp acc aenv env t-           -> TupleType (EltRepr t)-preExpType k e =-  case e of-    Let _ _           -> eltType (undefined::t)-    Var _             -> eltType (undefined::t)-    Const _           -> eltType (undefined::t)-    Undef             -> eltType (undefined::t)-    Tuple _           -> eltType (undefined::t)-    Prj _ _           -> eltType (undefined::t)-    IndexNil          -> eltType (undefined::t)-    IndexCons _ _     -> eltType (undefined::t)-    IndexHead _       -> eltType (undefined::t)-    IndexTail _       -> eltType (undefined::t)-    IndexAny          -> eltType (undefined::t)-    IndexSlice _ _ _  -> eltType (undefined::t)-    IndexFull _ _ _   -> eltType (undefined::t)-    ToIndex _ _       -> eltType (undefined::t)-    FromIndex _ _     -> eltType (undefined::t)-    Cond _ t _        -> preExpType k t-    While _ _ _       -> eltType (undefined::t)-    PrimConst _       -> eltType (undefined::t)-    PrimApp _ _       -> eltType (undefined::t)-    Index acc _       -> k acc-    LinearIndex acc _ -> k acc-    Shape _           -> eltType (undefined::t)-    ShapeSize _       -> eltType (undefined::t)-    Intersect _ _     -> eltType (undefined::t)-    Union _ _         -> eltType (undefined::t)-    Foreign _ _ _     -> eltType (undefined::t)-    Coerce _          -> eltType (undefined::t)----- |Size of a tuple type, in bytes----sizeOf :: TupleType a -> Int-sizeOf TypeRunit       = 0-sizeOf (TypeRpair a b) = sizeOf a + sizeOf b-sizeOf (TypeRscalar t) = sizeOfScalarType t--sizeOfScalarType :: ScalarType t -> Int-sizeOfScalarType (SingleScalarType t) = sizeOfSingleType t-sizeOfScalarType (VectorScalarType t) = sizeOfVectorType t--sizeOfSingleType :: SingleType t -> Int-sizeOfSingleType (NumSingleType t)    = sizeOfNumType t-sizeOfSingleType (NonNumSingleType t) = sizeOfNonNumType t--sizeOfVectorType :: VectorType t -> Int-sizeOfVectorType (Vector2Type t)  = 2 * sizeOfSingleType t-sizeOfVectorType (Vector3Type t)  = 3 * sizeOfSingleType t-sizeOfVectorType (Vector4Type t)  = 4 * sizeOfSingleType t-sizeOfVectorType (Vector8Type t)  = 8 * sizeOfSingleType t-sizeOfVectorType (Vector16Type t) = 16 * sizeOfSingleType t--sizeOfNumType :: forall t. NumType t -> Int-sizeOfNumType (IntegralNumType t) | IntegralDict <- integralDict t = F.sizeOf (undefined::t)-sizeOfNumType (FloatingNumType t) | FloatingDict <- floatingDict t = F.sizeOf (undefined::t)--sizeOfNonNumType :: forall t. NonNumType t -> Int-sizeOfNonNumType TypeBool{} = 1 -- stored as Word8-sizeOfNonNumType t | NonNumDict <- nonNumDict t = F.sizeOf (undefined::t)-
src/Data/Array/Accelerate/Array/Data.hs view
@@ -1,1036 +1,393 @@-{-# LANGUAGE BangPatterns        #-}-{-# LANGUAGE DeriveDataTypeable  #-}-{-# LANGUAGE GADTs               #-}-{-# LANGUAGE MagicHash           #-}-{-# LANGUAGE ScopedTypeVariables #-}-{-# LANGUAGE StandaloneDeriving  #-}-{-# LANGUAGE TemplateHaskell     #-}-{-# LANGUAGE TypeFamilies        #-}-{-# LANGUAGE UnboxedTuples       #-}-{-# OPTIONS_HADDOCK hide #-}--- |--- Module      : Data.Array.Accelerate.Array.Data--- 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)------ This module fixes the concrete representation of Accelerate arrays.  We--- allocate all arrays using pinned memory to enable safe direct-access by--- non-Haskell code in multi-threaded code.  In particular, we can safely pass--- pointers to an array's payload to foreign code.-----module Data.Array.Accelerate.Array.Data (--  -- * Array operations and representations-  ArrayElt(..), ArrayData, MutableArrayData, runArrayData,-  ArrayEltR(..), GArrayData(..),--  -- * Array tuple operations-  fstArrayData, sndArrayData, pairArrayData,--  -- * 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.Monitoring-import Data.Array.Accelerate.Debug.Trace---- standard libraries-import Control.Applicative-import Control.Monad-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--import GHC.Base                                                     ( Int(..), IO(..), unsafeCoerce#, newAlignedPinnedByteArray#, byteArrayContents# )-import GHC.ForeignPtr                                               ( ForeignPtr(..), ForeignPtrContents(..) )----- Determine the underlying type of a Haskell CLong or CULong.----$( runQ [d| type HTYPE_INT = $(-              case finiteBitSize (undefined::Int) of-                32 -> [t| Int32 |]-                64 -> [t| Int64 |]-                _  -> error "I don't know what architecture I am" ) |] )--$( runQ [d| type HTYPE_WORD = $(-              case finiteBitSize (undefined::Word) of-                32 -> [t| Word32 |]-                64 -> [t| Word64 |]-                _  -> error "I don't know what architecture I am" ) |] )--$( runQ [d| type HTYPE_LONG = $(-              case finiteBitSize (undefined::CLong) of-                32 -> [t| Int32 |]-                64 -> [t| Int64 |]-                _  -> error "I don't know what architecture I am" ) |] )--$( runQ [d| type HTYPE_UNSIGNED_LONG = $(-              case finiteBitSize (undefined::CULong) of-                32 -> [t| Word32 |]-                64 -> [t| Word64 |]-                _  -> error "I don't know what architecture I am" ) |] )--$( runQ [d| type HTYPE_CCHAR = $(-              case isSigned (undefined::CChar) of-                True  -> [t| Int8  |]-                False -> [t| Word8 |] ) |] )----- Array representation--- ------------------------ |Immutable array representation----type ArrayData e = MutableArrayData e---- |Mutable array representation----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)----data family GArrayData :: (* -> *) -> * -> *-data instance GArrayData ba ()      = AD_Unit-data instance GArrayData ba Int     = AD_Int     (ba Int)-data instance GArrayData ba Int8    = AD_Int8    (ba Int8)-data instance GArrayData ba Int16   = AD_Int16   (ba Int16)-data instance GArrayData ba Int32   = AD_Int32   (ba Int32)-data instance GArrayData ba Int64   = AD_Int64   (ba Int64)-data instance GArrayData ba Word    = AD_Word    (ba Word)-data instance GArrayData ba Word8   = AD_Word8   (ba Word8)-data instance GArrayData ba Word16  = AD_Word16  (ba Word16)-data instance GArrayData ba Word32  = AD_Word32  (ba Word32)-data instance GArrayData ba Word64  = AD_Word64  (ba Word64)-data instance GArrayData ba CShort  = AD_CShort  (ba Int16)-data instance GArrayData ba CUShort = AD_CUShort (ba Word16)-data instance GArrayData ba CInt    = AD_CInt    (ba Int32)-data instance GArrayData ba CUInt   = AD_CUInt   (ba Word32)-data instance GArrayData ba CLong   = AD_CLong   (ba HTYPE_LONG)-data instance GArrayData ba CULong  = AD_CULong  (ba HTYPE_UNSIGNED_LONG)-data instance GArrayData ba CLLong  = AD_CLLong  (ba Int64)-data instance GArrayData ba CULLong = AD_CULLong (ba Word64)-data instance GArrayData ba Half    = AD_Half    (ba Half)-data instance GArrayData ba Float   = AD_Float   (ba Float)-data instance GArrayData ba Double  = AD_Double  (ba Double)-data instance GArrayData ba CFloat  = AD_CFloat  (ba Float)-data instance GArrayData ba CDouble = AD_CDouble (ba Double)-data instance GArrayData ba Bool    = AD_Bool    (ba Word8)-data instance GArrayData ba Char    = AD_Char    (ba Char)-data instance GArrayData ba CChar   = AD_CChar   (ba HTYPE_CCHAR)-data instance GArrayData ba CSChar  = AD_CSChar  (ba Int8)-data instance GArrayData ba CUChar  = AD_CUChar  (ba Word8)-data instance GArrayData ba (V2 a)  = AD_V2   (GArrayData ba a)-data instance GArrayData ba (V3 a)  = AD_V3   (GArrayData ba a)-data instance GArrayData ba (V4 a)  = AD_V4   (GArrayData ba a)-data instance GArrayData ba (V8 a)  = AD_V8   (GArrayData ba a)-data instance GArrayData ba (V16 a) = AD_V16  (GArrayData ba a)-data instance GArrayData ba (a, b)  = AD_Pair (GArrayData ba a)-                                              (GArrayData ba b)--deriving instance Typeable GArrayData----- | GADT to reify the 'ArrayElt' class.----data ArrayEltR a where-  ArrayEltRunit    :: ArrayEltR ()-  ArrayEltRint     :: ArrayEltR Int-  ArrayEltRint8    :: ArrayEltR Int8-  ArrayEltRint16   :: ArrayEltR Int16-  ArrayEltRint32   :: ArrayEltR Int32-  ArrayEltRint64   :: ArrayEltR Int64-  ArrayEltRword    :: ArrayEltR Word-  ArrayEltRword8   :: ArrayEltR Word8-  ArrayEltRword16  :: ArrayEltR Word16-  ArrayEltRword32  :: ArrayEltR Word32-  ArrayEltRword64  :: ArrayEltR Word64-  ArrayEltRcshort  :: ArrayEltR CShort-  ArrayEltRcushort :: ArrayEltR CUShort-  ArrayEltRcint    :: ArrayEltR CInt-  ArrayEltRcuint   :: ArrayEltR CUInt-  ArrayEltRclong   :: ArrayEltR CLong-  ArrayEltRculong  :: ArrayEltR CULong-  ArrayEltRcllong  :: ArrayEltR CLLong-  ArrayEltRcullong :: ArrayEltR CULLong-  ArrayEltRhalf    :: ArrayEltR Half-  ArrayEltRfloat   :: ArrayEltR Float-  ArrayEltRdouble  :: ArrayEltR Double-  ArrayEltRcfloat  :: ArrayEltR CFloat-  ArrayEltRcdouble :: ArrayEltR CDouble-  ArrayEltRbool    :: ArrayEltR Bool-  ArrayEltRchar    :: ArrayEltR Char-  ArrayEltRcchar   :: ArrayEltR CChar-  ArrayEltRcschar  :: ArrayEltR CSChar-  ArrayEltRcuchar  :: ArrayEltR CUChar-  ArrayEltRvec2    :: ArrayEltR a -> ArrayEltR (V2 a)-  ArrayEltRvec3    :: ArrayEltR a -> ArrayEltR (V3 a)-  ArrayEltRvec4    :: ArrayEltR a -> ArrayEltR (V4 a)-  ArrayEltRvec8    :: ArrayEltR a -> ArrayEltR (V8 a)-  ArrayEltRvec16   :: ArrayEltR a -> ArrayEltR (V16 a)-  ArrayEltRpair    :: (ArrayElt a, ArrayElt b)-                   => ArrayEltR a -> ArrayEltR b -> ArrayEltR (a,b)---- Array operations--- ---------------------- TLM: do we need to INLINE these functions to get good performance interfacing---      to external libraries, especially Repa?--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)-  ptrsOfMutableArrayData :: MutableArrayData e -> IO (ArrayPtrs e)-  ---  {-# INLINE unsafeFreezeArrayData  #-}-  {-# INLINE ptrsOfMutableArrayData #-}-  unsafeFreezeArrayData  = return-  ptrsOfMutableArrayData = return . ptrsOfArrayData--instance ArrayElt () where-  type ArrayPtrs () = ()-  arrayElt          = ArrayEltRunit-  {-# INLINE newArrayData         #-}-  {-# INLINE ptrsOfArrayData      #-}-  {-# INLINE touchArrayData       #-}-  {-# INLINE unsafeIndexArrayData #-}-  {-# INLINE unsafeReadArrayData  #-}-  {-# INLINE unsafeWriteArrayData #-}-  newArrayData !_                    = return AD_Unit-  ptrsOfArrayData      AD_Unit       = ()-  touchArrayData       AD_Unit       = return ()-  unsafeIndexArrayData AD_Unit !_    = ()-  unsafeReadArrayData  AD_Unit !_    = return ()-  unsafeWriteArrayData AD_Unit !_ () = return ()--instance ArrayElt Int where-  type ArrayPtrs Int = Ptr Int-  arrayElt           = ArrayEltRint-  {-# INLINE newArrayData         #-}-  {-# INLINE ptrsOfArrayData      #-}-  {-# INLINE touchArrayData       #-}-  {-# INLINE unsafeIndexArrayData #-}-  {-# INLINE unsafeReadArrayData  #-}-  {-# INLINE unsafeWriteArrayData #-}-  newArrayData size                    = AD_Int <$> newArrayData' size-  ptrsOfArrayData      (AD_Int ba)     = unsafeUniqueArrayPtr ba-  touchArrayData       (AD_Int ba)     = touchUniqueArray ba-  unsafeIndexArrayData (AD_Int ba) i   = unsafeIndexArray ba i-  unsafeReadArrayData  (AD_Int ba) i   = unsafeReadArray ba i-  unsafeWriteArrayData (AD_Int ba) i e = unsafeWriteArray ba i e--instance ArrayElt Int8 where-  type ArrayPtrs Int8 = Ptr Int8-  arrayElt            = ArrayEltRint8-  {-# INLINE newArrayData         #-}-  {-# INLINE ptrsOfArrayData      #-}-  {-# INLINE touchArrayData       #-}-  {-# INLINE unsafeIndexArrayData #-}-  {-# INLINE unsafeReadArrayData  #-}-  {-# INLINE unsafeWriteArrayData #-}-  newArrayData size                     = AD_Int8 <$> newArrayData' size-  ptrsOfArrayData      (AD_Int8 ba)     = unsafeUniqueArrayPtr ba-  touchArrayData       (AD_Int8 ba)     = touchUniqueArray ba-  unsafeIndexArrayData (AD_Int8 ba) i   = unsafeIndexArray ba i-  unsafeReadArrayData  (AD_Int8 ba) i   = unsafeReadArray ba i-  unsafeWriteArrayData (AD_Int8 ba) i e = unsafeWriteArray ba i e--instance ArrayElt Int16 where-  type ArrayPtrs Int16 = Ptr Int16-  arrayElt             = ArrayEltRint16-  {-# INLINE newArrayData         #-}-  {-# INLINE ptrsOfArrayData      #-}-  {-# INLINE touchArrayData       #-}-  {-# INLINE unsafeIndexArrayData #-}-  {-# INLINE unsafeReadArrayData  #-}-  {-# INLINE unsafeWriteArrayData #-}-  newArrayData size                      = AD_Int16 <$> newArrayData' size-  ptrsOfArrayData      (AD_Int16 ba)     = unsafeUniqueArrayPtr ba-  touchArrayData       (AD_Int16 ba)     = touchUniqueArray ba-  unsafeIndexArrayData (AD_Int16 ba) i   = unsafeIndexArray ba i-  unsafeReadArrayData  (AD_Int16 ba) i   = unsafeReadArray ba i-  unsafeWriteArrayData (AD_Int16 ba) i e = unsafeWriteArray ba i e--instance ArrayElt Int32 where-  type ArrayPtrs Int32 = Ptr Int32-  arrayElt             = ArrayEltRint32-  {-# INLINE newArrayData         #-}-  {-# INLINE ptrsOfArrayData      #-}-  {-# INLINE touchArrayData       #-}-  {-# INLINE unsafeIndexArrayData #-}-  {-# INLINE unsafeReadArrayData  #-}-  {-# INLINE unsafeWriteArrayData #-}-  newArrayData size                      = AD_Int32 <$> newArrayData' size-  ptrsOfArrayData      (AD_Int32 ba)     = unsafeUniqueArrayPtr ba-  touchArrayData       (AD_Int32 ba)     = touchUniqueArray ba-  unsafeIndexArrayData (AD_Int32 ba) i   = unsafeIndexArray ba i-  unsafeReadArrayData  (AD_Int32 ba) i   = unsafeReadArray ba i-  unsafeWriteArrayData (AD_Int32 ba) i e = unsafeWriteArray ba i e--instance ArrayElt Int64 where-  type ArrayPtrs Int64 = Ptr Int64-  arrayElt             = ArrayEltRint64-  {-# INLINE newArrayData         #-}-  {-# INLINE ptrsOfArrayData      #-}-  {-# INLINE touchArrayData       #-}-  {-# INLINE unsafeIndexArrayData #-}-  {-# INLINE unsafeReadArrayData  #-}-  {-# INLINE unsafeWriteArrayData #-}-  newArrayData size                      = AD_Int64 <$> newArrayData' size-  ptrsOfArrayData      (AD_Int64 ba)     = unsafeUniqueArrayPtr ba-  touchArrayData       (AD_Int64 ba)     = touchUniqueArray ba-  unsafeIndexArrayData (AD_Int64 ba) i   = unsafeIndexArray ba i-  unsafeReadArrayData  (AD_Int64 ba) i   = unsafeReadArray ba i-  unsafeWriteArrayData (AD_Int64 ba) i e = unsafeWriteArray ba i e--instance ArrayElt Word where-  type ArrayPtrs Word = Ptr Word-  arrayElt            = ArrayEltRword-  {-# INLINE newArrayData         #-}-  {-# INLINE ptrsOfArrayData      #-}-  {-# INLINE touchArrayData       #-}-  {-# INLINE unsafeIndexArrayData #-}-  {-# INLINE unsafeReadArrayData  #-}-  {-# INLINE unsafeWriteArrayData #-}-  newArrayData size                     = AD_Word <$> newArrayData' size-  ptrsOfArrayData      (AD_Word ba)     = unsafeUniqueArrayPtr ba-  touchArrayData       (AD_Word ba)     = touchUniqueArray ba-  unsafeIndexArrayData (AD_Word ba) i   = unsafeIndexArray ba i-  unsafeReadArrayData  (AD_Word ba) i   = unsafeReadArray ba i-  unsafeWriteArrayData (AD_Word ba) i e = unsafeWriteArray ba i e--instance ArrayElt Word8 where-  type ArrayPtrs Word8 = Ptr Word8-  arrayElt             = ArrayEltRword8-  {-# INLINE newArrayData         #-}-  {-# INLINE ptrsOfArrayData      #-}-  {-# INLINE touchArrayData       #-}-  {-# INLINE unsafeIndexArrayData #-}-  {-# INLINE unsafeReadArrayData  #-}-  {-# INLINE unsafeWriteArrayData #-}-  newArrayData size                      = AD_Word8 <$> newArrayData' size-  ptrsOfArrayData      (AD_Word8 ba)     = unsafeUniqueArrayPtr ba-  touchArrayData       (AD_Word8 ba)     = touchUniqueArray ba-  unsafeIndexArrayData (AD_Word8 ba) i   = unsafeIndexArray ba i-  unsafeReadArrayData  (AD_Word8 ba) i   = unsafeReadArray ba i-  unsafeWriteArrayData (AD_Word8 ba) i e = unsafeWriteArray ba i e--instance ArrayElt Word16 where-  type ArrayPtrs Word16 = Ptr Word16-  arrayElt              = ArrayEltRword16-  {-# INLINE newArrayData         #-}-  {-# INLINE ptrsOfArrayData      #-}-  {-# INLINE touchArrayData       #-}-  {-# INLINE unsafeIndexArrayData #-}-  {-# INLINE unsafeReadArrayData  #-}-  {-# INLINE unsafeWriteArrayData #-}-  newArrayData size                       = AD_Word16 <$> newArrayData' size-  unsafeIndexArrayData (AD_Word16 ba) i   = unsafeIndexArray ba i-  ptrsOfArrayData      (AD_Word16 ba)     = unsafeUniqueArrayPtr ba-  touchArrayData       (AD_Word16 ba)     = touchUniqueArray ba-  unsafeReadArrayData  (AD_Word16 ba) i   = unsafeReadArray ba i-  unsafeWriteArrayData (AD_Word16 ba) i e = unsafeWriteArray ba i e--instance ArrayElt Word32 where-  type ArrayPtrs Word32 = Ptr Word32-  arrayElt              = ArrayEltRword32-  {-# INLINE newArrayData         #-}-  {-# INLINE ptrsOfArrayData      #-}-  {-# INLINE touchArrayData       #-}-  {-# INLINE unsafeIndexArrayData #-}-  {-# INLINE unsafeReadArrayData  #-}-  {-# INLINE unsafeWriteArrayData #-}-  newArrayData size                       = AD_Word32 <$> newArrayData' size-  ptrsOfArrayData      (AD_Word32 ba)     = unsafeUniqueArrayPtr ba-  touchArrayData       (AD_Word32 ba)     = touchUniqueArray ba-  unsafeIndexArrayData (AD_Word32 ba) i   = unsafeIndexArray ba i-  unsafeReadArrayData  (AD_Word32 ba) i   = unsafeReadArray ba i-  unsafeWriteArrayData (AD_Word32 ba) i e = unsafeWriteArray ba i e--instance ArrayElt Word64 where-  type ArrayPtrs Word64 = Ptr Word64-  arrayElt              = ArrayEltRword64-  {-# INLINE newArrayData         #-}-  {-# INLINE ptrsOfArrayData      #-}-  {-# INLINE touchArrayData       #-}-  {-# INLINE unsafeIndexArrayData #-}-  {-# INLINE unsafeReadArrayData  #-}-  {-# INLINE unsafeWriteArrayData #-}-  newArrayData size                       = AD_Word64 <$> newArrayData' size-  ptrsOfArrayData      (AD_Word64 ba)     = unsafeUniqueArrayPtr ba-  touchArrayData       (AD_Word64 ba)     = touchUniqueArray ba-  unsafeIndexArrayData (AD_Word64 ba) i   = unsafeIndexArray ba i-  unsafeReadArrayData  (AD_Word64 ba) i   = unsafeReadArray ba i-  unsafeWriteArrayData (AD_Word64 ba) i e = unsafeWriteArray ba i e--instance ArrayElt CShort where-  type ArrayPtrs CShort = Ptr Int16-  arrayElt              = ArrayEltRcshort-  {-# INLINE newArrayData         #-}-  {-# INLINE ptrsOfArrayData      #-}-  {-# INLINE touchArrayData       #-}-  {-# INLINE unsafeIndexArrayData #-}-  {-# INLINE unsafeReadArrayData  #-}-  {-# INLINE unsafeWriteArrayData #-}-  newArrayData size                                = AD_CShort <$> newArrayData' size-  ptrsOfArrayData      (AD_CShort ba)              = unsafeUniqueArrayPtr ba-  touchArrayData       (AD_CShort ba)              = touchUniqueArray ba-  unsafeIndexArrayData (AD_CShort ba) i            = CShort  $! unsafeIndexArray ba i-  unsafeReadArrayData  (AD_CShort ba) i            = CShort <$> unsafeReadArray ba i-  unsafeWriteArrayData (AD_CShort ba) i (CShort e) = unsafeWriteArray ba i e--instance ArrayElt CUShort where-  type ArrayPtrs CUShort = Ptr Word16-  arrayElt               = ArrayEltRcushort-  {-# INLINE newArrayData         #-}-  {-# INLINE ptrsOfArrayData      #-}-  {-# INLINE touchArrayData       #-}-  {-# INLINE unsafeIndexArrayData #-}-  {-# INLINE unsafeReadArrayData  #-}-  {-# INLINE unsafeWriteArrayData #-}-  newArrayData size                                  = AD_CUShort <$> newArrayData' size-  ptrsOfArrayData      (AD_CUShort ba)               = unsafeUniqueArrayPtr ba-  touchArrayData       (AD_CUShort ba)               = touchUniqueArray ba-  unsafeIndexArrayData (AD_CUShort ba) i             = CUShort  $! unsafeIndexArray ba i-  unsafeReadArrayData  (AD_CUShort ba) i             = CUShort <$> unsafeReadArray ba i-  unsafeWriteArrayData (AD_CUShort ba) i (CUShort e) = unsafeWriteArray ba i e--instance ArrayElt CInt where-  type ArrayPtrs CInt = Ptr Int32-  arrayElt            = ArrayEltRcint-  {-# INLINE newArrayData         #-}-  {-# INLINE ptrsOfArrayData      #-}-  {-# INLINE touchArrayData       #-}-  {-# INLINE unsafeIndexArrayData #-}-  {-# INLINE unsafeReadArrayData  #-}-  {-# INLINE unsafeWriteArrayData #-}-  newArrayData size                            = AD_CInt <$> newArrayData' size-  ptrsOfArrayData      (AD_CInt ba)            = unsafeUniqueArrayPtr ba-  touchArrayData       (AD_CInt ba)            = touchUniqueArray ba-  unsafeIndexArrayData (AD_CInt ba) i          = CInt  $! unsafeIndexArray ba i-  unsafeReadArrayData  (AD_CInt ba) i          = CInt <$> unsafeReadArray ba i-  unsafeWriteArrayData (AD_CInt ba) i (CInt e) = unsafeWriteArray ba i e--instance ArrayElt CUInt where-  type ArrayPtrs CUInt = Ptr Word32-  arrayElt             = ArrayEltRcuint-  {-# INLINE newArrayData         #-}-  {-# INLINE ptrsOfArrayData      #-}-  {-# INLINE touchArrayData       #-}-  {-# INLINE unsafeIndexArrayData #-}-  {-# INLINE unsafeReadArrayData  #-}-  {-# INLINE unsafeWriteArrayData #-}-  newArrayData size                              = AD_CUInt <$> newArrayData' size-  ptrsOfArrayData      (AD_CUInt ba)             = unsafeUniqueArrayPtr ba-  touchArrayData       (AD_CUInt ba)             = touchUniqueArray ba-  unsafeIndexArrayData (AD_CUInt ba) i           = CUInt  $! unsafeIndexArray ba i-  unsafeReadArrayData  (AD_CUInt ba) i           = CUInt <$> unsafeReadArray ba i-  unsafeWriteArrayData (AD_CUInt ba) i (CUInt e) = unsafeWriteArray ba i e--instance ArrayElt CLong where-  type ArrayPtrs CLong = Ptr HTYPE_LONG-  arrayElt             = ArrayEltRclong-  {-# INLINE newArrayData         #-}-  {-# INLINE ptrsOfArrayData      #-}-  {-# INLINE touchArrayData       #-}-  {-# INLINE unsafeIndexArrayData #-}-  {-# INLINE unsafeReadArrayData  #-}-  {-# INLINE unsafeWriteArrayData #-}-  newArrayData size                              = AD_CLong <$> newArrayData' size-  ptrsOfArrayData      (AD_CLong ba)             = unsafeUniqueArrayPtr ba-  touchArrayData       (AD_CLong ba)             = touchUniqueArray ba-  unsafeIndexArrayData (AD_CLong ba) i           = CLong  $! unsafeIndexArray ba i-  unsafeReadArrayData  (AD_CLong ba) i           = CLong <$> unsafeReadArray ba i-  unsafeWriteArrayData (AD_CLong ba) i (CLong e) = unsafeWriteArray ba i e--instance ArrayElt CULong where-  type ArrayPtrs CULong = Ptr HTYPE_UNSIGNED_LONG-  arrayElt              = ArrayEltRculong-  {-# INLINE newArrayData         #-}-  {-# INLINE ptrsOfArrayData      #-}-  {-# INLINE touchArrayData       #-}-  {-# INLINE unsafeIndexArrayData #-}-  {-# INLINE unsafeReadArrayData  #-}-  {-# INLINE unsafeWriteArrayData #-}-  newArrayData size                                = AD_CULong <$> newArrayData' size-  ptrsOfArrayData      (AD_CULong ba)              = unsafeUniqueArrayPtr ba-  touchArrayData       (AD_CULong ba)              = touchUniqueArray ba-  unsafeIndexArrayData (AD_CULong ba) i            = CULong  $! unsafeIndexArray ba i-  unsafeReadArrayData  (AD_CULong ba) i            = CULong <$> unsafeReadArray ba i-  unsafeWriteArrayData (AD_CULong ba) i (CULong e) = unsafeWriteArray ba i e--instance ArrayElt CLLong where-  type ArrayPtrs CLLong = Ptr Int64-  arrayElt              = ArrayEltRcllong-  {-# INLINE unsafeIndexArrayData #-}-  {-# INLINE ptrsOfArrayData #-}-  {-# INLINE touchArrayData #-}-  {-# INLINE newArrayData #-}-  {-# INLINE unsafeReadArrayData #-}-  {-# INLINE unsafeWriteArrayData #-}-  newArrayData size                                = AD_CLLong <$> newArrayData' size-  ptrsOfArrayData      (AD_CLLong ba)              = unsafeUniqueArrayPtr ba-  touchArrayData       (AD_CLLong ba)              = touchUniqueArray ba-  unsafeIndexArrayData (AD_CLLong ba) i            = CLLong  $! unsafeIndexArray ba i-  unsafeReadArrayData  (AD_CLLong ba) i            = CLLong <$> unsafeReadArray ba i-  unsafeWriteArrayData (AD_CLLong ba) i (CLLong e) = unsafeWriteArray ba i e--instance ArrayElt CULLong where-  type ArrayPtrs CULLong = Ptr Word64-  arrayElt               = ArrayEltRcullong-  {-# INLINE newArrayData         #-}-  {-# INLINE ptrsOfArrayData      #-}-  {-# INLINE touchArrayData       #-}-  {-# INLINE unsafeIndexArrayData #-}-  {-# INLINE unsafeReadArrayData  #-}-  {-# INLINE unsafeWriteArrayData #-}-  newArrayData size                                  = AD_CULLong <$> newArrayData' size-  ptrsOfArrayData      (AD_CULLong ba)               = unsafeUniqueArrayPtr ba-  touchArrayData       (AD_CULLong ba)               = touchUniqueArray ba-  unsafeIndexArrayData (AD_CULLong ba) i             = CULLong  $! unsafeIndexArray ba i-  unsafeReadArrayData  (AD_CULLong ba) i             = CULLong <$> unsafeReadArray ba i-  unsafeWriteArrayData (AD_CULLong ba) i (CULLong e) = unsafeWriteArray ba i e--instance ArrayElt Half where-  type ArrayPtrs Half = Ptr Half-  arrayElt            = ArrayEltRhalf-  {-# INLINE newArrayData         #-}-  {-# INLINE ptrsOfArrayData      #-}-  {-# INLINE touchArrayData       #-}-  {-# INLINE unsafeIndexArrayData #-}-  {-# INLINE unsafeReadArrayData  #-}-  {-# INLINE unsafeWriteArrayData #-}-  newArrayData size                     = AD_Half <$> newArrayData' size-  ptrsOfArrayData      (AD_Half ba)     = unsafeUniqueArrayPtr ba-  touchArrayData       (AD_Half ba)     = touchUniqueArray ba-  unsafeIndexArrayData (AD_Half ba) i   = unsafeIndexArray ba i-  unsafeReadArrayData  (AD_Half ba) i   = unsafeReadArray ba i-  unsafeWriteArrayData (AD_Half ba) i e = unsafeWriteArray ba i e--instance ArrayElt Float where-  type ArrayPtrs Float = Ptr Float-  arrayElt             = ArrayEltRfloat-  {-# INLINE newArrayData         #-}-  {-# INLINE ptrsOfArrayData      #-}-  {-# INLINE touchArrayData       #-}-  {-# INLINE unsafeIndexArrayData #-}-  {-# INLINE unsafeReadArrayData  #-}-  {-# INLINE unsafeWriteArrayData #-}-  newArrayData size                      = AD_Float <$> newArrayData' size-  ptrsOfArrayData      (AD_Float ba)     = unsafeUniqueArrayPtr ba-  touchArrayData       (AD_Float ba)     = touchUniqueArray ba-  unsafeIndexArrayData (AD_Float ba) i   = unsafeIndexArray ba i-  unsafeReadArrayData  (AD_Float ba) i   = unsafeReadArray ba i-  unsafeWriteArrayData (AD_Float ba) i e = unsafeWriteArray ba i e--instance ArrayElt Double where-  type ArrayPtrs Double = Ptr Double-  arrayElt              = ArrayEltRdouble-  {-# INLINE unsafeIndexArrayData #-}-  {-# INLINE ptrsOfArrayData #-}-  {-# INLINE touchArrayData #-}-  {-# INLINE newArrayData #-}-  {-# INLINE unsafeReadArrayData #-}-  {-# INLINE unsafeWriteArrayData #-}-  newArrayData size                       = AD_Double <$> newArrayData' size-  ptrsOfArrayData      (AD_Double ba)     = unsafeUniqueArrayPtr ba-  touchArrayData       (AD_Double ba)     = touchUniqueArray ba-  unsafeIndexArrayData (AD_Double ba) i   = unsafeIndexArray ba i-  unsafeReadArrayData  (AD_Double ba) i   = unsafeReadArray ba i-  unsafeWriteArrayData (AD_Double ba) i e = unsafeWriteArray ba i e--instance ArrayElt CFloat where-  type ArrayPtrs CFloat = Ptr Float-  arrayElt              = ArrayEltRcfloat-  {-# INLINE newArrayData         #-}-  {-# INLINE ptrsOfArrayData      #-}-  {-# INLINE touchArrayData       #-}-  {-# INLINE unsafeIndexArrayData #-}-  {-# INLINE unsafeReadArrayData  #-}-  {-# INLINE unsafeWriteArrayData #-}-  newArrayData size                                = AD_CFloat <$> newArrayData' size-  ptrsOfArrayData      (AD_CFloat ba)              = unsafeUniqueArrayPtr ba-  touchArrayData       (AD_CFloat ba)              = touchUniqueArray ba-  unsafeIndexArrayData (AD_CFloat ba) i            = CFloat  $! unsafeIndexArray ba i-  unsafeReadArrayData  (AD_CFloat ba) i            = CFloat <$> unsafeReadArray ba i-  unsafeWriteArrayData (AD_CFloat ba) i (CFloat e) = unsafeWriteArray ba i e--instance ArrayElt CDouble where-  type ArrayPtrs CDouble = Ptr Double-  arrayElt               = ArrayEltRcdouble-  {-# INLINE newArrayData         #-}-  {-# INLINE ptrsOfArrayData      #-}-  {-# INLINE touchArrayData       #-}-  {-# INLINE unsafeIndexArrayData #-}-  {-# INLINE unsafeReadArrayData  #-}-  {-# INLINE unsafeWriteArrayData #-}-  newArrayData size                                  = AD_CDouble <$> newArrayData' size-  ptrsOfArrayData      (AD_CDouble ba)               = unsafeUniqueArrayPtr ba-  touchArrayData       (AD_CDouble ba)               = touchUniqueArray ba-  unsafeIndexArrayData (AD_CDouble ba) i             = CDouble  $! unsafeIndexArray ba i-  unsafeReadArrayData  (AD_CDouble ba) i             = CDouble <$> unsafeReadArray ba i-  unsafeWriteArrayData (AD_CDouble ba) i (CDouble e) = unsafeWriteArray ba i e---- Bool arrays are stored as arrays of bytes. While this is memory inefficient,--- it is better suited to parallel backends than a packed bit-vector--- representation.----instance ArrayElt Bool where-  type ArrayPtrs Bool = Ptr Word8-  arrayElt            = ArrayEltRbool-  {-# INLINE newArrayData         #-}-  {-# INLINE ptrsOfArrayData      #-}-  {-# INLINE touchArrayData       #-}-  {-# INLINE unsafeIndexArrayData #-}-  {-# INLINE unsafeReadArrayData  #-}-  {-# INLINE unsafeWriteArrayData #-}-  newArrayData size                     = AD_Bool <$> newArrayData' size-  ptrsOfArrayData      (AD_Bool ba)     = unsafeUniqueArrayPtr ba-  touchArrayData       (AD_Bool ba)     = touchUniqueArray ba-  unsafeIndexArrayData (AD_Bool ba) i   = toBool  $! unsafeIndexArray ba i-  unsafeReadArrayData  (AD_Bool ba) i   = toBool <$> unsafeReadArray ba i-  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-  arrayElt            = ArrayEltRchar-  {-# INLINE newArrayData         #-}-  {-# INLINE ptrsOfArrayData      #-}-  {-# INLINE touchArrayData       #-}-  {-# INLINE unsafeIndexArrayData #-}-  {-# INLINE unsafeReadArrayData  #-}-  {-# INLINE unsafeWriteArrayData #-}-  newArrayData size                     = AD_Char <$> newArrayData' size-  ptrsOfArrayData      (AD_Char ba)     = unsafeUniqueArrayPtr ba-  touchArrayData       (AD_Char ba)     = touchUniqueArray ba-  unsafeIndexArrayData (AD_Char ba) i   = unsafeIndexArray ba i-  unsafeReadArrayData  (AD_Char ba) i   = unsafeReadArray ba i-  unsafeWriteArrayData (AD_Char ba) i e = unsafeWriteArray ba i e--instance ArrayElt CChar where-  type ArrayPtrs CChar = Ptr HTYPE_CCHAR-  arrayElt             = ArrayEltRcchar-  {-# INLINE newArrayData         #-}-  {-# INLINE ptrsOfArrayData      #-}-  {-# INLINE touchArrayData       #-}-  {-# INLINE unsafeIndexArrayData #-}-  {-# INLINE unsafeReadArrayData  #-}-  {-# INLINE unsafeWriteArrayData #-}-  newArrayData size                              = AD_CChar <$> newArrayData' size-  ptrsOfArrayData      (AD_CChar ba)             = unsafeUniqueArrayPtr ba-  touchArrayData       (AD_CChar ba)             = touchUniqueArray ba-  unsafeIndexArrayData (AD_CChar ba) i           = CChar  $! unsafeIndexArray ba i-  unsafeReadArrayData  (AD_CChar ba) i           = CChar <$> unsafeReadArray ba i-  unsafeWriteArrayData (AD_CChar ba) i (CChar e) = unsafeWriteArray ba i e--instance ArrayElt CSChar where-  type ArrayPtrs CSChar = Ptr Int8-  arrayElt              = ArrayEltRcschar-  {-# INLINE newArrayData         #-}-  {-# INLINE ptrsOfArrayData      #-}-  {-# INLINE touchArrayData       #-}-  {-# INLINE unsafeIndexArrayData #-}-  {-# INLINE unsafeReadArrayData  #-}-  {-# INLINE unsafeWriteArrayData #-}-  newArrayData size                                = AD_CSChar <$> newArrayData' size-  ptrsOfArrayData      (AD_CSChar ba)              = unsafeUniqueArrayPtr ba-  touchArrayData       (AD_CSChar ba)              = touchUniqueArray ba-  unsafeIndexArrayData (AD_CSChar ba) i            = CSChar  $! unsafeIndexArray ba i-  unsafeReadArrayData  (AD_CSChar ba) i            = CSChar <$> unsafeReadArray ba i-  unsafeWriteArrayData (AD_CSChar ba) i (CSChar e) = unsafeWriteArray ba i e--instance ArrayElt CUChar where-  type ArrayPtrs CUChar = Ptr Word8-  arrayElt              = ArrayEltRcuchar-  {-# INLINE newArrayData         #-}-  {-# INLINE ptrsOfArrayData      #-}-  {-# INLINE touchArrayData       #-}-  {-# INLINE unsafeIndexArrayData #-}-  {-# INLINE unsafeReadArrayData  #-}-  {-# INLINE unsafeWriteArrayData #-}-  newArrayData size                                = AD_CUChar <$> newArrayData' size-  ptrsOfArrayData      (AD_CUChar ba)              = unsafeUniqueArrayPtr ba-  touchArrayData       (AD_CUChar ba)              = touchUniqueArray ba-  unsafeIndexArrayData (AD_CUChar ba) i            = CUChar  $! unsafeIndexArray ba i-  unsafeReadArrayData  (AD_CUChar ba) i            = CUChar <$> unsafeReadArray ba i-  unsafeWriteArrayData (AD_CUChar ba) i (CUChar e) = unsafeWriteArray ba i e--instance ArrayElt a => ArrayElt (V2 a) where-  type ArrayPtrs (V2 a) = ArrayPtrs a-  arrayElt              = ArrayEltRvec2 arrayElt-  {-# INLINE newArrayData         #-}-  {-# INLINE ptrsOfArrayData      #-}-  {-# INLINE touchArrayData       #-}-  {-# INLINE unsafeIndexArrayData #-}-  {-# INLINE unsafeReadArrayData  #-}-  {-# INLINE unsafeWriteArrayData #-}-  ptrsOfArrayData (AD_V2 ba) = ptrsOfArrayData ba-  touchArrayData  (AD_V2 ba) = touchArrayData ba-  newArrayData size          = AD_V2 <$> newArrayData (2 * size)--  unsafeIndexArrayData (AD_V2 ba) ix =-    let ix' = 2*ix-    in  V2 (unsafeIndexArrayData ba ix')-           (unsafeIndexArrayData ba (ix'+1))--  unsafeReadArrayData (AD_V2 ba) ix =-    let ix' = 2*ix-    in  V2 <$> unsafeReadArrayData ba ix'-           <*> unsafeReadArrayData ba (ix'+1)--  unsafeWriteArrayData (AD_V2 ba) ix (V2 a b) =-    let ix' = 2*ix-    in do unsafeWriteArrayData ba ix'     a-          unsafeWriteArrayData ba (ix'+1) b--instance ArrayElt a => ArrayElt (V3 a) where-  type ArrayPtrs (V3 a) = ArrayPtrs a-  arrayElt              = ArrayEltRvec3 arrayElt-  {-# INLINE newArrayData         #-}-  {-# INLINE ptrsOfArrayData      #-}-  {-# INLINE touchArrayData       #-}-  {-# INLINE unsafeIndexArrayData #-}-  {-# INLINE unsafeReadArrayData  #-}-  {-# INLINE unsafeWriteArrayData #-}-  ptrsOfArrayData (AD_V3 ba) = ptrsOfArrayData ba-  touchArrayData  (AD_V3 ba) = touchArrayData ba-  newArrayData size          = AD_V3 <$> newArrayData (3 * size)--  unsafeIndexArrayData (AD_V3 ba) ix =-    let ix' = 3*ix-    in  V3 (unsafeIndexArrayData ba ix')-           (unsafeIndexArrayData ba (ix'+1))-           (unsafeIndexArrayData ba (ix'+2))--  unsafeReadArrayData (AD_V3 ba) ix =-    let ix' = 3*ix-    in  V3 <$> unsafeReadArrayData ba ix'-           <*> unsafeReadArrayData ba (ix'+1)-           <*> unsafeReadArrayData ba (ix'+2)--  unsafeWriteArrayData (AD_V3 ba) ix (V3 a b c) =-    let ix' = 3*ix-    in do unsafeWriteArrayData ba ix'     a-          unsafeWriteArrayData ba (ix'+1) b-          unsafeWriteArrayData ba (ix'+3) c--instance ArrayElt a => ArrayElt (V4 a) where-  type ArrayPtrs (V4 a) = ArrayPtrs a-  arrayElt              = ArrayEltRvec4 arrayElt-  {-# INLINE newArrayData         #-}-  {-# INLINE ptrsOfArrayData      #-}-  {-# INLINE touchArrayData       #-}-  {-# INLINE unsafeIndexArrayData #-}-  {-# INLINE unsafeReadArrayData  #-}-  {-# INLINE unsafeWriteArrayData #-}-  ptrsOfArrayData (AD_V4 ba) = ptrsOfArrayData ba-  touchArrayData  (AD_V4 ba) = touchArrayData ba-  newArrayData size          = AD_V4 <$> newArrayData (4 * size)--  unsafeIndexArrayData (AD_V4 ba) ix =-    let ix' = 4*ix-    in  V4 (unsafeIndexArrayData ba ix')-           (unsafeIndexArrayData ba (ix'+1))-           (unsafeIndexArrayData ba (ix'+2))-           (unsafeIndexArrayData ba (ix'+3))--  unsafeReadArrayData (AD_V4 ba) ix =-    let ix' = 4*ix-    in  V4 <$> unsafeReadArrayData ba ix'-           <*> unsafeReadArrayData ba (ix'+1)-           <*> unsafeReadArrayData ba (ix'+2)-           <*> unsafeReadArrayData ba (ix'+3)--  unsafeWriteArrayData (AD_V4 ba) ix (V4 a b c d) =-    let ix' = 4*ix-    in do unsafeWriteArrayData ba ix'     a-          unsafeWriteArrayData ba (ix'+1) b-          unsafeWriteArrayData ba (ix'+2) c-          unsafeWriteArrayData ba (ix'+3) d--instance ArrayElt a => ArrayElt (V8 a) where-  type ArrayPtrs (V8 a) = ArrayPtrs a-  arrayElt              = ArrayEltRvec8 arrayElt-  {-# INLINE newArrayData         #-}-  {-# INLINE ptrsOfArrayData      #-}-  {-# INLINE touchArrayData       #-}-  {-# INLINE unsafeIndexArrayData #-}-  {-# INLINE unsafeReadArrayData  #-}-  {-# INLINE unsafeWriteArrayData #-}-  ptrsOfArrayData (AD_V8 ba) = ptrsOfArrayData ba-  touchArrayData  (AD_V8 ba) = touchArrayData ba-  newArrayData size          = AD_V8 <$> newArrayData (8 * size)--  unsafeIndexArrayData (AD_V8 ba) ix =-    let ix' = 8*ix-    in  V8 (unsafeIndexArrayData ba ix')-           (unsafeIndexArrayData ba (ix'+1))-           (unsafeIndexArrayData ba (ix'+2))-           (unsafeIndexArrayData ba (ix'+3))-           (unsafeIndexArrayData ba (ix'+4))-           (unsafeIndexArrayData ba (ix'+5))-           (unsafeIndexArrayData ba (ix'+6))-           (unsafeIndexArrayData ba (ix'+7))--  unsafeReadArrayData (AD_V8 ba) ix =-    let ix' = 8*ix-    in  V8 <$> unsafeReadArrayData ba ix'-           <*> unsafeReadArrayData ba (ix'+1)-           <*> unsafeReadArrayData ba (ix'+2)-           <*> unsafeReadArrayData ba (ix'+3)-           <*> unsafeReadArrayData ba (ix'+4)-           <*> unsafeReadArrayData ba (ix'+5)-           <*> unsafeReadArrayData ba (ix'+6)-           <*> unsafeReadArrayData ba (ix'+7)--  unsafeWriteArrayData (AD_V8 ba) ix (V8 a b c d e f g h) =-    let ix' = 8*ix-    in do unsafeWriteArrayData ba ix'     a-          unsafeWriteArrayData ba (ix'+1) b-          unsafeWriteArrayData ba (ix'+2) c-          unsafeWriteArrayData ba (ix'+3) d-          unsafeWriteArrayData ba (ix'+4) e-          unsafeWriteArrayData ba (ix'+5) f-          unsafeWriteArrayData ba (ix'+6) g-          unsafeWriteArrayData ba (ix'+7) h--instance ArrayElt a => ArrayElt (V16 a) where-  type ArrayPtrs (V16 a) = ArrayPtrs a-  arrayElt               = ArrayEltRvec16 arrayElt-  {-# INLINE newArrayData         #-}-  {-# INLINE ptrsOfArrayData      #-}-  {-# INLINE touchArrayData       #-}-  {-# INLINE unsafeIndexArrayData #-}-  {-# INLINE unsafeReadArrayData  #-}-  {-# INLINE unsafeWriteArrayData #-}-  ptrsOfArrayData (AD_V16 ba) = ptrsOfArrayData ba-  touchArrayData  (AD_V16 ba) = touchArrayData ba-  newArrayData size           = AD_V16 <$> newArrayData (16 * size)--  unsafeIndexArrayData (AD_V16 ba) ix =-    let ix' = 16*ix-    in  V16 (unsafeIndexArrayData ba ix')-            (unsafeIndexArrayData ba (ix'+1))-            (unsafeIndexArrayData ba (ix'+2))-            (unsafeIndexArrayData ba (ix'+3))-            (unsafeIndexArrayData ba (ix'+4))-            (unsafeIndexArrayData ba (ix'+5))-            (unsafeIndexArrayData ba (ix'+6))-            (unsafeIndexArrayData ba (ix'+7))-            (unsafeIndexArrayData ba (ix'+8))-            (unsafeIndexArrayData ba (ix'+9))-            (unsafeIndexArrayData ba (ix'+10))-            (unsafeIndexArrayData ba (ix'+11))-            (unsafeIndexArrayData ba (ix'+12))-            (unsafeIndexArrayData ba (ix'+13))-            (unsafeIndexArrayData ba (ix'+14))-            (unsafeIndexArrayData ba (ix'+15))--  unsafeReadArrayData (AD_V16 ba) ix =-    let ix' = 16*ix-    in  V16 <$> unsafeReadArrayData ba ix'-            <*> unsafeReadArrayData ba (ix'+1)-            <*> unsafeReadArrayData ba (ix'+2)-            <*> unsafeReadArrayData ba (ix'+3)-            <*> unsafeReadArrayData ba (ix'+4)-            <*> unsafeReadArrayData ba (ix'+5)-            <*> unsafeReadArrayData ba (ix'+6)-            <*> unsafeReadArrayData ba (ix'+7)-            <*> unsafeReadArrayData ba (ix'+8)-            <*> unsafeReadArrayData ba (ix'+9)-            <*> unsafeReadArrayData ba (ix'+10)-            <*> unsafeReadArrayData ba (ix'+11)-            <*> unsafeReadArrayData ba (ix'+12)-            <*> unsafeReadArrayData ba (ix'+13)-            <*> unsafeReadArrayData ba (ix'+14)-            <*> unsafeReadArrayData ba (ix'+15)--  unsafeWriteArrayData (AD_V16 ba) ix (V16 a b c d e f g h i j k l m n o p) =-    let ix' = 16*ix-    in do unsafeWriteArrayData ba ix'     a-          unsafeWriteArrayData ba (ix'+1) b-          unsafeWriteArrayData ba (ix'+2) c-          unsafeWriteArrayData ba (ix'+3) d-          unsafeWriteArrayData ba (ix'+4) e-          unsafeWriteArrayData ba (ix'+5) f-          unsafeWriteArrayData ba (ix'+6) g-          unsafeWriteArrayData ba (ix'+7) h-          unsafeWriteArrayData ba (ix'+8) i-          unsafeWriteArrayData ba (ix'+9) j-          unsafeWriteArrayData ba (ix'+10) k-          unsafeWriteArrayData ba (ix'+11) l-          unsafeWriteArrayData ba (ix'+12) m-          unsafeWriteArrayData ba (ix'+13) n-          unsafeWriteArrayData ba (ix'+14) o-          unsafeWriteArrayData ba (ix'+15) p--instance (ArrayElt a, ArrayElt b) => ArrayElt (a, b) where-  type ArrayPtrs (a, b) = (ArrayPtrs a, ArrayPtrs b)-  arrayElt              = ArrayEltRpair arrayElt arrayElt-  {-# INLINE newArrayData           #-}-  {-# INLINE ptrsOfArrayData        #-}-  {-# INLINE ptrsOfMutableArrayData #-}-  {-# INLINE touchArrayData         #-}-  {-# INLINE unsafeFreezeArrayData  #-}-  {-# INLINE unsafeIndexArrayData   #-}-  {-# INLINE unsafeReadArrayData    #-}-  {-# INLINE unsafeWriteArrayData   #-}-  newArrayData size                             = AD_Pair <$> newArrayData size <*> newArrayData size-  touchArrayData         (AD_Pair a b)          = touchArrayData a >> touchArrayData b-  ptrsOfArrayData        (AD_Pair a b)          = (ptrsOfArrayData a, ptrsOfArrayData b)-  ptrsOfMutableArrayData (AD_Pair a b)          = (,) <$> ptrsOfMutableArrayData a <*> ptrsOfMutableArrayData b-  unsafeReadArrayData    (AD_Pair a b) i        = (,) <$> unsafeReadArrayData a i <*> unsafeReadArrayData b i-  unsafeIndexArrayData   (AD_Pair a b) i        = (unsafeIndexArrayData a i, unsafeIndexArrayData b i)-  unsafeWriteArrayData   (AD_Pair a b) i (x, y) = unsafeWriteArrayData a i x >> unsafeWriteArrayData b i y-  unsafeFreezeArrayData  (AD_Pair a b)          = AD_Pair <$> unsafeFreezeArrayData a <*> unsafeFreezeArrayData b----- 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--- ---------------------{-# 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.----{-# 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 :: Storable e => UniqueArray e -> Int -> e-unsafeIndexArray ua i =-  unsafePerformIO $! unsafeReadArray ua i---- Read an element from a mutable array at the given index. This does no bounds--- checking.----{-# INLINE unsafeReadArray #-}-unsafeReadArray :: Storable e => UniqueArray e -> Int -> IO e-unsafeReadArray ua i =-  withUniqueArrayPtr ua $ \ptr -> peekElemOff ptr i---- Write an element into a mutable array at the given index. This does no bounds--- checking.----{-# INLINE unsafeWriteArray #-}-unsafeWriteArray :: Storable e => UniqueArray e -> Int -> e -> IO ()-unsafeWriteArray ua i e =-  withUniqueArrayPtr ua $ \ptr -> pokeElemOff ptr i e---- Allocate a new array with enough storage to hold the given number of--- elements.------ 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)-      didAllocateBytesLocal (fromIntegral bytes)-      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----{-# INLINE mallocPlainForeignPtrBytesAligned #-}-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#) #)+{-# LANGUAGE BangPatterns         #-}+{-# LANGUAGE GADTs                #-}+{-# LANGUAGE MagicHash            #-}+{-# LANGUAGE ScopedTypeVariables  #-}+{-# LANGUAGE TemplateHaskell      #-}+{-# LANGUAGE TypeFamilies         #-}+{-# LANGUAGE UnboxedTuples        #-}+{-# LANGUAGE UndecidableInstances #-}+{-# OPTIONS_HADDOCK hide #-}+-- |+-- Module      : Data.Array.Accelerate.Array.Data+-- Copyright   : [2008..2020] The Accelerate Team+-- License     : BSD3+--+-- Maintainer  : Trevor L. McDonell <trevor.mcdonell@gmail.com>+-- Stability   : experimental+-- Portability : non-portable (GHC extensions)+--+-- This module fixes the concrete representation of Accelerate arrays.  We+-- allocate all arrays using pinned memory to enable safe direct-access by+-- non-Haskell code in multi-threaded code.  In particular, we can safely pass+-- pointers to an array's payload to foreign code.+--++module Data.Array.Accelerate.Array.Data (++  -- * Array operations and representations+  ArrayData, MutableArrayData, ScalarArrayData, GArrayDataR, ScalarArrayDataR,+  runArrayData,+  newArrayData,+  indexArrayData, readArrayData, writeArrayData,+  unsafeArrayDataPtr,+  touchArrayData,+  rnfArrayData,++  -- * Type macros+  HTYPE_INT, HTYPE_WORD, HTYPE_CLONG, HTYPE_CULONG, HTYPE_CCHAR,++  -- * Allocator internals+  registerForeignPtrAllocator,++  -- * Utilities for type classes+  ScalarArrayDict(..), scalarArrayDict,+  SingleArrayDict(..), singleArrayDict,++  -- * TemplateHaskell+  liftArrayData,++) where++-- friends+import Data.Array.Accelerate.Array.Unique+import Data.Array.Accelerate.Representation.Type+import Data.Array.Accelerate.Error+import Data.Array.Accelerate.Type+import Data.Primitive.Vec++import Data.Array.Accelerate.Debug.Flags+import Data.Array.Accelerate.Debug.Monitoring+import Data.Array.Accelerate.Debug.Trace+++-- standard libraries+import Control.Applicative+import Control.DeepSeq+import Control.Monad                                                ( (<=<) )+import Data.Bits+import Data.IORef+import Data.Primitive                                               ( sizeOf# )+import Foreign.ForeignPtr+import Foreign.Storable+import Language.Haskell.TH                                          hiding ( Type )+import System.IO.Unsafe+import Text.Printf+import Prelude                                                      hiding ( mapM )++import GHC.Base+import GHC.ForeignPtr+import GHC.Ptr+++-- | Immutable array representation+--+type ArrayData e = MutableArrayData e++-- | Mutable array representation+--+type MutableArrayData e = GArrayDataR UniqueArray e++-- | Underlying array representation.+--+-- NOTE: We use a standard (non-strict) pair to enable lazy device-host data transfers+--+type family GArrayDataR ba a where+  GArrayDataR ba ()     = ()+  GArrayDataR ba (a, b) = (GArrayDataR ba a, GArrayDataR ba b)+  GArrayDataR ba a      = ba (ScalarArrayDataR a)++type ScalarArrayData a = UniqueArray (ScalarArrayDataR a)++-- | Mapping from scalar type to the type as represented in memory in an+-- array.+--+type family ScalarArrayDataR t where+  ScalarArrayDataR Int       = Int+  ScalarArrayDataR Int8      = Int8+  ScalarArrayDataR Int16     = Int16+  ScalarArrayDataR Int32     = Int32+  ScalarArrayDataR Int64     = Int64+  ScalarArrayDataR Word      = Word+  ScalarArrayDataR Word8     = Word8+  ScalarArrayDataR Word16    = Word16+  ScalarArrayDataR Word32    = Word32+  ScalarArrayDataR Word64    = Word64+  ScalarArrayDataR Half      = Half+  ScalarArrayDataR Float     = Float+  ScalarArrayDataR Double    = Double+  ScalarArrayDataR (Vec n t) = ScalarArrayDataR t+++data ScalarArrayDict a where+  ScalarArrayDict :: ( ArrayData a ~ ScalarArrayData a, ScalarArrayDataR a ~ ScalarArrayDataR b )+                  => {-# UNPACK #-} !Int    -- vector width+                  -> SingleType b           -- base type+                  -> ScalarArrayDict a++data SingleArrayDict a where+  SingleArrayDict :: ( ArrayData a ~ ScalarArrayData a, ScalarArrayDataR a ~ a )+                  => SingleArrayDict a++scalarArrayDict :: ScalarType a -> ScalarArrayDict a+scalarArrayDict = scalar+  where+    scalar :: ScalarType a -> ScalarArrayDict a+    scalar (VectorScalarType t) = vector t+    scalar (SingleScalarType t)+      | SingleArrayDict <- singleArrayDict t+      = ScalarArrayDict 1 t++    vector :: VectorType a -> ScalarArrayDict a+    vector (VectorType w s)+      | SingleArrayDict <- singleArrayDict s+      = ScalarArrayDict w s++singleArrayDict :: SingleType a -> SingleArrayDict a+singleArrayDict = single+  where+    single :: SingleType a -> SingleArrayDict a+    single (NumSingleType t) = num t++    num :: NumType a -> SingleArrayDict a+    num (IntegralNumType t) = integral t+    num (FloatingNumType t) = floating t++    integral :: IntegralType a -> SingleArrayDict a+    integral TypeInt    = SingleArrayDict+    integral TypeInt8   = SingleArrayDict+    integral TypeInt16  = SingleArrayDict+    integral TypeInt32  = SingleArrayDict+    integral TypeInt64  = SingleArrayDict+    integral TypeWord   = SingleArrayDict+    integral TypeWord8  = SingleArrayDict+    integral TypeWord16 = SingleArrayDict+    integral TypeWord32 = SingleArrayDict+    integral TypeWord64 = SingleArrayDict++    floating :: FloatingType a -> SingleArrayDict a+    floating TypeHalf   = SingleArrayDict+    floating TypeFloat  = SingleArrayDict+    floating TypeDouble = SingleArrayDict+++-- Array operations+-- ----------------++newArrayData :: HasCallStack => TupR ScalarType e -> Int -> IO (MutableArrayData e)+newArrayData TupRunit         !_    = return ()+newArrayData (TupRpair t1 t2) !size = (,) <$> newArrayData t1 size <*> newArrayData t2 size+newArrayData (TupRsingle t)   !size+  | SingleScalarType s <- t+  , SingleDict         <- singleDict s+  , SingleArrayDict    <- singleArrayDict s+  = allocateArray size+  --+  | VectorScalarType v <- t+  , VectorType w s     <- v+  , SingleDict         <- singleDict s+  , SingleArrayDict    <- singleArrayDict s+  = allocateArray (w * size)++indexArrayData :: TupR ScalarType e -> ArrayData e -> Int -> e+indexArrayData tR arr ix = unsafePerformIO $ readArrayData tR arr ix++readArrayData :: forall e. TupR ScalarType e -> MutableArrayData e -> Int -> IO e+readArrayData TupRunit         ()       !_  = return ()+readArrayData (TupRpair t1 t2) (a1, a2) !ix = (,) <$> readArrayData t1 a1 ix <*> readArrayData t2 a2 ix+readArrayData (TupRsingle t)   arr      !ix+  | SingleScalarType s <- t+  , SingleDict         <- singleDict s+  , SingleArrayDict    <- singleArrayDict s+  = unsafeReadArray arr ix+  --+  | VectorScalarType v <- t+  , VectorType w s     <- v+  , I# w#              <- w+  , I# ix#             <- ix+  , SingleDict         <- singleDict s+  , SingleArrayDict    <- singleArrayDict s+  = let+        !bytes# = w# *# sizeOf# (undefined :: ScalarArrayDataR e)+        !addr#  = unPtr# (unsafeUniqueArrayPtr arr) `plusAddr#` (ix# *# bytes#)+     in+     IO $ \s0 ->+       case newAlignedPinnedByteArray# bytes# 16# s0     of { (# s1, mba# #) ->+       case copyAddrToByteArray# addr# mba# 0# bytes# s1 of { s2             ->+       case unsafeFreezeByteArray# mba# s2               of { (# s3, ba# #)  ->+         (# s3, Vec ba# #)+       }}}++writeArrayData :: forall e. TupR ScalarType e -> MutableArrayData e -> Int -> e -> IO ()+writeArrayData TupRunit         ()       !_  ()       = return ()+writeArrayData (TupRpair t1 t2) (a1, a2) !ix (v1, v2) = writeArrayData t1 a1 ix v1 >> writeArrayData t2 a2 ix v2+writeArrayData (TupRsingle t)   arr      !ix !val+  | SingleScalarType s <- t+  , SingleDict         <- singleDict s+  , SingleArrayDict    <- singleArrayDict s+  = unsafeWriteArray arr ix val+  --+  | VectorScalarType v <- t+  , VectorType w s     <- v+  , Vec ba#            <- val+  , I# w#              <- w+  , I# ix#             <- ix+  , SingleDict         <- singleDict s+  , SingleArrayDict    <- singleArrayDict s+  = let+       !bytes# = w# *# sizeOf# (undefined :: ScalarArrayDataR e)+       !addr#  = unPtr# (unsafeUniqueArrayPtr arr) `plusAddr#` (ix# *# bytes#)+     in+     IO $ \s0 -> case copyByteArrayToAddr# ba# 0# addr# bytes# s0 of+                   s1 -> (# s1, () #)+++unsafeArrayDataPtr :: ScalarType e -> ArrayData e -> Ptr (ScalarArrayDataR e)+unsafeArrayDataPtr t arr+  | ScalarArrayDict{} <- scalarArrayDict t+  = unsafeUniqueArrayPtr arr++touchArrayData :: TupR ScalarType e -> ArrayData e -> IO ()+touchArrayData TupRunit         ()       = return ()+touchArrayData (TupRpair t1 t2) (a1, a2) = touchArrayData t1 a1 >> touchArrayData t2 a2+touchArrayData (TupRsingle t)   arr+  | ScalarArrayDict{} <- scalarArrayDict t+  = touchUniqueArray arr++rnfArrayData :: TupR ScalarType e -> ArrayData e -> ()+rnfArrayData TupRunit         ()       = ()+rnfArrayData (TupRpair t1 t2) (a1, a2) = rnfArrayData t1 a1 `seq` rnfArrayData t2 a2 `seq` ()+rnfArrayData (TupRsingle t)   arr      = rnf (unsafeArrayDataPtr t arr)++unPtr# :: Ptr a -> Addr#+unPtr# (Ptr addr#) = addr#++-- | Safe combination of creating and fast freezing of array data.+--+runArrayData+    :: IO (MutableArrayData e, e)+    -> (ArrayData e, e)+runArrayData st = unsafePerformIO $ do+  (mad, r) <- st+  return (mad, r)++-- Allocate a new array with enough storage to hold the given number of+-- elements.+--+-- 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.+--+allocateArray :: forall e. (HasCallStack, Storable e) => Int -> IO (UniqueArray e)+allocateArray !size+  = internalCheck "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)+      didAllocateBytesLocal (fromIntegral bytes)+      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 64# s of+    (# s', mbarr# #) -> (# s', ForeignPtr (byteArrayContents# (unsafeCoerce# mbarr#)) (PlainPtr mbarr#) #)+++liftArrayData :: Int -> TypeR e -> ArrayData e -> Q (TExp (ArrayData e))+liftArrayData n = tuple+  where+    tuple :: TypeR e -> ArrayData e -> Q (TExp (ArrayData e))+    tuple TupRunit         ()       = [|| () ||]+    tuple (TupRpair t1 t2) (a1, a2) = [|| ($$(tuple t1 a1), $$(tuple t2 a2)) ||]+    tuple (TupRsingle s) adata      = scalar s adata++    scalar :: ScalarType e -> ArrayData e -> Q (TExp (ArrayData e))+    scalar (SingleScalarType t) = single t+    scalar (VectorScalarType t) = vector t++    vector :: forall n e. VectorType (Vec n e) -> ArrayData (Vec n e) -> Q (TExp (ArrayData (Vec n e)))+    vector (VectorType w t)+      | SingleArrayDict <- singleArrayDict t+      = liftArrayData (w * n) (TupRsingle (SingleScalarType t))++    single :: SingleType e -> ArrayData e -> Q (TExp (ArrayData e))+    single (NumSingleType t) = num t++    num :: NumType e -> ArrayData e -> Q (TExp (ArrayData e))+    num (IntegralNumType t) = integral t+    num (FloatingNumType t) = floating t++    integral :: IntegralType e -> ArrayData e -> Q (TExp (ArrayData e))+    integral TypeInt    = liftUniqueArray n+    integral TypeInt8   = liftUniqueArray n+    integral TypeInt16  = liftUniqueArray n+    integral TypeInt32  = liftUniqueArray n+    integral TypeInt64  = liftUniqueArray n+    integral TypeWord   = liftUniqueArray n+    integral TypeWord8  = liftUniqueArray n+    integral TypeWord16 = liftUniqueArray n+    integral TypeWord32 = liftUniqueArray n+    integral TypeWord64 = liftUniqueArray n++    floating :: FloatingType e -> ArrayData e -> Q (TExp (ArrayData e))+    floating TypeHalf   = liftUniqueArray n+    floating TypeFloat  = liftUniqueArray n+    floating TypeDouble = liftUniqueArray n++-- Determine the underlying type of a Haskell CLong or CULong.+--+runQ [d| type HTYPE_INT = $(+              case finiteBitSize (undefined::Int) of+                32 -> [t| Int32 |]+                64 -> [t| Int64 |]+                _  -> error "I don't know what architecture I am" ) |]++runQ [d| type HTYPE_WORD = $(+              case finiteBitSize (undefined::Word) of+                32 -> [t| Word32 |]+                64 -> [t| Word64 |]+                _  -> error "I don't know what architecture I am" ) |]++runQ [d| type HTYPE_CLONG = $(+              case finiteBitSize (undefined::CLong) of+                32 -> [t| Int32 |]+                64 -> [t| Int64 |]+                _  -> error "I don't know what architecture I am" ) |]++runQ [d| type HTYPE_CULONG = $(+              case finiteBitSize (undefined::CULong) of+                32 -> [t| Word32 |]+                64 -> [t| Word64 |]+                _  -> error "I don't know what architecture I am" ) |]++runQ [d| type HTYPE_CCHAR = $(+              if isSigned (undefined::CChar)+                then [t| Int8  |]+                else [t| Word8 |] ) |] 
− src/Data/Array/Accelerate/Array/Lifted.hs
@@ -1,283 +0,0 @@-{-# 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--}-
src/Data/Array/Accelerate/Array/Remote.hs view
@@ -1,18 +1,17 @@ {-# 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+-- Copyright   : [2015..2020] The Accelerate Team -- License     : BSD3 ----- Maintainer  : Robert Clifton-Everest <robertce@cse.unsw.edu.au>+-- Maintainer  : Trevor L. McDonell <trevor.mcdonell@gmail.com> -- 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.+-- 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 (
src/Data/Array/Accelerate/Array/Remote/Class.hs view
@@ -1,13 +1,13 @@-{-# LANGUAGE ConstraintKinds #-}-{-# LANGUAGE TypeFamilies    #-}+{-# LANGUAGE AllowAmbiguousTypes #-}+{-# 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+-- Copyright   : [2015..2020] The Accelerate Team -- License     : BSD3 ----- Maintainer  : Robert Clifton-Everest <robertce@cse.unsw.edu.au>+-- Maintainer  : Trevor L. McDonell <trevor.mcdonell@gmail.com> -- Stability   : experimental -- Portability : non-portable (GHC extensions) --@@ -27,26 +27,19 @@  module Data.Array.Accelerate.Array.Remote.Class ( -  RemoteMemory(..), PrimElt+  RemoteMemory(..)  ) where  import Data.Array.Accelerate.Array.Data+import Data.Array.Accelerate.Type  import Control.Applicative import Control.Monad.Catch-import Data.Int-import Data.Word-import Data.Typeable-import Foreign.Ptr-import Foreign.Storable+import Data.Kind 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.@@ -54,20 +47,20 @@ class (Applicative m, Monad m, MonadCatch m, MonadMask m) => RemoteMemory m where    -- | Pointers into this particular remote memory.-  type RemotePtr m :: * -> *+  type RemotePtr m :: Type -> Type    -- | 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 ()+  pokeRemote :: SingleType e -> Int -> RemotePtr m (ScalarArrayDataR e) -> 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 ()+  peekRemote :: SingleType e -> Int -> RemotePtr m (ScalarArrayDataR e) -> MutableArrayData e -> m ()    -- | Cast a remote pointer.-  castRemotePtr :: proxy m -> RemotePtr m a -> RemotePtr m b+  castRemotePtr :: RemotePtr m a -> RemotePtr m b    -- | Returns the total remote memory available in bytes.   totalRemoteMem :: m Int64
src/Data/Array/Accelerate/Array/Remote/LRU.hs view
@@ -1,3 +1,5 @@+{-# LANGUAGE AllowAmbiguousTypes #-}+{-# LANGUAGE CPP                 #-} {-# LANGUAGE BangPatterns        #-} {-# LANGUAGE ConstraintKinds     #-} {-# LANGUAGE DoAndIfThenElse     #-}@@ -6,15 +8,14 @@ {-# LANGUAGE PatternGuards       #-} {-# LANGUAGE RankNTypes          #-} {-# LANGUAGE ScopedTypeVariables #-}-{-# LANGUAGE TemplateHaskell     #-}+{-# LANGUAGE TypeApplications    #-} {-# 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+-- Module      : Data.Array.Accelerate.Array.Remote.LRU+-- Copyright   : [2015..2020] The Accelerate Team -- License     : BSD3 ----- Maintainer  : Robert Clifton-Everest <robertce@cse.unsw.edu.au>+-- Maintainer  : Trevor L. McDonell <trevor.mcdonell@gmail.com> -- Stability   : experimental -- Portability : non-portable (GHC extensions) --@@ -35,26 +36,33 @@  ) where +import Data.Array.Accelerate.Analysis.Match                     ( matchSingleType, (:~:)(..) )+import Data.Array.Accelerate.Array.Data+import Data.Array.Accelerate.Array.Remote.Class+import Data.Array.Accelerate.Array.Remote.Table                 ( StableArray, makeWeakArrayData )+import Data.Array.Accelerate.Array.Unique                       ( touchUniqueArray )+import Data.Array.Accelerate.Error                              ( internalError )+import Data.Array.Accelerate.Representation.Elt+import Data.Array.Accelerate.Representation.Type+import Data.Array.Accelerate.Type+import qualified Data.Array.Accelerate.Array.Remote.Table       as Basic+import qualified Data.Array.Accelerate.Debug                    as D+ import Control.Concurrent.MVar                                  ( MVar, newMVar, withMVar, takeMVar, putMVar, mkWeakMVar ) import Control.Monad                                            ( filterM ) import Control.Monad.Catch import Control.Monad.IO.Class                                   ( MonadIO, liftIO ) import Data.Functor+#if __GLASGOW_HASKELL__ < 808 import Data.Int                                                 ( Int64 )+#endif import Data.Maybe                                               ( isNothing )-import Data.Proxy-import Foreign.Storable                                         ( sizeOf ) import System.CPUTime import System.Mem.Weak                                          ( Weak, deRefWeak, finalize ) import Prelude                                                  hiding ( lookup ) import qualified Data.HashTable.IO                              as HT -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 Data.Array.Accelerate.Error                              ( internalError )-import qualified Data.Array.Accelerate.Array.Remote.Table       as Basic-import qualified Data.Array.Accelerate.Debug                    as D+import GHC.Stack   -- We build cached memory tables on top of a basic memory table.@@ -80,16 +88,17 @@ type Timestamp = Integer  data Used task where-  Used :: PrimElt e a+  Used :: ArrayData e ~ ScalarArrayData e        => !Timestamp        -> !Status        -> {-# UNPACK #-} !Int                   -- Use count        -> ![task]                               -- Asynchronous tasks using the array-       -> {-# UNPACK #-} !Int                   -- Array size-       -> {-# UNPACK #-} !(Weak (ArrayData e))+       -> {-# UNPACK #-} !Int                   -- Number of elements+       -> !(SingleType e)+       -> {-# UNPACK #-} !(Weak (ScalarArrayData e))        -> Used task --- |A Task represents a process executing asynchronously that can be polled for+-- | 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. --@@ -100,7 +109,7 @@ instance Task () where   completed () = return True --- |Create a new memory cache from host to remote arrays.+-- | 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@@ -115,7 +124,7 @@   weak_utbl <- mkWeakMVar ref (cache_finalizer utbl)   return    $! MemoryTable mt ref weak_utbl --- |Perform some action that requires the remote pointer corresponding to+-- | 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.@@ -129,13 +138,14 @@ -- more accesses of the remote pointer. -- withRemote-    :: forall task m a b c. (PrimElt a b, Task task, RemoteMemory m, MonadIO m, Functor m)+    :: forall task m a c. (HasCallStack, Task task, RemoteMemory m, MonadIO m, Functor m)     => MemoryTable (RemotePtr m) task+    -> SingleType a     -> ArrayData a-    -> (RemotePtr m b -> m (task, c))+    -> (RemotePtr m (ScalarArrayDataR a) -> m (task, c))     -> m (Maybe c)-withRemote (MemoryTable !mt !ref _) !arr run = do-  key <- Basic.makeStableArray arr+withRemote (MemoryTable !mt !ref _) !tp !arr run | SingleArrayDict <- singleArrayDict tp = do+  key <- Basic.makeStableArray tp arr   mp  <- withMVar' ref $ \utbl -> do     mu  <- liftIO . HT.mutate utbl key $ \case       Nothing -> (Nothing,           Nothing)@@ -147,13 +157,13 @@         return Nothing -- The array was never in the table        Just u  -> do-        mp  <- liftIO $ Basic.lookup mt arr+        mp  <- liftIO $ Basic.lookup @m mt tp arr         ptr <- case mp of-                 Just p          -> return p-                 Nothing-                   | isEvicted u -> copyBack utbl (incCount u)-                   | otherwise   -> do message ("lost array " ++ show key)-                                       $internalError "withRemote" "non-evicted array has been lost"+                Just p          -> return p+                Nothing+                  | isEvicted u -> copyBack utbl (incCount u)+                  | otherwise   -> do message ("lost array " ++ show key)+                                      internalError "non-evicted array has been lost"         return (Just ptr)   --   case mp of@@ -161,34 +171,39 @@     Just ptr -> Just <$> go key ptr   where     updateTask :: Used task -> task -> IO (Used task)-    updateTask (Used _ status count tasks n weak_arr) task = do+    updateTask (Used _ status count tasks n tp' weak_arr) task = do       ts      <- getCPUTime       tasks'  <- cleanUses tasks-      return (Used ts status (count - 1) (task : tasks') n weak_arr)+      return (Used ts status (count - 1) (task : tasks') n tp' weak_arr) -    copyBack :: UT task -> Used task -> m (RemotePtr m b)-    copyBack 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+    copyBack :: HasCallStack => UT task -> Used task -> m (RemotePtr m (ScalarArrayDataR a))+    copyBack utbl (Used ts _ count tasks n tp' weak_arr)+      | Just Refl <- matchSingleType tp tp' = do+        message "withRemote/reuploading-evicted-array"+        p <- mallocWithUsage mt utbl tp arr (Used ts Clean count tasks n tp weak_arr)+        pokeRemote tp n p arr+        return p+      | otherwise = internalError "Type mismatch"      -- We can't combine the use of `withMVar ref` above with the one here     -- because the `permute` operation from the PTX backend requires nested     -- calls to `withRemote` in order to copy the defaults array.     ---    go :: StableArray -> RemotePtr m b -> m c+    go :: (HasCallStack, ArrayData a ~ ScalarArrayData a)+       => StableArray+       -> RemotePtr m (ScalarArrayDataR a)+       -> m c     go key ptr = do       message ("withRemote/using: " ++ show key)       (task, c) <- run ptr       liftIO . withMVar ref  $ \utbl -> do         HT.mutateIO utbl key $ \case-          Nothing -> $internalError "withRemote" "invariant violated"+          Nothing -> internalError "invariant violated"           Just u  -> do             u' <- updateTask u task             return (Just u', ())         ---        touchArrayData arr+        touchUniqueArray arr       return c  @@ -207,15 +222,16 @@ -- 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)+malloc :: forall e m task. (HasCallStack, RemoteMemory m, MonadIO m, Task task)        => MemoryTable (RemotePtr m) task+       -> SingleType e        -> ArrayData e-       -> Bool                                -- ^ True if host array is frozen.-       -> Int-       -> m Bool                              -- ^ Was the array allocated successfully?-malloc (MemoryTable mt ref weak_utbl) !ad !frozen !n = do+       -> Bool            -- ^ True if host array is frozen.+       -> Int             -- ^ Number of elements+       -> m Bool          -- ^ Was the array allocated successfully?+malloc (MemoryTable mt ref weak_utbl) !tp !ad !frozen !n | SingleArrayDict <- singleArrayDict tp = do -- Required for ArrayData e ~ ScalarArrayData e   ts  <- liftIO $ getCPUTime-  key <- Basic.makeStableArray ad+  key <- Basic.makeStableArray tp ad   --   let status = if frozen                  then Clean@@ -225,41 +241,44 @@     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)+        weak_arr <- liftIO $ makeWeakArrayData tp ad ad (Just $ finalizer key weak_utbl)+        _        <- mallocWithUsage mt utbl tp ad (Used ts status 0 [] n tp weak_arr)         return True       else         return False  mallocWithUsage-    :: forall a e m task. (PrimElt e a, RemoteMemory m, MonadIO m, Task task)+    :: forall e m task. (HasCallStack, RemoteMemory m, MonadIO m, Task task, ArrayData e ~ ScalarArrayData e)     => Basic.MemoryTable (RemotePtr m)     -> UT task+    -> SingleType e     -> ArrayData e     -> Used task-    -> m (RemotePtr m a)-mallocWithUsage !mt !utbl !ad !usage@(Used _ _ _ _ n _) = malloc'+    -> m (RemotePtr m (ScalarArrayDataR e))+mallocWithUsage !mt !utbl !tp !ad !usage@(Used _ _ _ _ n _ _) = malloc'   where+    malloc' :: HasCallStack => m (RemotePtr m (ScalarArrayDataR e))     malloc' = do-      mp <- Basic.malloc mt ad n :: m (Maybe (RemotePtr m a))+      mp <- Basic.malloc @e @m mt tp ad n :: m (Maybe (RemotePtr m (ScalarArrayDataR e)))       case mp of         Nothing -> do           success <- evictLRU utbl mt           if success then malloc'-                     else $internalError "malloc" "Remote memory exhausted"+                     else internalError "Remote memory exhausted"         Just p -> liftIO $ do-          key <- Basic.makeStableArray ad+          key <- Basic.makeStableArray tp 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+    :: forall m task. (HasCallStack, 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+    Just (sa, Used ts status count tasks n tp weak_arr) -> do       mad <- liftIO $ deRefWeak weak_arr       case mad of         Nothing -> liftIO $ do@@ -270,34 +289,36 @@           --           -- Small caveat: Due to finalisers being delayed, it's a good idea           -- to free the array here.-          Basic.freeStable (Proxy :: Proxy m) mt sa+          Basic.freeStable @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 $ D.didEvictBytes (remoteBytes n weak_arr)-          liftIO $ Basic.freeStable (Proxy :: Proxy m) mt sa-          liftIO $ HT.insert utbl sa (Used ts Evicted count tasks n weak_arr)+          copyIfNecessary status n tp arr+          liftIO $ D.didEvictBytes (remoteBytes tp n)+          liftIO $ Basic.freeStable @m mt sa+          liftIO $ HT.insert utbl sa (Used ts Evicted count tasks n tp 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 (sa, used@(Used ts status count tasks n tp weak_arr))+      | count == 0+      , evictable status+      = do+          tasks' <- cleanUses tasks+          HT.insert utbl sa (Used ts status count tasks' n tp 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 -    remoteBytes :: forall e a. PrimElt e a => Int -> Weak (ArrayData e) -> Int64-    remoteBytes n _ = fromIntegral n * fromIntegral (sizeOf (undefined::a))+    remoteBytes :: SingleType e -> Int -> Int64+    remoteBytes tp n = fromIntegral (bytesElt (TupRsingle (SingleScalarType tp))) * fromIntegral n      evictable :: Status -> Bool     evictable Clean     = True@@ -305,53 +326,54 @@     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+    copyIfNecessary :: Status -> Int -> SingleType e -> ArrayData e -> m ()+    copyIfNecessary Clean     _ _  _  = return ()+    copyIfNecessary Unmanaged _ _  _  = return ()+    copyIfNecessary Evicted   _ _  _  = internalError "Attempting to evict already evicted array"+    copyIfNecessary Dirty     n tp ad = do+      mp <- liftIO $ Basic.lookup @m mt tp ad       case mp of         Nothing -> return () -- RCE: I think this branch is actually impossible.-        Just p  -> peekRemote n p ad+        Just p  -> peekRemote tp 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+free :: forall m a task. (HasCallStack, RemoteMemory m)+     => MemoryTable (RemotePtr m) task+     -> SingleType a      -> ArrayData a      -> IO ()-free proxy (MemoryTable !mt !ref _) !arr+free (MemoryTable !mt !ref _) !tp !arr   = withMVar' ref   $ \utbl -> do-      key <- Basic.makeStableArray arr+      key <- Basic.makeStableArray tp arr       delete utbl key-      Basic.freeStable proxy mt key+      Basic.freeStable @m mt key --- |Record an association between a host-side array and a remote memory area+-- | 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+    :: (HasCallStack, MonadIO m, RemoteMemory m)+    => MemoryTable (RemotePtr m) task+    -> SingleType e     -> ArrayData e-    -> p a+    -> RemotePtr m (ScalarArrayDataR e)     -> m ()-insertUnmanaged (MemoryTable mt ref weak_utbl) !arr !ptr-  = liftIO-  . withMVar ref-  $ \utbl -> do-      key       <- Basic.makeStableArray arr-      ()        <- Basic.insertUnmanaged mt arr ptr+insertUnmanaged (MemoryTable mt ref weak_utbl) !tp !arr !ptr | SingleArrayDict <- singleArrayDict tp = do -- Gives evidence that ArrayData e ~ ScalarArrayData e+  key <- Basic.makeStableArray tp arr+  ()  <- Basic.insertUnmanaged mt tp arr ptr+  liftIO+    $ withMVar ref+    $ \utbl -> do       ts        <- getCPUTime-      weak_arr  <- makeWeakArrayData arr arr (Just $ finalizer key weak_utbl)-      HT.insert utbl key (Used ts Unmanaged 0 [] 0 weak_arr)+      weak_arr  <- makeWeakArrayData tp arr arr (Just $ finalizer key weak_utbl)+      HT.insert utbl key (Used ts Unmanaged 0 [] 0 tp weak_arr)   -- Removing entries@@ -368,11 +390,11 @@ delete = HT.delete  --- |Initiate garbage collection and `free` any remote arrays that no longer+-- | Initiate garbage collection and `free` any remote arrays that no longer -- have matching host-side equivalents. -- reclaim-    :: forall m task. (RemoteMemory m, MonadIO m)+    :: forall m task. (HasCallStack, RemoteMemory m, MonadIO m)     => MemoryTable (RemotePtr m) task     -> m () reclaim (MemoryTable !mt _ _) = Basic.reclaim mt@@ -383,7 +405,7 @@   $ HT.mapM_ (\(_,u) -> f u) tbl   where     f :: Used task -> IO ()-    f (Used _ _ _ _ _ w) = finalize w+    f (Used _ _ _ _ _ _ w) = finalize w  -- Miscellaneous -- -------------@@ -392,10 +414,10 @@ 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+incCount (Used ts status count uses n tp weak_arr) = Used ts status (count + 1) uses n tp weak_arr  isEvicted :: Used task -> Bool-isEvicted (Used _ status _ _ _ _) = status == Evicted+isEvicted (Used _ status _ _ _ _ _) = status == Evicted  {-# INLINE withMVar' #-} withMVar' :: (MonadIO m, MonadMask m) => MVar a -> (a -> m b) -> m b
src/Data/Array/Accelerate/Array/Remote/Nursery.hs view
@@ -1,14 +1,11 @@-{-# LANGUAGE BangPatterns    #-}-{-# LANGUAGE LambdaCase      #-}-{-# LANGUAGE TemplateHaskell #-}+{-# LANGUAGE BangPatterns #-}+{-# LANGUAGE LambdaCase   #-} -- | -- 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+-- Copyright   : [2008..2020] The Accelerate Team -- License     : BSD3 ----- Maintainer  : Trevor L. McDonell <tmcdonell@cse.unsw.edu.au>+-- Maintainer  : Trevor L. McDonell <trevor.mcdonell@gmail.com> -- Stability   : experimental -- Portability : non-portable (GHC extensions) --@@ -66,7 +63,7 @@ -- | Look for an entry with the requested size. -- {-# INLINEABLE lookup #-}-lookup :: Int -> Nursery ptr -> IO (Maybe (ptr Word8))+lookup :: HasCallStack => Int -> Nursery ptr -> IO (Maybe (ptr Word8)) lookup !key (Nursery !ref !_) =   withMVar ref $ \nrs ->     HT.mutateIO nrs key $ \case@@ -79,7 +76,7 @@               then return (Nothing, Just v)   -- delete this entry from the map               else return (Just vs, Just v)   -- re-insert the tail           ---          Seq.EmptyL  -> $internalError "lookup" "expected non-empty sequence"+          Seq.EmptyL  -> internalError "expected non-empty sequence"   -- | Add an entry to the nursery
src/Data/Array/Accelerate/Array/Remote/Table.hs view
@@ -1,3 +1,4 @@+{-# LANGUAGE AllowAmbiguousTypes        #-} {-# LANGUAGE BangPatterns               #-} {-# LANGUAGE CPP                        #-} {-# LANGUAGE ConstraintKinds            #-}@@ -7,18 +8,17 @@ {-# LANGUAGE PatternGuards              #-} {-# LANGUAGE RankNTypes                 #-} {-# LANGUAGE ScopedTypeVariables        #-}-{-# LANGUAGE TemplateHaskell            #-}+{-# LANGUAGE TypeApplications           #-}+{-# LANGUAGE TypeOperators              #-} {-# 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+-- Copyright   : [2008..2020] The Accelerate Team -- License     : BSD3 ----- Maintainer  : Robert Clifton-Everest <tmcdonell@cse.unsw.edu.au>+-- Maintainer  : Trevor L. McDonell <trevor.mcdonell@gmail.com> -- Stability   : experimental -- Portability : non-portable (GHC extensions) --@@ -35,7 +35,7 @@    -- Internals   StableArray, makeStableArray,-  makeWeakArrayData+  makeWeakArrayData,  ) where @@ -46,28 +46,27 @@ 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 Text.Printf 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.Type import Data.Array.Accelerate.Array.Unique                       ( UniqueArray(..) )-import Data.Array.Accelerate.Array.Data                         ( ArrayData, GArrayData(..),-                                                                  ArrayPtrs, ArrayElt, arrayElt, ArrayEltR(..) )+import Data.Array.Accelerate.Array.Data 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 +import GHC.Stack + -- 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.@@ -89,10 +88,9 @@                                       (p Word8 -> IO ())  data RemoteArray p where-  RemoteArray :: Typeable e-              => {-# UNPACK #-} !(Weak ())  -- Keep track of host array liveness-              -> !(p e)                     -- The actual remote pointer+  RemoteArray :: !(p Word8)                 -- The actual remote pointer               -> {-# UNPACK #-} !Int        -- The array size in bytes+              -> {-# UNPACK #-} !(Weak ())  -- Keep track of host array liveness               -> RemoteArray p  -- | An untyped reference to an array, similar to a StableName.@@ -103,7 +101,7 @@ instance Show StableArray where   show (StableArray u) = show (hash u) --- |Create a new memory table from host to remote arrays.+-- | 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@@ -122,36 +120,36 @@  -- | Look for the remote pointer corresponding to a given host-side array. ---lookup :: PrimElt a b-       => MemoryTable p+lookup :: forall m a. (HasCallStack, RemoteMemory m)+       => MemoryTable (RemotePtr m)+       -> SingleType a        -> 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+       -> IO (Maybe (RemotePtr m (ScalarArrayDataR a)))+lookup (MemoryTable !ref _ _ _) !tp !arr+  | SingleArrayDict <- singleArrayDict tp = do+    sa <- makeStableArray tp arr+    mw <- withMVar ref (`HT.lookup` sa)+    case mw of+      Nothing                      -> trace ("lookup/not found: " ++ show sa) $ return Nothing+      Just (RemoteArray p _ w) -> do+        mv <- deRefWeak w+        case mv of+          Just{}                   -> trace ("lookup/found: " ++ show sa) $ return (Just $ castRemotePtr @m p) +          -- 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 tp arr >>= \x -> internalError $ "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.@@ -159,139 +157,148 @@ -- 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)+malloc :: forall a m. (HasCallStack, RemoteMemory m, MonadIO m)        => MemoryTable (RemotePtr m)+       -> SingleType a        -> 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')-+       -> m (Maybe (RemotePtr m (ScalarArrayDataR a)))+malloc mt@(MemoryTable _ _ !nursery _) !tp !ad !n+  | SingleArrayDict <- singleArrayDict tp+  , SingleDict      <- singleDict tp+  = 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)) `quot` f+        bytes             = chunk * multiple (n * sizeOf (undefined::(ScalarArrayDataR a))) chunk+    --+    message $ printf "malloc %d bytes (%d x %d bytes, type=%s, pagesize=%d)" bytes n (sizeOf (undefined:: (ScalarArrayDataR a))) (show tp) chunk+    --+    mp <-+      fmap (castRemotePtr @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 tp ad p' bytes+        return mp   where+    {-# INLINE orElse #-}     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)+    orElse this next = do+      result <- this+      case result of+        Just{}  -> return result+        Nothing -> next +    {-# INLINE attempt #-}     attempt :: String -> m (Maybe x) -> m (Maybe x)-    attempt msg next = do-      ma <- next-      case ma of+    attempt msg this = do+      result <- this+      case result of+        Just{}  -> trace msg (return result)         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)+free :: forall m a. (RemoteMemory m)+     => MemoryTable (RemotePtr m)+     -> SingleType a      -> ArrayData a      -> IO ()-free proxy mt !arr = do-  sa <- makeStableArray arr-  freeStable proxy mt sa+free mt tp !arr = do+  sa <- makeStableArray tp arr+  freeStable @m 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)+    :: forall m. RemoteMemory m+    => MemoryTable (RemotePtr m)     -> StableArray     -> IO ()-freeStable proxy (MemoryTable !ref _ !nrs _) !sa =+freeStable (MemoryTable !ref _ !nrs _) !sa =   withMVar ref      $ \mt ->   HT.mutateIO mt sa $ \mw -> do     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+      Just (RemoteArray !p !bytes _) -> do+        message ("free/nursery: " ++ show sa ++ " of " ++ showBytes bytes)+        N.insert bytes (castRemotePtr @m p) nrs         D.decreaseCurrentBytesRemote (fromIntegral bytes)      return (Nothing, ())  --- 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.+-- | 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)+insert+    :: forall m a. (RemoteMemory m, MonadIO m)+    => MemoryTable (RemotePtr m)+    -> SingleType a+    -> ArrayData a+    -> RemotePtr m (ScalarArrayDataR a)+    -> Int+    -> m ()+insert mt@(MemoryTable !ref _ _ _) !tp !arr !ptr !bytes | SingleArrayDict <- singleArrayDict tp = do+  key  <- makeStableArray tp arr+  weak <- liftIO $ makeWeakArrayData tp arr () (Just $ freeStable @m mt key)   message $ "insert: " ++ show key   liftIO  $ D.increaseCurrentBytesRemote (fromIntegral bytes)-  liftIO  $ withMVar ref $ \tbl -> HT.insert tbl key (RemoteArray weak ptr bytes)+  liftIO  $ withMVar ref $ \tbl -> HT.insert tbl key (RemoteArray (castRemotePtr @m ptr) bytes weak)  --- |Record an association between a host-side array and a remote memory area+-- | 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+    :: forall m a. (MonadIO m, RemoteMemory m)+    => MemoryTable (RemotePtr m)+    -> SingleType a     -> ArrayData a-    -> p b+    -> RemotePtr m (ScalarArrayDataR a)     -> m ()-insertUnmanaged (MemoryTable !ref !weak_ref _ _) !arr !ptr = do-  key  <- makeStableArray  arr-  weak <- liftIO $ makeWeakArrayData arr () (Just $ remoteFinalizer weak_ref key)+insertUnmanaged (MemoryTable !ref !weak_ref _ _) tp !arr !ptr | SingleArrayDict  <- singleArrayDict tp = do+  key  <- makeStableArray tp arr+  weak <- liftIO $ makeWeakArrayData tp arr () (Just $ remoteFinalizer weak_ref key)   message $ "insertUnmanaged: " ++ show key-  liftIO  $ withMVar ref $ \tbl -> HT.insert tbl key (RemoteArray weak ptr 0)+  liftIO  $ withMVar ref $ \tbl -> HT.insert tbl key (RemoteArray (castRemotePtr @m ptr) 0 weak)   -- Removing entries -- ---------------- --- |Initiate garbage collection and mark any arrays that no longer have host-side--- equivalents as reusable.+-- | 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@@ -309,9 +316,9 @@     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+      mapM_ (freeStable @m mt) rs -- remove them all   where-    removable rs (sa, RemoteArray w _ _) = do+    removable rs (sa, RemoteArray _ _ w) = do       alive <- isJust <$> deRefWeak w       if alive         then return rs@@ -327,7 +334,7 @@   $ liftIO (N.cleanup release nrs)  --- |Initiate garbage collection and `free` any remote arrays that no longer+-- | 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 ()@@ -348,110 +355,34 @@ -- {-# INLINE makeStableArray #-} makeStableArray-    :: (MonadIO m, Typeable a, Typeable e, ArrayPtrs a ~ Ptr e, ArrayElt a)-    => ArrayData a+    :: MonadIO m+    => SingleType a+    -> ArrayData a     -> m StableArray-makeStableArray !ad = return $! StableArray (id arrayElt ad)-  where-    id :: (ArrayPtrs e ~ Ptr a) => 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 ArrayEltRhalf      (AD_Half 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 (ArrayEltRvec2 r)  (AD_V2 a)       = id r a-    id (ArrayEltRvec3 r)  (AD_V3 a)       = id r a-    id (ArrayEltRvec4 r)  (AD_V4 a)       = id r a-    id (ArrayEltRvec8 r)  (AD_V8 a)       = id r a-    id (ArrayEltRvec16 r) (AD_V16 a)      = id r a-#if __GLASGOW_HASKELL__ < 800-    id _ _ =-      error "I do have a cause, though. It is obscenity. I'm for it."-#endif+makeStableArray !tp !ad+  | SingleArrayDict <- singleArrayDict tp+  = return $! StableArray (uniqueArrayId ad) + -- Weak arrays--- ----------------------+-- ----------- --- |Make a weak pointer using an array as a key. Unlike the standard `mkWeak`,+-- | 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+    :: forall e c.+       SingleType e+    -> ArrayData e     -> c     -> Maybe (IO ())     -> IO (Weak c)-makeWeakArrayData !ad !c !mf = mw arrayElt ad-  where-    mw :: (ArrayPtrs e' ~ Ptr a) => 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 ArrayEltRhalf      (AD_Half 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-    mw (ArrayEltRvec2 r)  (AD_V2 a)       = mw r a-    mw (ArrayEltRvec3 r)  (AD_V3 a)       = mw r a-    mw (ArrayEltRvec4 r)  (AD_V4 a)       = mw r a-    mw (ArrayEltRvec8 r)  (AD_V8 a)       = mw r a-    mw (ArrayEltRvec16 r) (AD_V16 a)      = mw r a-#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+makeWeakArrayData !tp !ad !c !mf | SingleArrayDict <- singleArrayDict tp = do+  let !uad = uniqueArrayData ad+  case mf of+    Nothing -> return ()+    Just f  -> addFinalizer uad f+  mkWeak uad c   -- Debug@@ -472,16 +403,23 @@ {-# 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+  yes <- liftIO $ D.getFlag D.dump_gc+  if yes+    then do+      total       <- totalRemoteMem+      before      <- availableRemoteMem+      before_nrs  <- liftIO $ N.size nrs+      r           <- next+      after       <- availableRemoteMem+      after_nrs   <- liftIO $ N.size nrs+      message $ printf "%s (freed: %s, stashed: %s, remaining: %s of %s)"+                  msg+                  (showBytes (before - after))+                  (showBytes (after_nrs - before_nrs))+                  (showBytes after)+                  (showBytes total)+      --+      return r+    else+      next 
− src/Data/Array/Accelerate/Array/Representation.hs
@@ -1,235 +0,0 @@-{-# LANGUAGE FlexibleContexts    #-}-{-# LANGUAGE FlexibleInstances   #-}-{-# LANGUAGE GADTs               #-}-{-# LANGUAGE ScopedTypeVariables #-}-{-# LANGUAGE TemplateHaskell     #-}-{-# LANGUAGE TupleSections       #-}-{-# LANGUAGE TypeFamilies        #-}-{-# LANGUAGE TypeOperators       #-}-{-# OPTIONS_HADDOCK hide #-}--- |--- Module      : Data.Array.Accelerate.Array.Representation--- 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.Representation (--  -- * Array shapes, indices, and slices-  Shape(..), Slice(..), SliceIndex(..),--  -- * Slice shape functions-  sliceShape, enumSlices,--) where---- friends-import Data.Array.Accelerate.Error---- standard library-import GHC.Base                                         ( quotInt, remInt )----- |Index representation------- |Class of index representations (which are nested pairs)----class (Eq sh, Slice sh) => Shape sh where-  -- user-facing methods-  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)-  fromIndex :: sh -> Int -> sh -- inverse of `toIndex`--  iter      :: sh -> (sh -> a) -> (a -> a -> a) -> a -> a-                               -- iterate through the entire shape, applying the function in the-                               -- second argument; third argument combines results and fourth is an-                               -- initial value that is combined with the results; the index space-                               -- is traversed in row-major order--  iter1     :: sh -> (sh -> a) -> (a -> a -> a) -> a-                               -- variant of 'iter' without an initial value--  -- operations to facilitate conversion with IArray-  rangeToShape :: (sh, sh) -> sh   -- convert a minpoint-maxpoint index-                                   -- into a shape-  shapeToRange :: sh -> (sh, sh)   -- ...the converse---  -- other conversions-  shapeToList :: sh -> [Int]    -- convert a shape into its list of dimensions-  listToShape :: [Int] -> sh    -- convert a list of dimensions into a shape--instance Shape () where-  rank _            = 0-  empty             = ()-  ignore            = ()-  () `intersect` () = ()-  () `union` ()     = ()-  size ()           = 1-  toIndex () ()     = 0-  fromIndex () _    = ()-  iter  () f _ _    = f ()-  iter1 () f _      = f ()--  rangeToShape ((), ()) = ()-  shapeToRange ()       = ((), ())--  shapeToList () = []-  listToShape [] = ()-  listToShape _  = $internalError "listToShape" "non-empty list when converting to unit"--instance Shape sh => Shape (sh, Int) where-  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--  fromIndex (sh, sz) i              = (fromIndex sh (i `quotInt` sz), r)-    -- If we assume that the index is in range, there is no point in computing-    -- the remainder for the highest dimension since i < sz must hold.-    ---    where-      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      -> next `addDim` 0-                                        Mirror     -> next `addDim` (-i)-                                        Wrap       -> next `addDim` (sz+i)-                                        Constant e -> Left e-    | i >= sz                       = case bndy of-                                        Clamp      -> next `addDim` (sz-1)-                                        Mirror     -> next `addDim` (sz-(i-sz+2))-                                        Wrap       -> next `addDim` (i-sz)-                                        Constant e -> Left e-    | otherwise                     = next `addDim` i-    where-      -- This function is quite difficult to optimize due to the deep recursion-      -- that it 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---}--  iter (sh, sz) f c r = iter sh (\ix -> iter' (ix,0)) c r-    where-      iter' (ix,i) | i >= sz   = r-                   | otherwise = f (ix,i) `c` iter' (ix,i+1)--  iter1 (_,  0)  _ _ = $boundsError "iter1" "empty iteration space"-  iter1 (sh, sz) f c = iter1 sh (\ix -> iter1' (ix,0)) c-    where-      iter1' (ix,i) | i == sz-1 = f (ix,i)-                    | otherwise = f (ix,i) `c` iter1' (ix,i+1)--  rangeToShape ((sh1, sz1), (sh2, sz2))-    = (rangeToShape (sh1, sh2), sz2 - sz1 + 1)-  shapeToRange (sh, sz)-    = let (low, high) = shapeToRange sh-      in-      ((low, 0), (high, sz - 1))--  shapeToList (sh,sz) = sz : shapeToList sh-  listToShape []      = $internalError "listToShape" "empty list when converting to Ix"-  listToShape (x:xs)  = (listToShape xs,x)----- |Slice representation------- |Class of slice representations (which are nested pairs)----class Slice sl where-  type SliceShape    sl      -- the projected slice-  type CoSliceShape  sl      -- the complement of the slice-  type FullShape     sl      -- the combined dimension-    -- argument *value* not used; it's just a phantom value to fix the type-  sliceIndex :: {-dummy-} sl -> SliceIndex sl (SliceShape sl) (CoSliceShape sl) (FullShape sl)--instance Slice () where-  type SliceShape    () = ()-  type CoSliceShape  () = ()-  type FullShape     () = ()-  sliceIndex _ = SliceNil--instance Slice sl => Slice (sl, ()) where-  type SliceShape   (sl, ()) = (SliceShape  sl, Int)-  type CoSliceShape (sl, ()) = CoSliceShape sl-  type FullShape    (sl, ()) = (FullShape   sl, Int)-  sliceIndex _ = 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 _ = SliceFixed (sliceIndex (undefined::sl))---- |Generalised array index, which may index only in a subset of the dimensions--- of a shape.----data SliceIndex ix slice coSlice sliceDim where-  SliceNil   :: SliceIndex () () () ()-  SliceAll   ::-   SliceIndex ix slice co dim -> SliceIndex (ix, ()) (slice, Int) co (dim, Int)-  SliceFixed ::-   SliceIndex ix slice co dim -> SliceIndex (ix, Int) slice (co, Int) (dim, Int)--instance Show (SliceIndex ix slice coSlice sliceDim) where-  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]]-
− src/Data/Array/Accelerate/Array/Sugar.hs
@@ -1,1381 +0,0 @@-{-# LANGUAGE BangPatterns          #-}-{-# LANGUAGE CPP                   #-}-{-# LANGUAGE ConstraintKinds       #-}-{-# LANGUAGE DeriveDataTypeable    #-}-{-# LANGUAGE FlexibleContexts      #-}-{-# LANGUAGE FlexibleInstances     #-}-{-# LANGUAGE GADTs                 #-}-{-# LANGUAGE ScopedTypeVariables   #-}-{-# LANGUAGE StandaloneDeriving    #-}-{-# LANGUAGE TemplateHaskell       #-}-{-# LANGUAGE TupleSections         #-}-{-# LANGUAGE TypeFamilies          #-}-{-# LANGUAGE TypeOperators         #-}-{-# LANGUAGE UndecidableInstances  #-}-{-# OPTIONS_GHC -fno-warn-orphans #-}-#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, Matrix, 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, reshape, (!), (!!), allocateArray, fromFunction, fromFunctionM, 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.Typeable-import GHC.Exts                                                 ( IsList )-import System.IO.Unsafe                                         ( unsafePerformIO )-import Prelude                                                  hiding ( (!!) )-import Language.Haskell.TH                                      hiding ( Foreign )-import qualified GHC.Exts                                       as GHC-import qualified Data.Vector.Unboxed                            as U---- friends-import Data.Array.Accelerate.Array.Data-import Data.Array.Accelerate.Error-import Data.Array.Accelerate.Product-import Data.Array.Accelerate.Type-import qualified Data.Array.Accelerate.Array.Representation     as Repr---- $setup--- >>> :seti -XOverloadedLists---- 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--- --------------------------------------------------- TLM: Why is EltRepr not an associated type of Elt?------- | 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 Half            = Half-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 (V2 a)          = V2 a    -- we can only store primitive types in SIMD vectors-type instance EltRepr (V3 a)          = V3 a-type instance EltRepr (V4 a)          = V4 a-type instance EltRepr (V8 a)          = V8 a-type instance EltRepr (V16 a)         = V16 a-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 instance EltRepr (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p) = 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, EltRepr p)--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 (half, 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 _ = TypeRunit-  fromElt   = id-  toElt     = id--instance Elt Z where-  eltType _  = TypeRunit-  fromElt Z  = ()-  toElt ()   = Z--instance (Elt t, Elt h) => Elt (t:.h) where-  eltType (_::(t:.h))   = TypeRpair (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 _     = TypeRunit-  fromElt All   = ()-  toElt ()      = All--instance Elt (Any Z) where-  eltType _     = TypeRunit-  fromElt _     = ()-  toElt _       = Any--instance Shape sh => Elt (Any (sh:.Int)) where-  eltType _     = TypeRpair (eltType (undefined::Any sh)) TypeRunit-  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 Half 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 _             = TypeRpair (TypeRpair TypeRunit (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 _             = TypeRpair (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 _             = TypeRpair (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 _               = TypeRpair (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 _-    = TypeRpair (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 _-    = TypeRpair (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 _-    = TypeRpair (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 _-    = TypeRpair (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 _-    = TypeRpair (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 _-    = TypeRpair (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 _-    = TypeRpair (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 _-    = TypeRpair (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 _-    = TypeRpair (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 _-    = TypeRpair (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)--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 p)-  => Elt (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p) where-  eltType _-    = TypeRpair (eltType (undefined :: (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o)))-                (eltType (undefined :: p))-  fromElt (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p) = (fromElt (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o), fromElt p)-  toElt (abcdefghijklmno, p) = let (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o) = toElt abcdefghijklmno-                               in  (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, toElt p)---- |Convenience functions-----singletonScalarType :: IsScalar a => a -> TupleType a-singletonScalarType _ = TypeRscalar scalarType--{-# INLINE liftToElt #-}-liftToElt :: (Elt a, Elt b)-          => (EltRepr a -> EltRepr b)-          -> (a -> b)-liftToElt f = toElt . f . fromElt--{-# INLINE liftToElt2 #-}-liftToElt2 :: (Elt a, Elt b, Elt c)-           => (EltRepr a -> EltRepr b -> EltRepr c)-           -> (a -> b -> c)-liftToElt2 f x y = toElt $ f (fromElt x) (fromElt y)--{-# INLINE sinkFromElt #-}-sinkFromElt :: (Elt a, Elt b)-            => (a -> b)-            -> (EltRepr a -> EltRepr b)-sinkFromElt f = fromElt . f . toElt--{-# INLINE sinkFromElt2 #-}-sinkFromElt2 :: (Elt a, Elt b, Elt c)-             => (a -> b -> c)-             -> (EltRepr a -> EltRepr b -> EltRepr c)-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-  strForeign _ = "<foreign>"--  -- Backends which want to support compile-time embedding must be able to lift-  -- the foreign function into Template Haskell-  liftForeign :: asm args -> Q (TExp (asm args))-  liftForeign _ = $internalError "liftForeign" "not supported by this backend"----- 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 instance ArrRepr (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p) = 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, ArrRepr p)--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)--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 p)-  => Arrays (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p) where-  arrays  _             = ArraysRpair (arrays (undefined :: (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o))) (arrays (undefined::p))-  flavour _             = ArraysFtuple-  ---  toArr    (abcdefghijklmno, p) = let (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o) = toArr abcdefghijklmno in (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, toArr p)-  fromArr  (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p) = (fromArr (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o), fromArr p)----- {-# 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-    where-      Z :. rows :. cols = shape arr-      lengths           = U.generate (rows*cols) (\i -> length (show (arr !! i)))-      widths            = U.generate cols (\c -> U.maximum (U.generate rows (\r -> lengths U.! (r*cols+c))))-      ---      showMat-        | rows * cols == 0 = "[]"-        | otherwise        = "\n  [" ++ ppMat 0 0-      ---      ppMat :: Int -> Int -> String-      ppMat !r !c | c >= cols = ppMat (r+1) 0-      ppMat !r !c             =-        let-            !i    = r*cols+c-            !l    = lengths U.! i-            !w    = widths  U.! c-            !pad  = 1-            cell  = replicate (w-l+pad) ' ' ++ show (arr !! i)-            ---            before-              | r > 0 && c == 0 = "\n   "-              | otherwise       = ""-            ---            after-              | r >= rows-1 && c >= cols-1 = "]"-              | otherwise                  = ',' : ppMat r (c+1)-        in-        before ++ cell ++ after-#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 ArrayEltRhalf         (AD_Half 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 (ArrayEltRvec2 r)     (AD_V2 a)       = go r a `seq` ()-      go (ArrayEltRvec3 r)     (AD_V3 a)       = go r a `seq` ()-      go (ArrayEltRvec4 r)     (AD_V4 a)       = go r a `seq` ()-      go (ArrayEltRvec8 r)     (AD_V8 a)       = go r a `seq` ()-      go (ArrayEltRvec16 r)    (AD_V16 a)      = go r a `seq` ()-      go (ArrayEltRpair r1 r2) (AD_Pair a1 a2) = go r1 a1 `seq` go r2 a2 `seq` ()----- | Scalar arrays hold a single element----type Scalar = Array DIM0---- | Vectors are one-dimensional arrays----type Vector = Array DIM1---- | Matrices are two-dimensional arrays----type Matrix = Array DIM2---- | 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 = Vector---- 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--  -- |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)--  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---- | Change the shape of an array without altering its contents. The 'size' of--- the source and result arrays must be identical.----reshape :: (Shape sh, Shape sh', Elt e) => sh -> Array sh' e -> Array sh e-reshape sh (Array sh' adata)-  = $boundsCheck "reshape" "shape mismatch" (size sh == Repr.size sh')-  $ Array (fromElt sh) adata---- | Array indexing----infixl 9 !-{-# INLINE (!) #-}-(!) :: Array sh e -> sh -> e-(!) (Array sh adata) ix = toElt (adata `unsafeIndexArrayData` toIndex (toElt sh) ix)--infixl 9 !!-{-# INLINE (!!) #-}-(!!) :: Array sh e -> Int -> e-(!!) (Array _ adata) i = toElt (adata `unsafeIndexArrayData` i)---- | Create an array from its representation function, applied at each index of--- the array.----{-# INLINEABLE fromFunction #-}-fromFunction :: (Shape sh, Elt e) => sh -> (sh -> e) -> Array sh e-fromFunction sh f = unsafePerformIO $! fromFunctionM sh (return . f)---- | Create an array using a monadic function applied at each index.----{-# INLINEABLE fromFunctionM #-}-fromFunctionM :: (Shape sh, Elt e) => sh -> (sh -> IO e) -> IO (Array sh e)-fromFunctionM sh f = do-  let !n = size sh-  arr <- newArrayData n-  ---  let write !i-        | i >= n    = return ()-        | otherwise = do-            v <- f (fromIndex sh i)-            unsafeWriteArrayData arr i (fromElt v)-            write (i+1)-  ---  write 0-  return $! arr `seq` Array (fromElt sh) arr----- | Create a vector from the concatenation of the given list of vectors.----{-# INLINEABLE concatVectors #-}-concatVectors :: Elt e => [Vector e] -> Vector e-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.----{-# INLINEABLE allocateArray #-}-allocateArray :: (Shape sh, Elt e) => sh -> IO (Array sh e)-allocateArray sh = do-  adata  <- newArrayData (size sh)-  return $! Array (fromElt sh) adata----- | 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) :: Matrix 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.----{-# INLINEABLE fromList #-}-fromList :: (Shape sh, Elt e) => sh -> [e] -> Array sh e-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.----{-# INLINEABLE toList #-}-toList :: forall sh e. Array sh e -> [e]-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----- | Orphans----deriving instance (Show a, Show b, Show c, Show d, Show e, Show f, Show g, Show h, Show i, Show j, Show k, Show l, Show m, Show n, Show o, Show p)-  => Show (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p)-
src/Data/Array/Accelerate/Array/Unique.hs view
@@ -1,23 +1,22 @@+{-# LANGUAGE BangPatterns        #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TemplateHaskell     #-} {-# OPTIONS_HADDOCK hide #-} -- | -- Module      : Data.Array.Accelerate.Array.Unique--- Copyright   : [2016..2017] Manuel M T Chakravarty, Gabriele Keller, Trevor L. McDonell, Robert Clifton-Everest+-- Copyright   : [2016..2020] The Accelerate Team -- License     : BSD3 ----- Maintainer  : Trevor L. McDonell <tmcdonell@cse.unsw.edu.au>+-- Maintainer  : Trevor L. McDonell <trevor.mcdonell@gmail.com> -- Stability   : experimental -- Portability : non-portable (GHC extensions) -- -module Data.Array.Accelerate.Array.Unique (--  UniqueArray(..),-  newUniqueArray,-  withUniqueArrayPtr,-  unsafeUniqueArrayPtr,-  touchUniqueArray,+module Data.Array.Accelerate.Array.Unique+  where -) where+-- friends+import Data.Array.Accelerate.Lifetime  -- library import Control.Applicative@@ -25,13 +24,16 @@ import Control.DeepSeq import Foreign.ForeignPtr import Foreign.ForeignPtr.Unsafe+import Foreign.Marshal.Array import Foreign.Ptr+import Foreign.Storable+import Language.Haskell.TH+import Language.Haskell.TH.Syntax+import Data.Word+import System.IO.Unsafe 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@@ -52,8 +54,7 @@     }  instance NFData (UniqueArray e) where-  rnf (UniqueArray _ ad) = unsafeGetValue ad `seq` ()-+  rnf = rnfUniqueArray  -- | Create a new UniqueArray --@@ -73,7 +74,31 @@ withUniqueArrayPtr ua go =   withLifetime (uniqueArrayData ua) $ \fp -> withForeignPtr fp go +-- | Returns the element of an immutable array at the specified index. This+-- does no bounds checking.+--+{-# INLINE unsafeIndexArray #-}+unsafeIndexArray :: Storable e => UniqueArray e -> Int -> e+unsafeIndexArray !ua !i =+  unsafePerformIO $! unsafeReadArray ua i +-- | Read an element from a mutable array at the given index. This does no+-- bounds checking.+--+{-# INLINE unsafeReadArray #-}+unsafeReadArray :: Storable e => UniqueArray e -> Int -> IO e+unsafeReadArray !ua !i =+  withUniqueArrayPtr ua $ \ptr -> peekElemOff ptr i++-- | Write an element into a mutable array at the given index. This does no+-- bounds checking.+--+{-# INLINE unsafeWriteArray #-}+unsafeWriteArray :: Storable e => UniqueArray e -> Int -> e -> IO ()+unsafeWriteArray !ua !i !e =+  withUniqueArrayPtr ua $ \ptr -> pokeElemOff ptr i e++ -- | Extract the pointer backing the unique array. -- -- This is potentially unsafe, as if the argument is the last occurrence of this@@ -95,4 +120,19 @@ {-# INLINE touchUniqueArray #-} touchUniqueArray :: UniqueArray a -> IO () touchUniqueArray = touchLifetime . uniqueArrayData+++rnfUniqueArray :: UniqueArray a -> ()+rnfUniqueArray (UniqueArray _ ad) = unsafeGetValue ad `seq` ()++-- TODO: Make sure that the data is correctly aligned...+--+liftUniqueArray :: forall a. Storable a => Int -> UniqueArray a -> Q (TExp (UniqueArray a))+liftUniqueArray sz ua = do+  bytes <- runIO $ peekArray (sizeOf (undefined::a) * sz) (castPtr (unsafeUniqueArrayPtr ua) :: Ptr Word8)+  [|| unsafePerformIO $ do+       fp  <- newForeignPtr_ $$( unsafeTExpCoerce [| Ptr $(litE (StringPrimL bytes)) |] )+       ua' <- newUniqueArray (castForeignPtr fp)+       return ua'+   ||] 
src/Data/Array/Accelerate/Async.hs view
@@ -4,10 +4,10 @@ {-# OPTIONS_HADDOCK hide #-} -- | -- Module      : Data.Array.Accelerate.Async--- Copyright   : [2009..2017] Manuel M T Chakravarty, Gabriele Keller, Trevor L. McDonell+-- Copyright   : [2009..2020] The Accelerate Team -- License     : BSD3 ----- Maintainer  : Trevor L. McDonell <tmcdonell@cse.unsw.edu.au>+-- Maintainer  : Trevor L. McDonell <trevor.mcdonell@gmail.com> -- Stability   : experimental -- Portability : non-portable (GHC extensions) --
src/Data/Array/Accelerate/Classes.hs view
@@ -1,10 +1,10 @@ {-# LANGUAGE NoImplicitPrelude #-} -- | -- Module      : Data.Array.Accelerate.Classes--- Copyright   : [2016..2017] Manuel M T Chakravarty, Gabriele Keller, Trevor L. McDonell+-- Copyright   : [2016..2020] The Accelerate Team -- License     : BSD3 ----- Maintainer  : Trevor L. McDonell <tmcdonell@cse.unsw.edu.au>+-- Maintainer  : Trevor L. McDonell <trevor.mcdonell@gmail.com> -- Stability   : experimental -- Portability : non-portable (GHC extensions) --@@ -23,8 +23,8 @@    -- *** Numeric type classes   module Num,-  module Real,   module Integral,+  module Rational,   module Fractional,   module Floating,   module RealFrac,@@ -43,9 +43,9 @@ 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.Rational                       as Rational 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
src/Data/Array/Accelerate/Classes/Bounded.hs view
@@ -1,13 +1,15 @@ {-# LANGUAGE ConstraintKinds   #-} {-# LANGUAGE FlexibleContexts  #-} {-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE TemplateHaskell   #-}+{-# LANGUAGE TypeApplications  #-} {-# OPTIONS_GHC -fno-warn-orphans #-} -- | -- Module      : Data.Array.Accelerate.Classes.Bounded--- Copyright   : [2016..2017] Manuel M T Chakravarty, Gabriele Keller, Trevor L. McDonell+-- Copyright   : [2016..2020] The Accelerate Team -- License     : BSD3 ----- Maintainer  : Trevor L. McDonell <tmcdonell@cse.unsw.edu.au>+-- Maintainer  : Trevor L. McDonell <trevor.mcdonell@gmail.com> -- Stability   : experimental -- Portability : non-portable (GHC extensions) --@@ -19,10 +21,15 @@  ) where -import Data.Array.Accelerate.Array.Sugar+import Data.Array.Accelerate.Array.Data+import Data.Array.Accelerate.Pattern import Data.Array.Accelerate.Smart+import Data.Array.Accelerate.Sugar.Elt import Data.Array.Accelerate.Type +import Prelude                                                      ( ($), (<$>), Num(..), Char, Bool, show, concat, map, mapM )+import Language.Haskell.TH                                          hiding ( Exp )+import Language.Haskell.TH.Extra import qualified Prelude                                            as P  @@ -77,129 +84,72 @@   maxBound = mkMaxBound  instance P.Bounded (Exp CShort) where-  minBound = mkMinBound-  maxBound = mkMaxBound+  minBound = mkBitcast (mkMinBound @Int16)+  maxBound = mkBitcast (mkMaxBound @Int16)  instance P.Bounded (Exp CUShort) where-  minBound = mkMinBound-  maxBound = mkMaxBound+  minBound = mkBitcast (mkMinBound @Word16)+  maxBound = mkBitcast (mkMaxBound @Word16)  instance P.Bounded (Exp CInt) where-  minBound = mkMinBound-  maxBound = mkMaxBound+  minBound = mkBitcast (mkMinBound @Int32)+  maxBound = mkBitcast (mkMaxBound @Int32)  instance P.Bounded (Exp CUInt) where-  minBound = mkMinBound-  maxBound = mkMaxBound+  minBound = mkBitcast (mkMinBound @Word32)+  maxBound = mkBitcast (mkMaxBound @Word32)  instance P.Bounded (Exp CLong) where-  minBound = mkMinBound-  maxBound = mkMaxBound+  minBound = mkBitcast (mkMinBound @HTYPE_CLONG)+  maxBound = mkBitcast (mkMaxBound @HTYPE_CLONG)  instance P.Bounded (Exp CULong) where-  minBound = mkMinBound-  maxBound = mkMaxBound+  minBound = mkBitcast (mkMinBound @HTYPE_CULONG)+  maxBound = mkBitcast (mkMaxBound @HTYPE_CULONG)  instance P.Bounded (Exp CLLong) where-  minBound = mkMinBound-  maxBound = mkMaxBound+  minBound = mkBitcast (mkMinBound @Int64)+  maxBound = mkBitcast (mkMaxBound @Int64)  instance P.Bounded (Exp CULLong) where-  minBound = mkMinBound-  maxBound = mkMaxBound+  minBound = mkBitcast (mkMinBound @Word64)+  maxBound = mkBitcast (mkMaxBound @Word64)  instance P.Bounded (Exp Bool) where-  minBound = mkMinBound-  maxBound = mkMaxBound+  minBound = constant P.minBound+  maxBound = constant P.maxBound  instance P.Bounded (Exp Char) where   minBound = mkMinBound   maxBound = mkMaxBound  instance P.Bounded (Exp CChar) where-  minBound = mkMinBound-  maxBound = mkMaxBound+  minBound = mkBitcast (mkMinBound @HTYPE_CCHAR)+  maxBound = mkBitcast (mkMaxBound @HTYPE_CCHAR)  instance P.Bounded (Exp CSChar) where-  minBound = mkMinBound-  maxBound = mkMaxBound+  minBound = mkBitcast (mkMinBound @Int8)+  maxBound = mkBitcast (mkMaxBound @Int8)  instance P.Bounded (Exp CUChar) where-  minBound = mkMinBound-  maxBound = mkMaxBound--instance (Bounded a, Bounded b)-    => P.Bounded (Exp (a,b)) where-  minBound = tup2 (P.minBound, P.minBound)-  maxBound = tup2 (P.maxBound, P.maxBound)--instance (Bounded a, Bounded b, Bounded 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 (Bounded a, Bounded b, Bounded c, Bounded 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 (Bounded a, Bounded b, Bounded c, Bounded d, Bounded 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 (Bounded a, Bounded b, Bounded c, Bounded d, Bounded e, Bounded 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 (Bounded a, Bounded b, Bounded c, Bounded d, Bounded e, Bounded f, Bounded 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 (Bounded a, Bounded b, Bounded c, Bounded d, Bounded e, Bounded f, Bounded g, Bounded 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 (Bounded a, Bounded b, Bounded c, Bounded d, Bounded e, Bounded f, Bounded g, Bounded h, Bounded 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 (Bounded a, Bounded b, Bounded c, Bounded d, Bounded e, Bounded f, Bounded g, Bounded h, Bounded i, Bounded 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 (Bounded a, Bounded b, Bounded c, Bounded d, Bounded e, Bounded f, Bounded g, Bounded h, Bounded i, Bounded j, Bounded 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 (Bounded a, Bounded b, Bounded c, Bounded d, Bounded e, Bounded f, Bounded g, Bounded h, Bounded i, Bounded j, Bounded k, Bounded 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 (Bounded a, Bounded b, Bounded c, Bounded d, Bounded e, Bounded f, Bounded g, Bounded h, Bounded i, Bounded j, Bounded k, Bounded l, Bounded 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 (Bounded a, Bounded b, Bounded c, Bounded d, Bounded e, Bounded f, Bounded g, Bounded h, Bounded i, Bounded j, Bounded k, Bounded l, Bounded m, Bounded 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 (Bounded a, Bounded b, Bounded c, Bounded d, Bounded e, Bounded f, Bounded g, Bounded h, Bounded i, Bounded j, Bounded k, Bounded l, Bounded m, Bounded n, Bounded 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)+  minBound = mkBitcast (mkMinBound @Word8)+  maxBound = mkBitcast (mkMaxBound @Word8) -instance (Bounded a, Bounded b, Bounded c, Bounded d, Bounded e, Bounded f, Bounded g, Bounded h, Bounded i, Bounded j, Bounded k, Bounded l, Bounded m, Bounded n, Bounded o, Bounded p)-    => P.Bounded (Exp (a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p)) where-  minBound = tup16 (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, P.minBound)-  maxBound = tup16 (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, P.maxBound)+$(runQ $ do+    let+        mkInstance :: Int -> Q [Dec]+        mkInstance n =+          let+              xs      = [ mkName ('x':show i) | i <- [0 .. n-1] ]+              cst     = tupT (map (\x -> [t| Bounded $(varT x) |]) xs)+              res     = tupT (map varT xs)+              app x   = appsE (conE (mkName ('T':show n)) : P.replicate n x)+          in+          [d| instance $cst => P.Bounded (Exp $res) where+                minBound = $(app [| P.minBound |])+                maxBound = $(app [| P.maxBound |])+            |]+    --+    concat <$> mapM mkInstance [2..16]+ ) 
src/Data/Array/Accelerate/Classes/Enum.hs view
@@ -5,10 +5,10 @@ {-# OPTIONS_GHC -fno-warn-orphans #-} -- | -- Module      : Data.Array.Accelerate.Classes.Enum--- Copyright   : [2016..2017] Manuel M T Chakravarty, Gabriele Keller, Trevor L. McDonell+-- Copyright   : [2016..2020] The Accelerate Team -- License     : BSD3 ----- Maintainer  : Trevor L. McDonell <tmcdonell@cse.unsw.edu.au>+-- Maintainer  : Trevor L. McDonell <trevor.mcdonell@gmail.com> -- Stability   : experimental -- Portability : non-portable (GHC extensions) --@@ -20,11 +20,12 @@  ) where +import Data.Array.Accelerate.Classes.Num import Data.Array.Accelerate.Smart import Data.Array.Accelerate.Type import Text.Printf -import Prelude                                                      hiding ( Enum )+import Prelude                                                      ( ($), String, error, unlines, succ, pred ) import qualified Prelude                                            as P  @@ -34,143 +35,148 @@   instance P.Enum (Exp Int) where-  succ x    = mkAdd x (constant 1)-  pred x    = mkSub x (constant 1)+  succ      = defaultSucc+  pred      = defaultPred   toEnum    = defaultToEnum   fromEnum  = defaultFromEnum  instance P.Enum (Exp Int8) where-  succ x    = mkAdd x (constant 1)-  pred x    = mkSub x (constant 1)+  succ      = defaultSucc+  pred      = defaultPred   toEnum    = defaultToEnum   fromEnum  = defaultFromEnum  instance P.Enum (Exp Int16) where-  succ x    = mkAdd x (constant 1)-  pred x    = mkSub x (constant 1)+  succ      = defaultSucc+  pred      = defaultPred   toEnum    = defaultToEnum   fromEnum  = defaultFromEnum  instance P.Enum (Exp Int32) where-  succ x    = mkAdd x (constant 1)-  pred x    = mkSub x (constant 1)+  succ      = defaultSucc+  pred      = defaultPred   toEnum    = defaultToEnum   fromEnum  = defaultFromEnum  instance P.Enum (Exp Int64) where-  succ x    = mkAdd x (constant 1)-  pred x    = mkSub x (constant 1)+  succ      = defaultSucc+  pred      = defaultPred   toEnum    = defaultToEnum   fromEnum  = defaultFromEnum  instance P.Enum (Exp Word) where-  succ x    = mkAdd x (constant 1)-  pred x    = mkSub x (constant 1)+  succ      = defaultSucc+  pred      = defaultPred   toEnum    = defaultToEnum   fromEnum  = defaultFromEnum  instance P.Enum (Exp Word8) where-  succ x    = mkAdd x (constant 1)-  pred x    = mkSub x (constant 1)+  succ      = defaultSucc+  pred      = defaultPred   toEnum    = defaultToEnum   fromEnum  = defaultFromEnum  instance P.Enum (Exp Word16) where-  succ x    = mkAdd x (constant 1)-  pred x    = mkSub x (constant 1)+  succ      = defaultSucc+  pred      = defaultPred   toEnum    = defaultToEnum   fromEnum  = defaultFromEnum  instance P.Enum (Exp Word32) where-  succ x    = mkAdd x (constant 1)-  pred x    = mkSub x (constant 1)+  succ      = defaultSucc+  pred      = defaultPred   toEnum    = defaultToEnum   fromEnum  = defaultFromEnum  instance P.Enum (Exp Word64) where-  succ x    = mkAdd x (constant 1)-  pred x    = mkSub x (constant 1)+  succ      = defaultSucc+  pred      = defaultPred   toEnum    = defaultToEnum   fromEnum  = defaultFromEnum  instance P.Enum (Exp CInt) where-  succ x    = mkAdd x (constant 1)-  pred x    = mkSub x (constant 1)+  succ      = defaultSucc+  pred      = defaultPred   toEnum    = defaultToEnum   fromEnum  = defaultFromEnum  instance P.Enum (Exp CUInt) where-  succ x    = mkAdd x (constant 1)-  pred x    = mkSub x (constant 1)+  succ      = defaultSucc+  pred      = defaultPred   toEnum    = defaultToEnum   fromEnum  = defaultFromEnum  instance P.Enum (Exp CLong) where-  succ x    = mkAdd x (constant 1)-  pred x    = mkSub x (constant 1)+  succ      = defaultSucc+  pred      = defaultPred   toEnum    = defaultToEnum   fromEnum  = defaultFromEnum  instance P.Enum (Exp CULong) where-  succ x    = mkAdd x (constant 1)-  pred x    = mkSub x (constant 1)+  succ      = defaultSucc+  pred      = defaultPred   toEnum    = defaultToEnum   fromEnum  = defaultFromEnum  instance P.Enum (Exp CLLong) where-  succ x    = mkAdd x (constant 1)-  pred x    = mkSub x (constant 1)+  succ      = defaultSucc+  pred      = defaultPred   toEnum    = defaultToEnum   fromEnum  = defaultFromEnum  instance P.Enum (Exp CULLong) where-  succ x    = mkAdd x (constant 1)-  pred x    = mkSub x (constant 1)+  succ      = defaultSucc+  pred      = defaultPred   toEnum    = defaultToEnum   fromEnum  = defaultFromEnum  instance P.Enum (Exp CShort) where-  succ x    = mkAdd x (constant 1)-  pred x    = mkSub x (constant 1)+  succ      = defaultSucc+  pred      = defaultPred   toEnum    = defaultToEnum   fromEnum  = defaultFromEnum  instance P.Enum (Exp CUShort) where-  succ x    = mkAdd x (constant 1)-  pred x    = mkSub x (constant 1)+  succ      = defaultSucc+  pred      = defaultPred   toEnum    = defaultToEnum   fromEnum  = defaultFromEnum  instance P.Enum (Exp Half) where-  succ x    = mkAdd x (constant 1)-  pred x    = mkSub x (constant 1)+  succ      = defaultSucc+  pred      = defaultPred   toEnum    = defaultToEnum   fromEnum  = defaultFromEnum  instance P.Enum (Exp Float) where-  succ x    = mkAdd x (constant 1)-  pred x    = mkSub x (constant 1)+  succ      = defaultSucc+  pred      = defaultPred   toEnum    = defaultToEnum   fromEnum  = defaultFromEnum  instance P.Enum (Exp Double) where-  succ x    = mkAdd x (constant 1)-  pred x    = mkSub x (constant 1)+  succ      = defaultSucc+  pred      = defaultPred   toEnum    = defaultToEnum   fromEnum  = defaultFromEnum  instance P.Enum (Exp CFloat) where-  succ x    = mkAdd x (constant 1)-  pred x    = mkSub x (constant 1)+  succ      = defaultSucc+  pred      = defaultPred   toEnum    = defaultToEnum   fromEnum  = defaultFromEnum  instance P.Enum (Exp CDouble) where-  succ x    = mkAdd x (constant 1)-  pred x    = mkSub x (constant 1)+  succ      = defaultSucc+  pred      = defaultPred   toEnum    = defaultToEnum   fromEnum  = defaultFromEnum +defaultSucc :: Num a => Exp a -> Exp a+defaultSucc x = x + 1++defaultPred :: Num a => Exp a -> Exp a+defaultPred x = x - 1  defaultToEnum :: Int -> a defaultToEnum = preludeError "toEnum"
src/Data/Array/Accelerate/Classes/Eq.hs view
@@ -1,31 +1,49 @@-{-# LANGUAGE FlexibleContexts  #-}-{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE ConstraintKinds     #-}+{-# LANGUAGE FlexibleContexts    #-}+{-# LANGUAGE FlexibleInstances   #-}+{-# LANGUAGE GADTs               #-}+{-# LANGUAGE PatternSynonyms     #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TemplateHaskell     #-}+{-# LANGUAGE TypeApplications    #-}+{-# LANGUAGE TypeFamilies        #-}+{-# LANGUAGE TypeOperators       #-}+{-# LANGUAGE ViewPatterns        #-} {-# OPTIONS_GHC -fno-warn-orphans #-} -- | -- Module      : Data.Array.Accelerate.Classes.Eq--- Copyright   : [2016..2017] Manuel M T Chakravarty, Gabriele Keller, Trevor L. McDonell+-- Copyright   : [2016..2020] The Accelerate Team -- License     : BSD3 ----- Maintainer  : Trevor L. McDonell <tmcdonell@cse.unsw.edu.au>+-- Maintainer  : Trevor L. McDonell <trevor.mcdonell@gmail.com> -- Stability   : experimental -- Portability : non-portable (GHC extensions) --  module Data.Array.Accelerate.Classes.Eq ( +  Bool(..), pattern True_, pattern False_,   Eq(..),-  (&&),-  (||),+  (&&), (&&!),+  (||), (||!),   not,  ) where -import Data.Array.Accelerate.Array.Sugar+import Data.Array.Accelerate.AST.Idx+import Data.Array.Accelerate.Pattern+import Data.Array.Accelerate.Pattern.Bool import Data.Array.Accelerate.Smart+import Data.Array.Accelerate.Sugar.Elt+import Data.Array.Accelerate.Sugar.Shape import Data.Array.Accelerate.Type +import Data.Bool                                                    ( Bool(..) )+import Data.Char                                                    ( Char ) import Text.Printf-import Prelude                                                      ( String, error)+import Prelude                                                      ( ($), String, Num(..), show, error, return, concat, map, zipWith, foldr1, mapM )+import Language.Haskell.TH                                          hiding ( Exp )+import Language.Haskell.TH.Extra import qualified Prelude                                            as P  @@ -37,16 +55,43 @@ -- infixr 3 && (&&) :: Exp Bool -> Exp Bool -> Exp Bool-(&&) = mkLAnd+(&&) (Exp x) (Exp y) =+  mkExp $ SmartExp (Cond (SmartExp $ Prj PairIdxLeft x)+                         (SmartExp $ Prj PairIdxLeft y)+                         (SmartExp $ Const scalarTypeWord8 0))+          `Pair` SmartExp Nil +-- | Conjunction: True if both arguments are true. This is a strict version of+-- '(&&)': it will always evaluate both arguments, even when the first is false.+--+-- @since 1.3.0.0+--+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+(||) (Exp x) (Exp y) =+  mkExp $ SmartExp (Cond (SmartExp $ Prj PairIdxLeft x)+                         (SmartExp $ Const scalarTypeWord8 1)+                         (SmartExp $ Prj PairIdxLeft y))+          `Pair` SmartExp Nil ++-- | Disjunction: True if either argument is true. This is a strict version of+-- '(||)': it will always evaluate both arguments, even when the first is true.+--+-- @since 1.3.0.0+--+infixr 2 ||!+(||!) :: Exp Bool -> Exp Bool -> Exp Bool+(||!) = mkLOr+ -- | Logical negation -- not :: Exp Bool -> Exp Bool@@ -67,250 +112,103 @@   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+  _ == _ = True_+  _ /= _ = False_ -instance Eq CShort where-  (==) = mkEq-  (/=) = mkNEq+instance Eq Z where+  _ == _ = True_+  _ /= _ = False_ -instance Eq CUShort where-  (==) = mkEq-  (/=) = mkNEq+instance Eq sh => Eq (sh :. Int) where+  x == y = indexHead x == indexHead y && indexTail x == indexTail y+  x /= y = indexHead x /= indexHead y || indexTail x /= indexTail y  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 Half 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--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 p) => Eq (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p) where-  x == y = let (a1,b1,c1,d1,e1,f1,g1,h1,i1,j1,k1,l1,m1,n1,o1,p1) = untup16 x-               (a2,b2,c2,d2,e2,f2,g2,h2,i2,j2,k2,l2,m2,n2,o2,p2) = untup16 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 && p1 == p2-  x /= y = let (a1,b1,c1,d1,e1,f1,g1,h1,i1,j1,k1,l1,m1,n1,o1,p1) = untup16 x-               (a2,b2,c2,d2,e2,f2,g2,h2,i2,j2,k2,l2,m2,n2,o2,p2) = untup16 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 || p1 /= p2-+  x == y = mkCoerce x == (mkCoerce y :: Exp PrimBool)+  x /= y = mkCoerce x /= (mkCoerce y :: Exp PrimBool)  -- 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 Eq a => P.Eq (Exp a) where+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)++$(runQ $ do+    let+        integralTypes :: [Name]+        integralTypes =+          [ ''Int+          , ''Int8+          , ''Int16+          , ''Int32+          , ''Int64+          , ''Word+          , ''Word8+          , ''Word16+          , ''Word32+          , ''Word64+          ]++        floatingTypes :: [Name]+        floatingTypes =+          [ ''Half+          , ''Float+          , ''Double+          ]++        nonNumTypes :: [Name]+        nonNumTypes =+          [ ''Char+          ]++        cTypes :: [Name]+        cTypes =+          [ ''CInt+          , ''CUInt+          , ''CLong+          , ''CULong+          , ''CLLong+          , ''CULLong+          , ''CShort+          , ''CUShort+          , ''CChar+          , ''CUChar+          , ''CSChar+          , ''CFloat+          , ''CDouble+          ]++        mkPrim :: Name -> Q [Dec]+        mkPrim t =+          [d| instance Eq $(conT t) where+                (==) = mkEq+                (/=) = mkNEq+            |]++        mkTup :: Int -> Q [Dec]+        mkTup n =+          let+              xs      = [ mkName ('x':show i) | i <- [0 .. n-1] ]+              ys      = [ mkName ('y':show i) | i <- [0 .. n-1] ]+              cst     = tupT (map (\x -> [t| Eq $(varT x) |]) xs)+              res     = tupT (map varT xs)+              pat vs  = conP (mkName ('T':show n)) (map varP vs)+          in+          [d| instance ($cst) => Eq $res where+                $(pat xs) == $(pat ys) = $(foldr1 (\vs v -> [| $vs && $v |]) (zipWith (\x y -> [| $x == $y |]) (map varE xs) (map varE ys)))+                $(pat xs) /= $(pat ys) = $(foldr1 (\vs v -> [| $vs || $v |]) (zipWith (\x y -> [| $x /= $y |]) (map varE xs) (map varE ys)))+            |]++    is <- mapM mkPrim integralTypes+    fs <- mapM mkPrim floatingTypes+    ns <- mapM mkPrim nonNumTypes+    cs <- mapM mkPrim cTypes+    ts <- mapM mkTup [2..16]+    return $ concat (concat [is,fs,ns,cs,ts])+ ) 
src/Data/Array/Accelerate/Classes/Floating.hs view
@@ -1,13 +1,15 @@ {-# LANGUAGE ConstraintKinds   #-} {-# LANGUAGE FlexibleContexts  #-} {-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE TypeApplications  #-}+{-# LANGUAGE TypeFamilies      #-} {-# OPTIONS_GHC -fno-warn-orphans #-} -- | -- Module      : Data.Array.Accelerate.Classes.Floating--- Copyright   : [2016..2017] Manuel M T Chakravarty, Gabriele Keller, Trevor L. McDonell+-- Copyright   : [2016..2020] The Accelerate Team -- License     : BSD3 ----- Maintainer  : Trevor L. McDonell <tmcdonell@cse.unsw.edu.au>+-- Maintainer  : Trevor L. McDonell <trevor.mcdonell@gmail.com> -- Stability   : experimental -- Portability : non-portable (GHC extensions) --@@ -102,7 +104,7 @@   logBase = mkLogBase  instance P.Floating (Exp CFloat) where-  pi      = mkPi+  pi      = mkBitcast (mkPi @Float)   sin     = mkSin   cos     = mkCos   tan     = mkTan@@ -122,7 +124,7 @@   logBase = mkLogBase  instance P.Floating (Exp CDouble) where-  pi      = mkPi+  pi      = mkBitcast (mkPi @Double)   sin     = mkSin   cos     = mkCos   tan     = mkTan
src/Data/Array/Accelerate/Classes/Fractional.hs view
@@ -1,13 +1,14 @@ {-# LANGUAGE ConstraintKinds   #-} {-# LANGUAGE FlexibleContexts  #-} {-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE TypeFamilies      #-} {-# OPTIONS_GHC -fno-warn-orphans #-} -- | -- Module      : Data.Array.Accelerate.Classes.Fractional--- Copyright   : [2016..2017] Manuel M T Chakravarty, Gabriele Keller, Trevor L. McDonell+-- Copyright   : [2016..2020] The Accelerate Team -- License     : BSD3 ----- Maintainer  : Trevor L. McDonell <tmcdonell@cse.unsw.edu.au>+-- Maintainer  : Trevor L. McDonell <trevor.mcdonell@gmail.com> -- Stability   : experimental -- Portability : non-portable (GHC extensions) --@@ -15,7 +16,7 @@ module Data.Array.Accelerate.Classes.Fractional (    Fractional,-  (P./), P.recip, fromRational,+  (P./), P.recip, P.fromRational,  ) where @@ -24,7 +25,7 @@  import Data.Array.Accelerate.Classes.Num -import Prelude                                                      ( Rational, (.) )+import Prelude                                                      ( (.) ) import qualified Prelude                                            as P  @@ -35,8 +36,8 @@ -- version where the return type is fixed to an 'Exp' term in order to improve -- type checking in Accelerate modules when @RebindableSyntax@ is enabled. ---fromRational :: Fractional a => Rational -> Exp a-fromRational = P.fromRational+-- fromRational :: Fractional a => Rational -> Exp a+-- fromRational = P.fromRational   -- | Fractional numbers, supporting real division
src/Data/Array/Accelerate/Classes/FromIntegral.hs view
@@ -1,4 +1,3 @@-{-# LANGUAGE CPP                   #-} {-# LANGUAGE ConstraintKinds       #-} {-# LANGUAGE FlexibleContexts      #-} {-# LANGUAGE MonoLocalBinds        #-}@@ -6,10 +5,10 @@ {-# LANGUAGE TemplateHaskell       #-} -- | -- Module      : Data.Array.Accelerate.Classes.FromIntegral--- Copyright   : [2016..2017] Manuel M T Chakravarty, Gabriele Keller, Trevor L. McDonell+-- Copyright   : [2016..2020] The Accelerate Team -- License     : BSD3 ----- Maintainer  : Trevor L. McDonell <tmcdonell@cse.unsw.edu.au>+-- Maintainer  : Trevor L. McDonell <trevor.mcdonell@gmail.com> -- Stability   : experimental -- Portability : non-portable (GHC extensions) --@@ -55,24 +54,16 @@         -- 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             -- This is what a constructor such as IntegralNumType will be reified             -- as prior to GHC 8.4...             dig (NormalC _ [(_, AppT (ConT n) (VarT _))])               = digItOut n-#if __GLASGOW_HASKELL__ < 800-            dig (ForallC _ _ (NormalC _ [(_, AppT (ConT _) (ConT n))])) = return [n]-#else             -- ...but this is what IntegralNumType will be reified as on GHC 8.4             -- and later, after the changes described in             -- https://ghc.haskell.org/trac/ghc/wiki/Migration/8.4#TemplateHaskellreificationchangesforGADTs             dig (ForallC _ _ (GadtC _ [(_, AppT (ConT n) (VarT _))] _)) = digItOut n             dig (GadtC _ _ (AppT (ConT _) (ConT n)))                    = return [n]-#endif             dig _ = error "Unexpected case generating FromIntegral instances"             --           concat `fmap` mapM dig cons@@ -81,7 +72,9 @@         thFromIntegral a b =           let               ty  = AppT (AppT (ConT (mkName "FromIntegral")) (ConT a)) (ConT b)-              dec = ValD (VarP (mkName "fromIntegral")) (NormalB (VarE (mkName "mkFromIntegral"))) []+              dec = ValD (VarP (mkName "fromIntegral")) (NormalB (VarE (mkName f))) []+              f | a == b    = "id"+                | otherwise = "mkFromIntegral"           in           instanceD (return []) (return ty) [return dec]     --
src/Data/Array/Accelerate/Classes/Integral.hs view
@@ -2,13 +2,14 @@ {-# LANGUAGE FlexibleContexts  #-} {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE MonoLocalBinds    #-}+{-# LANGUAGE TypeFamilies      #-} {-# OPTIONS_GHC -fno-warn-orphans #-} -- | -- Module      : Data.Array.Accelerate.Classes.Integral--- Copyright   : [2016..2017] Manuel M T Chakravarty, Gabriele Keller, Trevor L. McDonell+-- Copyright   : [2016..2020] The Accelerate Team -- License     : BSD3 ----- Maintainer  : Trevor L. McDonell <tmcdonell@cse.unsw.edu.au>+-- Maintainer  : Trevor L. McDonell <trevor.mcdonell@gmail.com> -- Stability   : experimental -- Portability : non-portable (GHC extensions) --@@ -29,7 +30,9 @@ import Data.Array.Accelerate.Type  import Data.Array.Accelerate.Classes.Enum-import Data.Array.Accelerate.Classes.Real+import Data.Array.Accelerate.Classes.Num+import Data.Array.Accelerate.Classes.Ord+import Data.Array.Accelerate.Classes.Real                           ()  import Prelude                                                      ( error ) import qualified Prelude                                            as P@@ -37,7 +40,7 @@  -- | Integral numbers, supporting integral division ---type Integral a = (Enum a, Real a, P.Integral (Exp a))+type Integral a = (Enum a, Ord a, Num a, P.Integral (Exp a))   instance P.Integral (Exp Int) where
src/Data/Array/Accelerate/Classes/Num.hs view
@@ -1,13 +1,14 @@ {-# LANGUAGE ConstraintKinds   #-} {-# LANGUAGE FlexibleContexts  #-} {-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE TypeFamilies      #-} {-# OPTIONS_GHC -fno-warn-orphans #-} -- | -- Module      : Data.Array.Accelerate.Classes.Num--- Copyright   : [2016..2017] Manuel M T Chakravarty, Gabriele Keller, Trevor L. McDonell+-- Copyright   : [2016..2020] The Accelerate Team -- License     : BSD3 ----- Maintainer  : Trevor L. McDonell <tmcdonell@cse.unsw.edu.au>+-- Maintainer  : Trevor L. McDonell <trevor.mcdonell@gmail.com> -- Stability   : experimental -- Portability : non-portable (GHC extensions) --@@ -15,15 +16,15 @@ module Data.Array.Accelerate.Classes.Num (    Num,-  (P.+), (P.-), (P.*), P.negate, P.abs, P.signum, fromInteger,+  (P.+), (P.-), (P.*), P.negate, P.abs, P.signum, P.fromInteger,  ) where -import Data.Array.Accelerate.Array.Sugar+import Data.Array.Accelerate.Sugar.Elt import Data.Array.Accelerate.Smart import Data.Array.Accelerate.Type -import Prelude                                                      ( Integer, (.) )+import Prelude                                                      ( (.) ) import qualified Prelude                                            as P  @@ -57,8 +58,8 @@ -- version where the return type is fixed to an 'Exp' term in order to improve -- type checking in Accelerate modules when @RebindableSyntax@ is enabled. ---fromInteger :: Num a => Integer -> Exp a-fromInteger = P.fromInteger+-- fromInteger :: Num a => Integer -> Exp a+-- fromInteger = P.fromInteger   -- | Basic numeric class@@ -272,4 +273,3 @@   abs         = mkAbs   signum      = mkSig   fromInteger = constant . P.fromInteger-
src/Data/Array/Accelerate/Classes/Ord.hs view
@@ -1,14 +1,22 @@-{-# LANGUAGE FlexibleContexts  #-}-{-# LANGUAGE FlexibleInstances #-}-{-# LANGUAGE RebindableSyntax  #-}-{-# LANGUAGE TypeFamilies      #-}+{-# LANGUAGE ConstraintKinds     #-}+{-# LANGUAGE FlexibleContexts    #-}+{-# LANGUAGE FlexibleInstances   #-}+{-# LANGUAGE GADTs               #-}+{-# LANGUAGE PatternSynonyms     #-}+{-# LANGUAGE RebindableSyntax    #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TemplateHaskell     #-}+{-# LANGUAGE TypeApplications    #-}+{-# LANGUAGE TypeFamilies        #-}+{-# LANGUAGE TypeOperators       #-}+{-# LANGUAGE ViewPatterns        #-} {-# OPTIONS_GHC -fno-warn-orphans #-} -- | -- Module      : Data.Array.Accelerate.Classes.Ord--- Copyright   : [2016..2017] Manuel M T Chakravarty, Gabriele Keller, Trevor L. McDonell+-- Copyright   : [2016..2020] The Accelerate Team -- License     : BSD3 ----- Maintainer  : Trevor L. McDonell <tmcdonell@cse.unsw.edu.au>+-- Maintainer  : Trevor L. McDonell <trevor.mcdonell@gmail.com> -- Stability   : experimental -- Portability : non-portable (GHC extensions) --@@ -16,18 +24,29 @@ module Data.Array.Accelerate.Classes.Ord (    Ord(..),-  Ordering(..),+  Ordering(..), pattern LT_, pattern EQ_, pattern GT_,  ) where -import Data.Array.Accelerate.Array.Sugar+import Data.Array.Accelerate.Analysis.Match+import Data.Array.Accelerate.Pattern+import Data.Array.Accelerate.Pattern.Ordering+import Data.Array.Accelerate.Representation.Tag import Data.Array.Accelerate.Smart+import Data.Array.Accelerate.Sugar.Elt+import Data.Array.Accelerate.Sugar.Shape import Data.Array.Accelerate.Type -import Data.Array.Accelerate.Classes.Eq+-- We must hide (==), as that operator is used for the literals 0, 1 and 2 in the pattern synonyms for Ordering.+-- As RebindableSyntax is enabled, a literal pattern is compiled to a call to (==), meaning that the Prelude.(==) should be in scope as (==).+import Data.Array.Accelerate.Classes.Eq                             hiding ( (==) )+import qualified Data.Array.Accelerate.Classes.Eq                   as A +import Data.Char+import Language.Haskell.TH                                          hiding ( Exp )+import Language.Haskell.TH.Extra+import Prelude                                                      ( ($), (>>=), Ordering(..), Num(..), Maybe(..), String, show, error, unlines, return, concat, map, mapM ) import Text.Printf-import Prelude                                                      ( ($), (.), Ordering(..), String, error, unlines ) import qualified Prelude                                            as P  @@ -48,23 +67,23 @@   max     :: Exp a -> Exp a -> Exp a   compare :: Exp a -> Exp a -> Exp Ordering -  x <  y = if compare x y == constant LT then constant True  else constant False-  x <= y = if compare x y == constant GT then constant False else constant True-  x >  y = if compare x y == constant GT then constant True  else constant False-  x >= y = if compare x y == constant LT then constant False else constant True+  x <  y = if compare x y A.== constant LT then constant True  else constant False+  x <= y = if compare x y A.== constant GT then constant False else constant True+  x >  y = if compare x y A.== constant GT then constant True  else constant False+  x >= y = if compare x y A.== constant LT then constant False else constant True    min x y = if x <= y then x else y   max x y = if x <= y then y else x    compare x y =-    if x == y then constant EQ else-    if x <= y then constant LT-              else constant GT+    if x A.== y then constant EQ else+    if x   <= y then constant LT+                else constant GT  -- Local redefinition for use with RebindableSyntax (pulled forward from Prelude.hs) -- ifThenElse :: Elt a => Exp Bool -> Exp a -> Exp a -> Exp a-ifThenElse = Exp $$$ Cond+ifThenElse (Exp c) (Exp x) (Exp y) = Exp $ SmartExp $ Cond (mkCoerce' c) x y  instance Ord () where   (<)     _ _ = constant False@@ -75,445 +94,37 @@   max     _ _ = constant ()   compare _ _ = constant EQ -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 Half 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')---type instance EltRepr Ordering = Int8+instance Ord Z where+  (<)  _ _ = constant False+  (>)  _ _ = constant False+  (<=) _ _ = constant True+  (>=) _ _ = constant True+  min  _ _ = constant Z+  max  _ _ = constant Z -instance Elt Ordering where-  eltType _ = TypeRscalar scalarType-  fromElt = P.fromIntegral . P.fromEnum-  toElt   = P.toEnum . P.fromIntegral+instance Ord sh => Ord (sh :. Int) where+  x <= y = indexHead x <= indexHead y && indexTail x <= indexTail y+  x >= y = indexHead x >= indexHead y && indexTail x >= indexTail y+  x < y  = indexHead x < indexHead y+        && case matchTypeR (eltR @sh) (eltR @Z) of+             Just Refl -> constant True+             Nothing   -> indexTail x < indexTail y+  x > y  = indexHead x > indexHead y+        && case matchTypeR (eltR @sh) (eltR @Z) of+             Just Refl -> constant True+             Nothing   -> indexTail x > indexTail y  instance Eq Ordering where-  x == y = mkBitcast x == (mkBitcast y :: Exp Int8)-  x /= y = mkBitcast x /= (mkBitcast y :: Exp Int8)+  x == y = mkCoerce x A.== (mkCoerce y :: Exp TAG)+  x /= y = mkCoerce x A./= (mkCoerce y :: Exp TAG)  instance Ord Ordering where-  x < y   = mkBitcast x < (mkBitcast y :: Exp Int8)-  x > y   = mkBitcast x > (mkBitcast y :: Exp Int8)-  x <= y  = mkBitcast x <= (mkBitcast y :: Exp Int8)-  x >= y  = mkBitcast x >= (mkBitcast y :: Exp Int8)-  min x y = mkBitcast $ min (mkBitcast x) (mkBitcast y :: Exp Int8)-  max x y = mkBitcast $ max (mkBitcast x) (mkBitcast y :: Exp Int8)+  x < y   = mkCoerce x < (mkCoerce y :: Exp TAG)+  x > y   = mkCoerce x > (mkCoerce y :: Exp TAG)+  x <= y  = mkCoerce x <= (mkCoerce y :: Exp TAG)+  x >= y  = mkCoerce x >= (mkCoerce y :: Exp TAG)+  min x y = mkCoerce $ min (mkCoerce x) (mkCoerce y :: Exp TAG)+  max x y = mkCoerce $ max (mkCoerce x) (mkCoerce y :: Exp TAG)   -- Instances of 'Prelude.Ord' (mostly) don't make sense with the standard@@ -541,4 +152,104 @@             , "constraints for subsequent classes in the standard Haskell numeric"             , "hierarchy."             ]++$(runQ $ do+    let+        integralTypes :: [Name]+        integralTypes =+          [ ''Int+          , ''Int8+          , ''Int16+          , ''Int32+          , ''Int64+          , ''Word+          , ''Word8+          , ''Word16+          , ''Word32+          , ''Word64+          ]++        floatingTypes :: [Name]+        floatingTypes =+          [ ''Half+          , ''Float+          , ''Double+          ]++        nonNumTypes :: [Name]+        nonNumTypes =+          [ ''Char+          ]++        cTypes :: [Name]+        cTypes =+          [ ''CInt+          , ''CUInt+          , ''CLong+          , ''CULong+          , ''CLLong+          , ''CULLong+          , ''CShort+          , ''CUShort+          , ''CChar+          , ''CUChar+          , ''CSChar+          , ''CFloat+          , ''CDouble+          ]++        mkPrim :: Name -> Q [Dec]+        mkPrim t =+          [d| instance Ord $(conT t) where+                (<)  = mkLt+                (>)  = mkGt+                (<=) = mkLtEq+                (>=) = mkGtEq+                min  = mkMin+                max  = mkMax+            |]++        mkLt' :: [ExpQ] -> [ExpQ] -> ExpQ+        mkLt' [x] [y]       = [| $x < $y |]+        mkLt' (x:xs) (y:ys) = [| $x < $y || ( $x A.== $y && $(mkLt' xs ys) ) |]+        mkLt' _      _      = error "mkLt'"++        mkGt' :: [ExpQ] -> [ExpQ] -> ExpQ+        mkGt' [x]    [y]    = [| $x > $y |]+        mkGt' (x:xs) (y:ys) = [| $x > $y || ( $x A.== $y && $(mkGt' xs ys) ) |]+        mkGt' _      _      = error "mkGt'"++        mkLtEq' :: [ExpQ] -> [ExpQ] -> ExpQ+        mkLtEq' [x] [y]       = [| $x < $y |]+        mkLtEq' (x:xs) (y:ys) = [| $x < $y || ( $x A.== $y && $(mkLtEq' xs ys) ) |]+        mkLtEq' _      _      = error "mkLtEq'"++        mkGtEq' :: [ExpQ] -> [ExpQ] -> ExpQ+        mkGtEq' [x]    [y]    = [| $x > $y |]+        mkGtEq' (x:xs) (y:ys) = [| $x > $y || ( $x A.== $y && $(mkGtEq' xs ys) ) |]+        mkGtEq' _      _      = error "mkGtEq'"++        mkTup :: Int -> Q [Dec]+        mkTup n =+          let+              xs      = [ mkName ('x':show i) | i <- [0 .. n-1] ]+              ys      = [ mkName ('y':show i) | i <- [0 .. n-1] ]+              cst     = tupT (map (\x -> [t| Ord $(varT x) |]) xs)+              res     = tupT (map varT xs)+              pat vs  = conP (mkName ('T':show n)) (map varP vs)+          in+          [d| instance $cst => Ord $res where+                $(pat xs) <  $(pat ys) = $( mkLt' (map varE xs) (map varE ys) )+                $(pat xs) >  $(pat ys) = $( mkGt' (map varE xs) (map varE ys) )+                $(pat xs) >= $(pat ys) = $( mkGtEq' (map varE xs) (map varE ys) )+                $(pat xs) <= $(pat ys) = $( mkLtEq' (map varE xs) (map varE ys) )+            |]++    is <- mapM mkPrim integralTypes+    fs <- mapM mkPrim floatingTypes+    ns <- mapM mkPrim nonNumTypes+    cs <- mapM mkPrim cTypes+    ts <- mapM mkTup [2..16]+    return $ concat (concat [is,fs,ns,cs,ts])+ ) 
+ src/Data/Array/Accelerate/Classes/Rational.hs view
@@ -0,0 +1,97 @@+{-# LANGUAGE FlexibleContexts #-}+-- |+-- Module      : Data.Array.Accelerate.Classes.Rational+-- Copyright   : [2016..2020] The Accelerate Team+-- License     : BSD3+--+-- Maintainer  : Trevor L. McDonell <trevor.mcdonell@gmail.com>+-- Stability   : experimental+-- Portability : non-portable (GHC extensions)+--++module Data.Array.Accelerate.Classes.Rational (++  Rational(..)++) where++import Data.Array.Accelerate.Data.Ratio+import Data.Array.Accelerate.Data.Bits++import Data.Array.Accelerate.Language+import Data.Array.Accelerate.Pattern+import Data.Array.Accelerate.Smart+import Data.Array.Accelerate.Type++import Data.Array.Accelerate.Classes.Eq+import Data.Array.Accelerate.Classes.FromIntegral+import Data.Array.Accelerate.Classes.Integral+import Data.Array.Accelerate.Classes.Num+import Data.Array.Accelerate.Classes.Ord+import Data.Array.Accelerate.Classes.RealFloat++import Prelude                                            ( ($) )+++-- | Numbers which can be expressed as the quotient of two integers.+--+-- Accelerate does not have an arbitrary precision Integer type, however+-- fixed-length large integers are provide by the @accelerate-bignum@+-- package.+--+class (Num a, Ord a) => Rational a where+  -- | Convert a number to the quotient of two integers+  --+  toRational :: (FromIntegral Int64 b, Integral b) => Exp a -> Exp (Ratio b)++instance Rational Int    where toRational = integralToRational+instance Rational Int8   where toRational = integralToRational+instance Rational Int16  where toRational = integralToRational+instance Rational Int32  where toRational = integralToRational+instance Rational Int64  where toRational = integralToRational+instance Rational Word   where toRational = integralToRational+instance Rational Word8  where toRational = integralToRational+instance Rational Word16 where toRational = integralToRational+instance Rational Word32 where toRational = integralToRational+instance Rational Word64 where toRational = integralToRational++instance Rational Half   where toRational = floatingToRational+instance Rational Float  where toRational = floatingToRational+instance Rational Double where toRational = floatingToRational+++integralToRational+    :: (Integral a, Integral b, FromIntegral a Int64, FromIntegral Int64 b)+    => Exp a+    -> Exp (Ratio b)+integralToRational x = fromIntegral (fromIntegral x :: Exp Int64) :% 1++floatingToRational+    :: (RealFloat a, Integral b, FromIntegral Int64 b)+    => Exp a+    -> Exp (Ratio b)+floatingToRational x = fromIntegral u :% fromIntegral v+  where+    (m, e) = decodeFloat x+    (n, d) = elimZeros m (negate e)+    u :% v = cond (e >= 0)       ((m `shiftL` e) :% 1) $+             cond (m .&. 1 == 0) (n :% shiftL 1 d)     $+                                 (m :% shiftL 1 (negate e))++-- Stolen from GHC.Float.ConversionUtils+--+elimZeros :: Exp Int64 -> Exp Int -> (Exp Int64, Exp Int) -- Integer+elimZeros x y = (u, v)+  where+    T3 _ u v = while (\(T3 p _ _) -> p) elim (T3 moar x y)+    kthxbai  = constant False+    moar     = constant True++    elim :: Exp (Bool, Int64, Int) -> Exp (Bool, Int64, Int)+    elim (T3 _ n e) =+      let t = countTrailingZeros (fromIntegral n :: Exp Word8)+      in+      cond (e <= t) (T3 kthxbai (shiftR n e) 0)     $+      cond (t <  8) (T3 kthxbai (shiftR n t) (e-t)) $+                    (T3 moar    (shiftR n 8) (e-8))+
src/Data/Array/Accelerate/Classes/Real.hs view
@@ -7,10 +7,10 @@ {-# OPTIONS_GHC -fno-warn-orphans         #-} -- | -- Module      : Data.Array.Accelerate.Classes.Real--- Copyright   : [2016..2017] Manuel M T Chakravarty, Gabriele Keller, Trevor L. McDonell+-- Copyright   : [2016..2020] The Accelerate Team -- License     : BSD3 ----- Maintainer  : Trevor L. McDonell <tmcdonell@cse.unsw.edu.au>+-- Maintainer  : Trevor L. McDonell <trevor.mcdonell@gmail.com> -- Stability   : experimental -- Portability : non-portable (GHC extensions) --
src/Data/Array/Accelerate/Classes/RealFloat.hs view
@@ -4,15 +4,16 @@ {-# LANGUAGE FlexibleInstances   #-} {-# LANGUAGE NoImplicitPrelude   #-} {-# LANGUAGE ScopedTypeVariables #-}-{-# LANGUAGE TemplateHaskell     #-}+{-# LANGUAGE TypeApplications    #-}+{-# LANGUAGE TypeFamilies        #-} {-# LANGUAGE ViewPatterns        #-} {-# OPTIONS_GHC -fno-warn-orphans #-} -- | -- Module      : Data.Array.Accelerate.Classes.RealFloat--- Copyright   : [2016..2017] Manuel M T Chakravarty, Gabriele Keller, Trevor L. McDonell+-- Copyright   : [2016..2020] The Accelerate Team -- License     : BSD3 ----- Maintainer  : Trevor L. McDonell <tmcdonell@cse.unsw.edu.au>+-- Maintainer  : Trevor L. McDonell <trevor.mcdonell@gmail.com> -- Stability   : experimental -- Portability : non-portable (GHC extensions) --@@ -24,6 +25,8 @@ ) where  import Data.Array.Accelerate.Error+import Data.Array.Accelerate.Language                               ( cond, while )+import Data.Array.Accelerate.Pattern import Data.Array.Accelerate.Smart import Data.Array.Accelerate.Type @@ -59,7 +62,7 @@   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)+                     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@@ -75,20 +78,20 @@   -- | Corresponds to the second component of 'decodeFloat'   exponent       :: Exp a -> Exp Int   exponent x      = let (m,n) = decodeFloat x-                    in  Exp $ Cond (m == 0)-                                   0-                                   (n + floatDigits x)+                     in cond (m == 0)+                             0+                             (n + floatDigits x)    -- | Corresponds to the first component of 'decodeFloat'   significand    :: Exp a -> Exp a   significand x   = let (m,_) = decodeFloat x-                    in  encodeFloat m (negate (floatDigits x))+                     in encodeFloat m (negate (floatDigits x))    -- | Multiply a floating point number by an integer power of the radix   scaleFloat     :: Exp Int -> Exp a -> Exp a   scaleFloat k x  =-    Exp $ Cond (k == 0 || isFix) x-        $ encodeFloat m (n + clamp b)+    cond (k == 0 || isFix) x+         $ encodeFloat m (n + clamp b)     where       isFix = x == 0 || isNaN x || isInfinite x       (m,n) = decodeFloat x@@ -129,45 +132,48 @@   atan2           = mkAtan2   isNaN           = mkIsNaN   isInfinite      = mkIsInfinite-  floatRange _    = (-13,16)    -- bug in half <= 2.2.3-  isDenormalized  = ieee754 "isDenormalized" (ieee754_f16_is_denormalized . mkUnsafeCoerce)-  isNegativeZero  = ieee754 "isNegativeZero" (ieee754_f16_is_negative_zero . mkUnsafeCoerce)-  decodeFloat     = ieee754 "decodeFloat"    (\x -> let (m,n) = untup2 $ ieee754_f16_decode (mkUnsafeCoerce x)-                                                    in  (fromIntegral m, n))+  isDenormalized  = ieee754 "isDenormalized" (ieee754_f16_is_denormalized . mkBitcast)+  isNegativeZero  = ieee754 "isNegativeZero" (ieee754_f16_is_negative_zero . mkBitcast)+  decodeFloat     = ieee754 "decodeFloat"    (\x -> let T2 m n = ieee754_f16_decode (mkBitcast x)+                                                     in (fromIntegral m, n))  instance RealFloat Float where   atan2           = mkAtan2   isNaN           = mkIsNaN   isInfinite      = mkIsInfinite-  isDenormalized  = ieee754 "isDenormalized" (ieee754_f32_is_denormalized . mkUnsafeCoerce)-  isNegativeZero  = ieee754 "isNegativeZero" (ieee754_f32_is_negative_zero . mkUnsafeCoerce)-  decodeFloat     = ieee754 "decodeFloat"    (\x -> let (m,n) = untup2 $ ieee754_f32_decode (mkUnsafeCoerce x)-                                                    in  (fromIntegral m, n))+  isDenormalized  = ieee754 "isDenormalized" (ieee754_f32_is_denormalized . mkBitcast)+  isNegativeZero  = ieee754 "isNegativeZero" (ieee754_f32_is_negative_zero . mkBitcast)+  decodeFloat     = ieee754 "decodeFloat"    (\x -> let T2 m n = ieee754_f32_decode (mkBitcast x)+                                                     in (fromIntegral m, n))  instance RealFloat Double where   atan2           = mkAtan2   isNaN           = mkIsNaN   isInfinite      = mkIsInfinite-  isDenormalized  = ieee754 "isDenormalized" (ieee754_f64_is_denormalized . mkUnsafeCoerce)-  isNegativeZero  = ieee754 "isNegativeZero" (ieee754_f64_is_negative_zero . mkUnsafeCoerce)-  decodeFloat     = ieee754 "decodeFloat"    (untup2 . ieee754_f64_decode . mkUnsafeCoerce)+  isDenormalized  = ieee754 "isDenormalized" (ieee754_f64_is_denormalized . mkBitcast)+  isNegativeZero  = ieee754 "isNegativeZero" (ieee754_f64_is_negative_zero . mkBitcast)+  decodeFloat     = ieee754 "decodeFloat"    (\x -> let T2 m n = ieee754_f64_decode (mkBitcast x)+                                                     in (m, n))  instance RealFloat CFloat where   atan2           = mkAtan2-  isNaN           = mkIsNaN-  isInfinite      = mkIsInfinite-  isDenormalized  = ieee754 "isDenormalized" (ieee754_f32_is_denormalized . mkUnsafeCoerce)-  isNegativeZero  = ieee754 "isNegativeZero" (ieee754_f32_is_negative_zero . mkUnsafeCoerce)-  decodeFloat     = ieee754 "decodeFloat"    (\x -> let (m,n) = untup2 $ ieee754_f32_decode (mkUnsafeCoerce x)+  isNaN           = mkIsNaN . mkBitcast @Float+  isInfinite      = mkIsInfinite . mkBitcast @Float+  isDenormalized  = ieee754 "isDenormalized" (ieee754_f32_is_denormalized . mkBitcast)+  isNegativeZero  = ieee754 "isNegativeZero" (ieee754_f32_is_negative_zero . mkBitcast)+  decodeFloat     = ieee754 "decodeFloat"    (\x -> let T2 m n = ieee754_f32_decode (mkBitcast x)                                                     in  (fromIntegral m, n))+  encodeFloat x e = mkBitcast (encodeFloat @Float x e)  instance RealFloat CDouble where   atan2           = mkAtan2-  isNaN           = mkIsNaN-  isInfinite      = mkIsInfinite-  isDenormalized  = ieee754 "isDenormalized" (ieee754_f64_is_denormalized . mkUnsafeCoerce)-  isNegativeZero  = ieee754 "isNegativeZero" (ieee754_f64_is_negative_zero . mkUnsafeCoerce)-  decodeFloat     = ieee754 "decodeFloat"    (untup2 . ieee754_f64_decode . mkUnsafeCoerce)+  isNaN           = mkIsNaN . mkBitcast @Double+  isInfinite      = mkIsInfinite . mkBitcast @Double+  isDenormalized  = ieee754 "isDenormalized" (ieee754_f64_is_denormalized . mkBitcast)+  isNegativeZero  = ieee754 "isNegativeZero" (ieee754_f64_is_negative_zero . mkBitcast)+  decodeFloat     = ieee754 "decodeFloat"    (\x -> let T2 m n = ieee754_f64_decode (mkBitcast x)+                                                     in (m, n))+  encodeFloat x e = mkBitcast (encodeFloat @Double x e)   -- To satisfy superclass constraints@@ -194,10 +200,10 @@             ]  -ieee754 :: forall a b. P.RealFloat a => String -> (Exp a -> b) -> Exp a -> b+ieee754 :: forall a b. HasCallStack => P.RealFloat a => String -> (Exp a -> b) -> Exp a -> b ieee754 name f x   | P.isIEEE (undefined::a) = f x-  | otherwise               = $internalError (printf "RealFloat.%s" name) "Not implemented for non-IEEE floating point"+  | otherwise               = internalError (printf "%s: Not implemented for non-IEEE floating point" name)  -- From: ghc/libraries/base/cbits/primFloat.c -- ------------------------------------------@@ -310,21 +316,20 @@       exp1  = ((fromIntegral high1 `unsafeShiftR` 10) .&. 0x1F) + _HMINEXP       exp2  = exp1 + 1 -      (high3, exp3)-            = untup2-            $ Exp $ Cond (exp1 /= _HMINEXP)-                         -- don't add hidden bit to denorms-                         (tup2 (high2 .|. _HHIGHBIT, exp1))-                         -- a denorm, normalise the mantissa-                         (Exp $ While (\(untup2 -> (h,_)) -> (h .&. _HHIGHBIT) /= 0 )-                                      (\(untup2 -> (h,e)) -> tup2 (h `unsafeShiftL` 1, e-1))-                                      (tup2 (high2, exp2)))+      T2 high3 exp3+            = cond (exp1 /= _HMINEXP)+                   -- don't add hidden bit to denorms+                   (T2 (high2 .|. _HHIGHBIT) exp1)+                   -- a denorm, normalise the mantissa+                   (while (\(T2 h _) -> (h .&. _HHIGHBIT) /= 0 )+                          (\(T2 h e) -> T2 (h `unsafeShiftL` 1) (e-1))+                          (T2 high2 exp2)) -      high4 = Exp $ Cond (fromIntegral i < (0 :: Exp Int16)) (-high3) high3+      high4 = cond (fromIntegral i < (0 :: Exp Int16)) (-high3) high3   in-  Exp $ Cond (high1 .&. complement _HMSBIT == 0)-             (tup2 (0,0))-             (tup2 (high4, exp3))+  cond (high1 .&. complement _HMSBIT == 0)+       (T2 0 0)+       (T2 high4 exp3)   -- From: ghc/rts/StgPrimFloat.c@@ -345,27 +350,26 @@       exp1  = ((fromIntegral high1 `unsafeShiftR` 23) .&. 0xFF) + _FMINEXP       exp2  = exp1 + 1 -      (high3, exp3)-            = untup2-            $ Exp $ Cond (exp1 /= _FMINEXP)-                         -- don't add hidden bit to denorms-                         (tup2 (high2 .|. _FHIGHBIT, exp1))-                         -- a denorm, normalise the mantissa-                         (Exp $ While (\(untup2 -> (h,_)) -> (h .&. _FHIGHBIT) /= 0 )-                                      (\(untup2 -> (h,e)) -> tup2 (h `unsafeShiftL` 1, e-1))-                                      (tup2 (high2, exp2)))+      T2 high3 exp3+            = cond (exp1 /= _FMINEXP)+                   -- don't add hidden bit to denorms+                   (T2 (high2 .|. _FHIGHBIT) exp1)+                   -- a denorm, normalise the mantissa+                   (while (\(T2 h _) -> (h .&. _FHIGHBIT) /= 0 )+                          (\(T2 h e) -> T2 (h `unsafeShiftL` 1) (e-1))+                          (T2 high2 exp2)) -      high4 = Exp $ Cond (fromIntegral i < (0 :: Exp Int32)) (-high3) high3+      high4 = cond (fromIntegral i < (0 :: Exp Int32)) (-high3) high3   in-  Exp $ Cond (high1 .&. complement _FMSBIT == 0)-             (tup2 (0,0))-             (tup2 (high4, exp3))+  cond (high1 .&. complement _FMSBIT == 0)+       (T2 0 0)+       (T2 high4 exp3)   ieee754_f64_decode :: Exp Word64 -> Exp (Int64, Int) ieee754_f64_decode i =-  let (s,h,l,e) = untup4 $ ieee754_f64_decode2 i-  in  tup2 (fromIntegral s * (fromIntegral h `unsafeShiftL` 32 .|. fromIntegral l), e)+  let T4 s h l e = ieee754_f64_decode2 i+   in T2 (fromIntegral s * (fromIntegral h `unsafeShiftL` 32 .|. fromIntegral l)) e  ieee754_f64_decode2 :: Exp Word64 -> Exp (Int, Word32, Word32, Int) ieee754_f64_decode2 i =@@ -380,26 +384,25 @@       high  = fromIntegral (i `unsafeShiftR` 32)        iexp  = (fromIntegral ((high `unsafeShiftR` 20) .&. 0x7FF) + _DMINEXP)-      sign = Exp $ Cond (fromIntegral i < (0 :: Exp Int64)) (-1) 1+      sign = cond (fromIntegral i < (0 :: Exp Int64)) (-1) 1        high2 = high .&. (_DHIGHBIT - 1)       iexp2 = iexp + 1 -      (hi,lo,ie)-            = untup3-            $ Exp $ Cond (iexp2 /= _DMINEXP)-                         -- don't add hidden bit to denorms-                         (tup3 (high2 .|. _DHIGHBIT, low, iexp))-                         -- a denorm, nermalise the mantissa-                         (Exp $ While (\(untup3 -> (h,_,_)) -> (h .&. _DHIGHBIT) /= 0)-                                      (\(untup3 -> (h,l,e)) ->-                                        let h1 = h `unsafeShiftL` 1-                                            h2 = Exp $ Cond ((l .&. _DMSBIT) /= 0) (h1+1) h1-                                        in  tup3 (h2, l `unsafeShiftL` 1, e-1))-                                      (tup3 (high2, low, iexp2)))+      T3 hi lo ie+            = cond (iexp2 /= _DMINEXP)+                   -- don't add hidden bit to denorms+                   (T3 (high2 .|. _DHIGHBIT) low iexp)+                   -- a denorm, nermalise the mantissa+                   (while (\(T3 h _ _) -> (h .&. _DHIGHBIT) /= 0)+                          (\(T3 h l e) ->+                            let h1 = h `unsafeShiftL` 1+                                h2 = cond ((l .&. _DMSBIT) /= 0) (h1+1) h1+                            in  T3 h2 (l `unsafeShiftL` 1) (e-1))+                          (T3 high2 low iexp2))    in-  Exp $ Cond (low == 0 && (high .&. (complement _DMSBIT)) == 0)-             (tup4 (1,0,0,0))-             (tup4 (sign,hi,lo,ie))+  cond (low == 0 && (high .&. (complement _DMSBIT)) == 0)+       (T4 1 0 0 0)+       (T4 sign hi lo ie) 
+ src/Data/Array/Accelerate/Classes/RealFloat.hs-boot view
@@ -0,0 +1,67 @@+{-# LANGUAGE DefaultSignatures #-}+{-# LANGUAGE FlexibleContexts  #-}+-- |+-- Module      : Data.Array.Accelerate.Classes.RealFloat+-- Copyright   : [2019..2020] The Accelerate Team+-- License     : BSD3+--+-- Maintainer  : Trevor L. McDonell <trevor.mcdonell@gmail.com>+-- Stability   : experimental+-- Portability : non-portable (GHC extensions)+--++module Data.Array.Accelerate.Classes.RealFloat+  where++import Data.Array.Accelerate.Smart+import Data.Array.Accelerate.Type++import Data.Array.Accelerate.Classes.Floating+import Data.Array.Accelerate.Classes.FromIntegral+import {-# SOURCE #-} Data.Array.Accelerate.Classes.RealFrac++import Prelude                                                      ( Bool )+import qualified Prelude                                            as P+++class (RealFrac a, Floating a) => RealFloat a where+  floatRadix     :: Exp a -> Exp Int64  -- Integer+  floatDigits    :: Exp a -> Exp Int+  floatRange     :: Exp a -> (Exp Int, Exp Int)+  decodeFloat    :: Exp a -> (Exp Int64, Exp Int)    -- Integer+  encodeFloat    :: Exp Int64 -> Exp Int -> Exp a    -- Integer+  exponent       :: Exp a -> Exp Int+  significand    :: Exp a -> Exp a+  scaleFloat     :: Exp Int -> Exp a -> Exp a+  isNaN          :: Exp a -> Exp Bool+  isInfinite     :: Exp a -> Exp Bool+  isDenormalized :: Exp a -> Exp Bool+  isNegativeZero :: Exp a -> Exp Bool+  isIEEE         :: Exp a -> Exp Bool+  atan2          :: Exp a -> Exp a -> Exp a++  exponent        = P.undefined+  significand     = P.undefined+  scaleFloat      = P.undefined++  default floatRadix  :: P.RealFloat a => Exp a -> Exp Int64+  floatRadix _    = P.undefined++  default floatDigits :: P.RealFloat a => Exp a -> Exp Int+  floatDigits _   = P.undefined++  default floatRange  :: P.RealFloat a => Exp a -> (Exp Int, Exp Int)+  floatRange _    = P.undefined++  default encodeFloat :: (FromIntegral Int a, FromIntegral Int64 a) => Exp Int64 -> Exp Int -> Exp a+  encodeFloat _ _ = P.undefined++  default isIEEE      :: P.RealFloat a => Exp a -> Exp Bool+  isIEEE _        = P.undefined++instance RealFloat Half+instance RealFloat Float+instance RealFloat Double+instance RealFloat CFloat+instance RealFloat CDouble+
src/Data/Array/Accelerate/Classes/RealFrac.hs view
@@ -1,15 +1,17 @@-{-# LANGUAGE ConstraintKinds   #-}-{-# LANGUAGE FlexibleContexts  #-}-{-# LANGUAGE FlexibleInstances #-}-{-# LANGUAGE MonoLocalBinds    #-}-{-# LANGUAGE NoImplicitPrelude #-}+{-# LANGUAGE AllowAmbiguousTypes #-}+{-# LANGUAGE FlexibleContexts    #-}+{-# LANGUAGE FlexibleInstances   #-}+{-# LANGUAGE GADTs               #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TypeApplications    #-}+{-# LANGUAGE TypeFamilies        #-} {-# OPTIONS_GHC -fno-warn-orphans #-} -- | -- Module      : Data.Array.Accelerate.Classes.RealFrac--- Copyright   : [2016..2017] Manuel M T Chakravarty, Gabriele Keller, Trevor L. McDonell+-- Copyright   : [2016..2020] The Accelerate Team -- License     : BSD3 ----- Maintainer  : Trevor L. McDonell <tmcdonell@cse.unsw.edu.au>+-- Maintainer  : Trevor L. McDonell <trevor.mcdonell@gmail.com> -- Stability   : experimental -- Portability : non-portable (GHC extensions) --@@ -21,39 +23,47 @@  ) where -import Data.Array.Accelerate.Array.Sugar+import Data.Array.Accelerate.Language                               ( (^), cond, even )+import Data.Array.Accelerate.Lift                                   ( unlift )+import Data.Array.Accelerate.Pattern+import Data.Array.Accelerate.Representation.Type import Data.Array.Accelerate.Smart+import Data.Array.Accelerate.Sugar.Elt import Data.Array.Accelerate.Type  import Data.Array.Accelerate.Classes.Eq+import Data.Array.Accelerate.Classes.Ord import Data.Array.Accelerate.Classes.Floating import Data.Array.Accelerate.Classes.Fractional+import Data.Array.Accelerate.Classes.FromIntegral+import Data.Array.Accelerate.Classes.Integral import Data.Array.Accelerate.Classes.Num-import Data.Array.Accelerate.Classes.Real import Data.Array.Accelerate.Classes.ToFloating+import {-# SOURCE #-} Data.Array.Accelerate.Classes.RealFloat       -- defaultProperFraction +import Data.Maybe import Text.Printf-import Prelude                                                      ( ($), String, error, unlines )+import Prelude                                                      ( ($), String, error, unlines, otherwise ) 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' :: (RealFrac a, FromIntegral Int64 b, Integral 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' :: (Floating a, RealFrac a, ToFloating Int64 a) => Exp a -> Exp a -> Exp a mod' n d = n - (toFloating f) * d   where-    f :: Exp Int+    f :: Exp Int64     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)+    :: (Floating a, RealFrac a, Integral b, FromIntegral Int64 b, ToFloating b a)     => Exp a     -> Exp a     -> (Exp b, Exp a)@@ -64,8 +74,8 @@  -- | Extracting components of fractions. ---class (Real a, Fractional a) => RealFrac a where-  -- The function 'properFraction' takes a real fractional number @x@ and+class (Ord 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@@ -75,7 +85,7 @@   --   -- 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)+  properFraction :: (Integral b, FromIntegral Int64 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:@@ -94,71 +104,160 @@   -- 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+  truncate :: (Integral b, FromIntegral Int64 b) => Exp a -> Exp b+  truncate = defaultTruncate    -- | @'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+  round    :: (Integral b, FromIntegral Int64 b) => Exp a -> Exp b+  round    = defaultRound    -- | @'ceiling' x@ returns the least integer not less than @x@-  ceiling        :: (Elt b, IsIntegral b) => Exp a -> Exp b+  ceiling  :: (Integral b, FromIntegral Int64 b) => Exp a -> Exp b+  ceiling  = defaultCeiling    -- | @'floor' x@ returns the greatest integer not greater than @x@-  floor          :: (Elt b, IsIntegral b) => Exp a -> Exp b-+  floor    :: (Integral b, FromIntegral Int64 b) => Exp a -> Exp b+  floor    = defaultFloor  instance RealFrac Half where   properFraction  = defaultProperFraction-  truncate        = mkTruncate-  round           = mkRound-  ceiling         = mkCeiling-  floor           = mkFloor  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+  truncate        = defaultTruncate+  round           = defaultRound+  ceiling         = defaultCeiling+  floor           = defaultFloor  instance RealFrac CDouble where   properFraction  = defaultProperFraction-  truncate        = mkTruncate-  round           = mkRound-  ceiling         = mkCeiling-  floor           = mkFloor+  truncate        = defaultTruncate+  round           = defaultRound+  ceiling         = defaultCeiling+  floor           = defaultFloor   -- 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 b a, RealFrac a, IsIntegral b, Num b, Floating a)+--     => Exp a+--     -> (Exp b, Exp a)+-- defaultProperFraction x =+--   unlift $ Exp+--          $ Cond (x == 0) (tup2 (0, 0))+--                          (tup2 (n, f))+--   where+--     n = truncate x+--     f = x - toFloating n+ 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))+    :: (RealFloat a, FromIntegral Int64 b, Integral b)+    => Exp a+    -> (Exp b, Exp a)+defaultProperFraction x+  = unlift+  $ cond (n >= 0)+      (T2 (fromIntegral m * (2 ^ n)) 0.0)+      (T2 (fromIntegral q) (encodeFloat r n))   where-    n = truncate x-    f = x - toFloating n+    (m, n) = decodeFloat x+    (q, r) = quotRem m (2 ^ (negate n)) +defaultTruncate :: forall a b. (RealFrac a, Integral b, FromIntegral Int64 b) => Exp a -> Exp b+defaultTruncate x+  | Just IsFloatingDict <- isFloating @a+  , Just IsIntegralDict <- isIntegral @b+  = mkTruncate x+  --+  | otherwise+  = let (n, _) = properFraction x in n +defaultCeiling :: forall a b. (RealFrac a, Integral b, FromIntegral Int64 b) => Exp a -> Exp b+defaultCeiling x+  | Just IsFloatingDict <- isFloating @a+  , Just IsIntegralDict <- isIntegral @b+  = mkCeiling x+  --+  | otherwise+  = let (n, r) = properFraction x in cond (r > 0) (n+1) n++defaultFloor :: forall a b. (RealFrac a, Integral b, FromIntegral Int64 b) => Exp a -> Exp b+defaultFloor x+  | Just IsFloatingDict <- isFloating @a+  , Just IsIntegralDict <- isIntegral @b+  = mkFloor x+  --+  | otherwise+  = let (n, r) = properFraction x in cond (r < 0) (n-1) n++defaultRound :: forall a b. (RealFrac a, Integral b, FromIntegral Int64 b) => Exp a -> Exp b+defaultRound x+  | Just IsFloatingDict <- isFloating @a+  , Just IsIntegralDict <- isIntegral @b+  = mkRound x+  --+  | otherwise+  = let (n, r)    = properFraction x+        m         = cond (r < 0.0) (n-1) (n+1)+        half_down = abs r - 0.5+        p         = compare half_down 0.0+    in+    cond (constant LT == p) n                   $+    cond (constant EQ == p) (cond (even n) n m) $+            {- otherwise -} m+++data IsFloatingDict a where+  IsFloatingDict :: IsFloating a => IsFloatingDict a++data IsIntegralDict a where+  IsIntegralDict :: IsIntegral a => IsIntegralDict a++isFloating :: forall a. Elt a => Maybe (IsFloatingDict (EltR a))+isFloating+  | TupRsingle t       <- eltR @a+  , SingleScalarType s <- t+  , NumSingleType n    <- s+  , FloatingNumType f  <- n+  = case f of+      TypeHalf{}   -> Just IsFloatingDict+      TypeFloat{}  -> Just IsFloatingDict+      TypeDouble{} -> Just IsFloatingDict+  --+  | otherwise+  = Nothing++isIntegral :: forall a. Elt a => Maybe (IsIntegralDict (EltR a))+isIntegral+  | TupRsingle t       <- eltR @a+  , SingleScalarType s <- t+  , NumSingleType n    <- s+  , IntegralNumType i  <- n+  = case i of+      TypeInt{}    -> Just IsIntegralDict+      TypeInt8{}   -> Just IsIntegralDict+      TypeInt16{}  -> Just IsIntegralDict+      TypeInt32{}  -> Just IsIntegralDict+      TypeInt64{}  -> Just IsIntegralDict+      TypeWord{}   -> Just IsIntegralDict+      TypeWord8{}  -> Just IsIntegralDict+      TypeWord16{} -> Just IsIntegralDict+      TypeWord32{} -> Just IsIntegralDict+      TypeWord64{} -> Just IsIntegralDict+  --+  | otherwise+  = Nothing++ -- To satisfy superclass constraints -- instance RealFrac a => P.RealFrac (Exp a) where@@ -176,4 +275,3 @@             , "These Prelude.RealFrac instances are present only to fulfil superclass"             , "constraints for subsequent classes in the standard Haskell numeric hierarchy."             ]-
+ src/Data/Array/Accelerate/Classes/RealFrac.hs-boot view
@@ -0,0 +1,24 @@+{-# LANGUAGE NoImplicitPrelude #-}+-- |+-- Module      : Data.Array.Accelerate.Classes.RealFrac+-- Copyright   : [2019..2020] The Accelerate Team+-- License     : BSD3+--+-- Maintainer  : Trevor L. McDonell <trevor.mcdonell@gmail.com>+-- Stability   : experimental+-- Portability : non-portable (GHC extensions)+--++module Data.Array.Accelerate.Classes.RealFrac+  where++import Data.Array.Accelerate.Type++class RealFrac a++instance RealFrac Half+instance RealFrac Float+instance RealFrac Double+instance RealFrac CFloat+instance RealFrac CDouble+
src/Data/Array/Accelerate/Classes/ToFloating.hs view
@@ -1,16 +1,14 @@-{-# 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+-- Copyright   : [2016..2020] The Accelerate Team -- License     : BSD3 ----- Maintainer  : Trevor L. McDonell <tmcdonell@cse.unsw.edu.au>+-- Maintainer  : Trevor L. McDonell <trevor.mcdonell@gmail.com> -- Stability   : experimental -- Portability : non-portable (GHC extensions) --@@ -29,13 +27,13 @@  import Language.Haskell.TH                                          hiding ( Exp ) import Control.Monad-import Prelude                                                      ( ($), error, concat )+import Prelude                                                      hiding ( Num, Floating )   -- | 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.+-- coercion between two types. -- class ToFloating a b where   -- | General coercion to floating types@@ -51,24 +49,16 @@         -- 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             -- This is what a constructor such as IntegralNumType will be reified             -- as prior to GHC 8.4...             dig (NormalC _ [(_, AppT (ConT n) (VarT _))])               = digItOut n-#if __GLASGOW_HASKELL__ < 800-            dig (ForallC _ _ (NormalC _ [(_, AppT (ConT _) (ConT n))])) = return [n]-#else             -- ...but this is what IntegralNumType will be reified as on GHC 8.4             -- and later, after the changes described in             -- https://ghc.haskell.org/trac/ghc/wiki/Migration/8.4#TemplateHaskellreificationchangesforGADTs             dig (ForallC _ _ (GadtC _ [(_, AppT (ConT n) (VarT _))] _)) = digItOut n             dig (GadtC _ _ (AppT (ConT _) (ConT n)))                    = return [n]-#endif             dig _ = error "Unexpected case generating ToFloating instances"             --           concat `fmap` mapM dig cons@@ -77,7 +67,9 @@         thToFloating a b =           let               ty  = AppT (AppT (ConT (mkName "ToFloating")) (ConT a)) (ConT b)-              dec = ValD (VarP (mkName "toFloating")) (NormalB (VarE (mkName "mkToFloating"))) []+              dec = ValD (VarP (mkName "toFloating")) (NormalB (VarE (mkName f))) []+              f | a == b    = "id"+                | otherwise = "mkToFloating"           in           instanceD (return []) (return ty) [return dec]     --
src/Data/Array/Accelerate/Data/Bits.hs view
@@ -3,13 +3,14 @@ {-# LANGUAGE GADTs               #-} {-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE TemplateHaskell     #-}+{-# LANGUAGE TypeApplications    #-} {-# LANGUAGE ViewPatterns        #-} -- | -- Module      : Data.Array.Accelerate.Data.Bits--- Copyright   : [2016..2017] Manuel M T Chakravarty, Gabriele Keller, Trevor L. McDonell+-- Copyright   : [2016..2020] The Accelerate Team -- License     : BSD3 ----- Maintainer  : Trevor L. McDonell <tmcdonell@cse.unsw.edu.au>+-- Maintainer  : Trevor L. McDonell <trevor.mcdonell@gmail.com> -- Stability   : experimental -- Portability : non-portable (GHC extensions) --@@ -23,17 +24,17 @@  ) where -import Data.Array.Accelerate.Array.Sugar+import Data.Array.Accelerate.Array.Data import Data.Array.Accelerate.Language import Data.Array.Accelerate.Smart+import Data.Array.Accelerate.Sugar.Elt 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 Prelude                                                      ( (.), ($), undefined, otherwise ) import qualified Data.Bits                                          as B  @@ -181,7 +182,7 @@   rotate x _   = x   bit i        = i == 0   isSigned     = isSignedDefault-  popCount     = mkBoolToInt+  popCount     = boolToInt  instance Bits Int where   (.&.)        = mkBAnd@@ -368,8 +369,8 @@   (.|.)        = mkBOr   xor          = mkBXor   complement   = mkBNot-  bit          = bitDefault-  testBit      = testBitDefault+  bit          = mkBitcast . bitDefault @Int32+  testBit b    = testBitDefault (mkBitcast @Int32 b)   shift        = shiftDefault   shiftL       = shiftLDefault   shiftR       = shiftRDefault@@ -379,15 +380,15 @@   rotateL      = rotateLDefault   rotateR      = rotateRDefault   isSigned     = isSignedDefault-  popCount     = mkPopCount+  popCount     = mkPopCount . mkBitcast @Int32  instance Bits CUInt where   (.&.)        = mkBAnd   (.|.)        = mkBOr   xor          = mkBXor   complement   = mkBNot-  bit          = bitDefault-  testBit      = testBitDefault+  bit          = mkBitcast . bitDefault @Word32+  testBit b    = testBitDefault (mkBitcast @Word32 b)   shift        = shiftDefault   shiftL       = shiftLDefault   shiftR       = shiftRDefault@@ -397,15 +398,15 @@   rotateL      = rotateLDefault   rotateR      = rotateRDefault   isSigned     = isSignedDefault-  popCount     = mkPopCount+  popCount     = mkPopCount . mkBitcast @Word32  instance Bits CLong where   (.&.)        = mkBAnd   (.|.)        = mkBOr   xor          = mkBXor   complement   = mkBNot-  bit          = bitDefault-  testBit      = testBitDefault+  bit          = mkBitcast . bitDefault @HTYPE_CLONG+  testBit b    = testBitDefault (mkBitcast @HTYPE_CLONG b)   shift        = shiftDefault   shiftL       = shiftLDefault   shiftR       = shiftRDefault@@ -415,15 +416,15 @@   rotateL      = rotateLDefault   rotateR      = rotateRDefault   isSigned     = isSignedDefault-  popCount     = mkPopCount+  popCount     = mkPopCount . mkBitcast @HTYPE_CLONG  instance Bits CULong where   (.&.)        = mkBAnd   (.|.)        = mkBOr   xor          = mkBXor   complement   = mkBNot-  bit          = bitDefault-  testBit      = testBitDefault+  bit          = mkBitcast . bitDefault @HTYPE_CULONG+  testBit b    = testBitDefault (mkBitcast @HTYPE_CULONG b)   shift        = shiftDefault   shiftL       = shiftLDefault   shiftR       = shiftRDefault@@ -433,15 +434,15 @@   rotateL      = rotateLDefault   rotateR      = rotateRDefault   isSigned     = isSignedDefault-  popCount     = mkPopCount+  popCount     = mkPopCount . mkBitcast @HTYPE_CULONG  instance Bits CLLong where   (.&.)        = mkBAnd   (.|.)        = mkBOr   xor          = mkBXor   complement   = mkBNot-  bit          = bitDefault-  testBit      = testBitDefault+  bit          = mkBitcast . bitDefault @Int64+  testBit b    = testBitDefault (mkBitcast @Int64 b)   shift        = shiftDefault   shiftL       = shiftLDefault   shiftR       = shiftRDefault@@ -451,15 +452,15 @@   rotateL      = rotateLDefault   rotateR      = rotateRDefault   isSigned     = isSignedDefault-  popCount     = mkPopCount+  popCount     = mkPopCount . mkBitcast @Int64  instance Bits CULLong where   (.&.)        = mkBAnd   (.|.)        = mkBOr   xor          = mkBXor   complement   = mkBNot-  bit          = bitDefault-  testBit      = testBitDefault+  bit          = mkBitcast . bitDefault @Word64+  testBit b    = testBitDefault (mkBitcast @Word64 b)   shift        = shiftDefault   shiftL       = shiftLDefault   shiftR       = shiftRDefault@@ -469,15 +470,15 @@   rotateL      = rotateLDefault   rotateR      = rotateRDefault   isSigned     = isSignedDefault-  popCount     = mkPopCount+  popCount     = mkPopCount . mkBitcast @Word64  instance Bits CShort where   (.&.)        = mkBAnd   (.|.)        = mkBOr   xor          = mkBXor   complement   = mkBNot-  bit          = bitDefault-  testBit      = testBitDefault+  bit          = mkBitcast . bitDefault @Int16+  testBit b    = testBitDefault (mkBitcast @Int16 b)   shift        = shiftDefault   shiftL       = shiftLDefault   shiftR       = shiftRDefault@@ -487,15 +488,15 @@   rotateL      = rotateLDefault   rotateR      = rotateRDefault   isSigned     = isSignedDefault-  popCount     = mkPopCount+  popCount     = mkPopCount . mkBitcast @Int16  instance Bits CUShort where   (.&.)        = mkBAnd   (.|.)        = mkBOr   xor          = mkBXor   complement   = mkBNot-  bit          = bitDefault-  testBit      = testBitDefault+  bit          = mkBitcast . bitDefault @Word16+  testBit b    = testBitDefault (mkBitcast @Word16 b)   shift        = shiftDefault   shiftL       = shiftLDefault   shiftR       = shiftRDefault@@ -505,205 +506,230 @@   rotateL      = rotateLDefault   rotateR      = rotateRDefault   isSigned     = isSignedDefault-  popCount     = mkPopCount+  popCount     = mkPopCount . mkBitcast @Word16 --- 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 CChar where+  (.&.)        = mkBAnd+  (.|.)        = mkBOr+  xor          = mkBXor+  complement   = mkBNot+  bit          = mkBitcast . bitDefault @HTYPE_CCHAR+  testBit b    = testBitDefault (mkBitcast @HTYPE_CCHAR b)+  shift        = shiftDefault+  shiftL       = shiftLDefault+  shiftR       = shiftRDefault+  unsafeShiftL = mkBShiftL+  unsafeShiftR = mkBShiftR+  rotate       = rotateDefault+  rotateL      = rotateLDefault+  rotateR      = rotateRDefault+  isSigned     = isSignedDefault+  popCount     = mkPopCount . mkBitcast @HTYPE_CCHAR --- 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          = mkBitcast . bitDefault @Int8+  testBit b    = testBitDefault (mkBitcast @Int8 b)+  shift        = shiftDefault+  shiftL       = shiftLDefault+  shiftR       = shiftRDefault+  unsafeShiftL = mkBShiftL+  unsafeShiftR = mkBShiftR+  rotate       = rotateDefault+  rotateL      = rotateLDefault+  rotateR      = rotateRDefault+  isSigned     = isSignedDefault+  popCount     = mkPopCount . mkBitcast @Int8 --- 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+instance Bits CUChar where+  (.&.)        = mkBAnd+  (.|.)        = mkBOr+  xor          = mkBXor+  complement   = mkBNot+  bit          = mkBitcast . bitDefault @Word8+  testBit b    = testBitDefault (mkBitcast @Word8 b)+  shift        = shiftDefault+  shiftL       = shiftLDefault+  shiftR       = shiftRDefault+  unsafeShiftL = mkBShiftL+  unsafeShiftR = mkBShiftR+  rotate       = rotateDefault+  rotateL      = rotateLDefault+  rotateR      = rotateRDefault+  isSigned     = isSignedDefault+  popCount     = mkPopCount . mkBitcast @Word8  + -- Instances for FiniteBits -- ------------------------  instance FiniteBits Bool where-  finiteBitSize _      = constant 8 -- stored as Word8 {- (B.finiteBitSize (undefined::Bool)) -}+  finiteBitSize _      = constInt 8 -- stored as Word8 {- (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))+  finiteBitSize _    = constInt (B.finiteBitSize (undefined::Int))   countLeadingZeros  = mkCountLeadingZeros   countTrailingZeros = mkCountTrailingZeros  instance FiniteBits Int8 where-  finiteBitSize _    = constant (B.finiteBitSize (undefined::Int8))+  finiteBitSize _    = constInt (B.finiteBitSize (undefined::Int8))   countLeadingZeros  = mkCountLeadingZeros   countTrailingZeros = mkCountTrailingZeros  instance FiniteBits Int16 where-  finiteBitSize _    = constant (B.finiteBitSize (undefined::Int16))+  finiteBitSize _    = constInt (B.finiteBitSize (undefined::Int16))   countLeadingZeros  = mkCountLeadingZeros   countTrailingZeros = mkCountTrailingZeros  instance FiniteBits Int32 where-  finiteBitSize _    = constant (B.finiteBitSize (undefined::Int32))+  finiteBitSize _    = constInt (B.finiteBitSize (undefined::Int32))   countLeadingZeros  = mkCountLeadingZeros   countTrailingZeros = mkCountTrailingZeros  instance FiniteBits Int64 where-  finiteBitSize _    = constant (B.finiteBitSize (undefined::Int64))+  finiteBitSize _    = constInt (B.finiteBitSize (undefined::Int64))   countLeadingZeros  = mkCountLeadingZeros   countTrailingZeros = mkCountTrailingZeros  instance FiniteBits Word where-  finiteBitSize _    = constant (B.finiteBitSize (undefined::Word))+  finiteBitSize _    = constInt (B.finiteBitSize (undefined::Word))   countLeadingZeros  = mkCountLeadingZeros   countTrailingZeros = mkCountTrailingZeros  instance FiniteBits Word8 where-  finiteBitSize _    = constant (B.finiteBitSize (undefined::Word8))+  finiteBitSize _    = constInt (B.finiteBitSize (undefined::Word8))   countLeadingZeros  = mkCountLeadingZeros   countTrailingZeros = mkCountTrailingZeros  instance FiniteBits Word16 where-  finiteBitSize _    = constant (B.finiteBitSize (undefined::Word16))+  finiteBitSize _    = constInt (B.finiteBitSize (undefined::Word16))   countLeadingZeros  = mkCountLeadingZeros   countTrailingZeros = mkCountTrailingZeros  instance FiniteBits Word32 where-  finiteBitSize _    = constant (B.finiteBitSize (undefined::Word32))+  finiteBitSize _    = constInt (B.finiteBitSize (undefined::Word32))   countLeadingZeros  = mkCountLeadingZeros   countTrailingZeros = mkCountTrailingZeros  instance FiniteBits Word64 where-  finiteBitSize _    = constant (B.finiteBitSize (undefined::Word64))+  finiteBitSize _    = constInt (B.finiteBitSize (undefined::Word64))   countLeadingZeros  = mkCountLeadingZeros   countTrailingZeros = mkCountTrailingZeros  instance FiniteBits CInt where-  finiteBitSize _    = constant (B.finiteBitSize (undefined::CInt))-  countLeadingZeros  = mkCountLeadingZeros-  countTrailingZeros = mkCountTrailingZeros+  finiteBitSize _    = constInt (B.finiteBitSize (undefined::CInt))+  countLeadingZeros  = mkCountLeadingZeros  . mkBitcast @Int32+  countTrailingZeros = mkCountTrailingZeros . mkBitcast @Int32  instance FiniteBits CUInt where-  finiteBitSize _    = constant (B.finiteBitSize (undefined::CUInt))-  countLeadingZeros  = mkCountLeadingZeros-  countTrailingZeros = mkCountTrailingZeros+  finiteBitSize _    = constInt (B.finiteBitSize (undefined::CUInt))+  countLeadingZeros  = mkCountLeadingZeros  . mkBitcast @Word32+  countTrailingZeros = mkCountTrailingZeros . mkBitcast @Word32  instance FiniteBits CLong where-  finiteBitSize _    = constant (B.finiteBitSize (undefined::CLong))-  countLeadingZeros  = mkCountLeadingZeros-  countTrailingZeros = mkCountTrailingZeros+  finiteBitSize _    = constInt (B.finiteBitSize (undefined::CLong))+  countLeadingZeros  = mkCountLeadingZeros  . mkBitcast @HTYPE_CLONG+  countTrailingZeros = mkCountTrailingZeros . mkBitcast @HTYPE_CLONG  instance FiniteBits CULong where-  finiteBitSize _    = constant (B.finiteBitSize (undefined::CULong))-  countLeadingZeros  = mkCountLeadingZeros-  countTrailingZeros = mkCountTrailingZeros+  finiteBitSize _    = constInt (B.finiteBitSize (undefined::CULong))+  countLeadingZeros  = mkCountLeadingZeros  . mkBitcast @HTYPE_CULONG+  countTrailingZeros = mkCountTrailingZeros . mkBitcast @HTYPE_CULONG  instance FiniteBits CLLong where-  finiteBitSize _    = constant (B.finiteBitSize (undefined::CLLong))-  countLeadingZeros  = mkCountLeadingZeros-  countTrailingZeros = mkCountTrailingZeros+  finiteBitSize _    = constInt (B.finiteBitSize (undefined::CLLong))+  countLeadingZeros  = mkCountLeadingZeros  . mkBitcast @Int64+  countTrailingZeros = mkCountTrailingZeros . mkBitcast @Int64  instance FiniteBits CULLong where-  finiteBitSize _    = constant (B.finiteBitSize (undefined::CULLong))-  countLeadingZeros  = mkCountLeadingZeros-  countTrailingZeros = mkCountTrailingZeros+  finiteBitSize _    = constInt (B.finiteBitSize (undefined::CULLong))+  countLeadingZeros  = mkCountLeadingZeros  . mkBitcast @Word64+  countTrailingZeros = mkCountTrailingZeros . mkBitcast @Word64  instance FiniteBits CShort where-  finiteBitSize _    = constant (B.finiteBitSize (undefined::CShort))-  countLeadingZeros  = mkCountLeadingZeros-  countTrailingZeros = mkCountTrailingZeros+  finiteBitSize _    = constInt (B.finiteBitSize (undefined::CShort))+  countLeadingZeros  = mkCountLeadingZeros  . mkBitcast @Int16+  countTrailingZeros = mkCountTrailingZeros . mkBitcast @Int16  instance FiniteBits CUShort where-  finiteBitSize _    = constant (B.finiteBitSize (undefined::CUShort))-  countLeadingZeros  = mkCountLeadingZeros-  countTrailingZeros = mkCountTrailingZeros+  finiteBitSize _    = constInt (B.finiteBitSize (undefined::CUShort))+  countLeadingZeros  = mkCountLeadingZeros  . mkBitcast @Word16+  countTrailingZeros = mkCountTrailingZeros . mkBitcast @Word16 --- instance FiniteBits CChar--- instance FiniteBits CUChar--- instance FiniteBits CSChar+instance FiniteBits CChar where+  finiteBitSize _    = constInt (B.finiteBitSize (undefined::CChar))+  countLeadingZeros  = mkCountLeadingZeros  . mkBitcast @HTYPE_CCHAR+  countTrailingZeros = mkCountTrailingZeros . mkBitcast @HTYPE_CCHAR +instance FiniteBits CSChar where+  finiteBitSize _    = constInt (B.finiteBitSize (undefined::CSChar))+  countLeadingZeros  = mkCountLeadingZeros  . mkBitcast @Int8+  countTrailingZeros = mkCountTrailingZeros . mkBitcast @Int8 +instance FiniteBits CUChar where+  finiteBitSize _    = constInt (B.finiteBitSize (undefined::CUChar))+  countLeadingZeros  = mkCountLeadingZeros  . mkBitcast @Word8+  countTrailingZeros = mkCountTrailingZeros . mkBitcast @Word8++ -- Default implementations -- -------------------------bitDefault :: (IsIntegral t, Bits t) => Exp Int -> Exp t-bitDefault x = constant 1 `shiftL` x+bitDefault :: (IsIntegral (EltR t), Bits t) => Exp Int -> Exp t+bitDefault x = constInt 1 `shiftL` x -testBitDefault :: (IsIntegral t, Bits t) => Exp t -> Exp Int -> Exp Bool-testBitDefault x i = (x .&. bit i) /= constant 0+testBitDefault :: (IsIntegral (EltR t), Bits t) => Exp t -> Exp Int -> Exp Bool+testBitDefault x i = (x .&. bit i) /= constInt 0 -shiftDefault :: (FiniteBits t, IsIntegral t, B.Bits t) => Exp t -> Exp Int -> Exp t+shiftDefault :: (FiniteBits t, IsIntegral (EltR 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 :: (FiniteBits t, IsIntegral (EltR t)) => Exp t -> Exp Int -> Exp t shiftLDefault x i-  = cond (i >= finiteBitSize x) (constant 0)+  = cond (i >= finiteBitSize x) (constInt 0)   $ mkBShiftL x i -shiftRDefault :: forall t. (B.Bits t, FiniteBits t, IsIntegral t) => Exp t -> Exp Int -> Exp t+shiftRDefault :: forall t. (B.Bits t, FiniteBits t, IsIntegral (EltR 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 :: (FiniteBits t, IsIntegral (EltR t)) => Exp t -> Exp Int -> Exp t shiftRADefault x i-  = cond (i >= finiteBitSize x) (cond (mkLt x (constant 0)) (constant (-1)) (constant 0))+  = cond (i >= finiteBitSize x) (cond (mkLt x (constInt 0)) (constInt (-1)) (constInt 0))   $ mkBShiftR x i  -- Shift the argument right (unsigned)-shiftRLDefault :: (FiniteBits t, IsIntegral t) => Exp t -> Exp Int -> Exp t+shiftRLDefault :: (FiniteBits t, IsIntegral (EltR t)) => Exp t -> Exp Int -> Exp t shiftRLDefault x i-  = cond (i >= finiteBitSize x) (constant 0)+  = cond (i >= finiteBitSize x) (constInt 0)   $ mkBShiftR x i -rotateDefault :: forall t. (FiniteBits t, IsIntegral t) => Exp t -> Exp Int -> Exp t+rotateDefault :: forall t. (FiniteBits t, IsIntegral (EltR t)) => Exp t -> Exp Int -> Exp t+rotateDefault x i+  = cond (i < 0) (mkBRotateR x (-i))+  $ cond (i > 0) (mkBRotateL x i)+  $ x++{--+-- Rotation can be implemented in terms of two shifts, but care is needed+-- for negative values. This suggested implementation assumes+-- 2's-complement arithmetic.+--+-- This is disabled because (at least) LLVM-9 generates incorrect code on+-- the Turing architecture for negative shift amounts of 64-bit values.+--+rotateDefault :: forall t. (FiniteBits t, IsIntegral (EltR t)) => Exp t -> Exp Int -> Exp t rotateDefault =-  case (integralType :: IntegralType t) of+  case integralType :: IntegralType (EltR t) of     TypeInt{}     -> rotateDefault' (undefined::Word)     TypeInt8{}    -> rotateDefault' (undefined::Word8)     TypeInt16{}   -> rotateDefault' (undefined::Word16)@@ -714,17 +740,9 @@     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, IsIntegral (EltRepr i), IsIntegral (EltRepr w), BitSizeEq (EltRepr i) (EltRepr w), BitSizeEq (EltRepr w) (EltRepr i))+    :: forall i w. (Elt w, FiniteBits i, IsIntegral (EltR i), IsIntegral (EltR w), IsIntegral (EltR i), IsIntegral (EltR w), BitSizeEq (EltR i) (EltR w), BitSizeEq (EltR w) (EltR i))     => w {- dummy -}     -> Exp i     -> Exp Int@@ -739,19 +757,23 @@     x'   = i2w x     i'   = i `mkBAnd` (wsib - 1)     wsib = finiteBitSize x+--} -rotateLDefault :: (Elt t, IsIntegral t) => Exp t -> Exp Int -> Exp t+rotateLDefault :: (Elt t, IsIntegral (EltR 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 :: (Elt t, IsIntegral (EltR 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))++constInt :: IsIntegral (EltR e) => EltR e -> Exp e+constInt = mkExp . Const (SingleScalarType (NumSingleType (IntegralNumType integralType)))  {-- _popCountDefault :: forall a. (B.FiniteBits a, IsScalar a, Bits a, Num a) => Exp a -> Exp Int
src/Data/Array/Accelerate/Data/Complex.hs view
@@ -1,10 +1,13 @@-{-# LANGUAGE CPP                   #-} {-# LANGUAGE ConstraintKinds       #-} {-# LANGUAGE FlexibleContexts      #-} {-# LANGUAGE FlexibleInstances     #-}+{-# LANGUAGE GADTs                 #-}+{-# LANGUAGE MagicHash             #-} {-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE PatternSynonyms       #-} {-# LANGUAGE RebindableSyntax      #-} {-# LANGUAGE ScopedTypeVariables   #-}+{-# LANGUAGE TypeApplications      #-} {-# LANGUAGE TypeFamilies          #-} {-# LANGUAGE TypeSynonymInstances  #-} {-# LANGUAGE UndecidableInstances  #-}@@ -12,10 +15,10 @@ {-# OPTIONS_GHC -fno-warn-orphans #-} -- | -- Module      : Data.Array.Accelerate.Data.Complex--- Copyright   : [2015..2017] Trevor L. McDonell+-- Copyright   : [2015..2020] The Accelerate Team -- License     : BSD3 ----- Maintainer  : Trevor L. McDonell <tmcdonell@cse.unsw.edu.au>+-- Maintainer  : Trevor L. McDonell <trevor.mcdonell@gmail.com> -- Stability   : experimental -- Portability : non-portable (GHC extensions) --@@ -25,7 +28,7 @@ module Data.Array.Accelerate.Data.Complex (    -- * Rectangular from-  Complex(..),+  Complex(..), pattern (::+),   real,   imag, @@ -33,7 +36,7 @@   mkPolar,   cis,   polar,-  magnitude,+  magnitude, magnitude',   phase,    -- * Conjugate@@ -41,99 +44,169 @@  ) where -import Data.Array.Accelerate.Array.Sugar import Data.Array.Accelerate.Classes import Data.Array.Accelerate.Data.Functor+import Data.Array.Accelerate.Pattern import Data.Array.Accelerate.Prelude-import Data.Array.Accelerate.Product+import Data.Array.Accelerate.Representation.Tag+import Data.Array.Accelerate.Representation.Type+import Data.Array.Accelerate.Representation.Vec import Data.Array.Accelerate.Smart+import Data.Array.Accelerate.Sugar.Elt+import Data.Array.Accelerate.Sugar.Vec import Data.Array.Accelerate.Type+import Data.Primitive.Vec -import Prelude                                                      ( ($), undefined ) import Data.Complex                                                 ( Complex(..) )+import Prelude                                                      ( ($) ) import qualified Data.Complex                                       as C import qualified Prelude                                            as P  --- Use an array-of-structs representation for complex numbers. This matches the--- standard C-style layout, but means that we can define instances only at--- specific types (not for any type 'a') as we can only have vectors of--- primitive type.+infix 6 ::++pattern (::+) :: Elt a => Exp a -> Exp a -> Exp (Complex a)+pattern r ::+ i <- (deconstructComplex -> (r, i))+  where (::+) = constructComplex+{-# COMPLETE (::+) #-}+++-- Use an array-of-structs representation for complex numbers if possible.+-- This matches the standard C-style layout, but we can use this representation only at+-- specific types (not for any type 'a') as we can only have vectors of primitive type.+-- For other types, we use a structure-of-arrays representation. This is handled by the+-- ComplexR. We use the GADT ComplexR and function complexR to reconstruct+-- information on how the elements are represented. ---type instance EltRepr (Complex Half)    = V2 Half-type instance EltRepr (Complex Float)   = V2 Float-type instance EltRepr (Complex Double)  = V2 Double-type instance EltRepr (Complex CFloat)  = V2 CFloat-type instance EltRepr (Complex CDouble) = V2 CDouble+instance Elt a => Elt (Complex a) where+  type EltR (Complex a) = ComplexR (EltR a)+  eltR = let tR = eltR @a+          in case complexR tR of+               ComplexVec s -> TupRsingle $ VectorScalarType $ VectorType 2 s+               ComplexTup   -> TupRunit `TupRpair` tR `TupRpair` tR -instance Elt (Complex Half) where-  eltType _        = TypeRscalar scalarType-  toElt (V2 r i)   = r :+ i-  fromElt (r :+ i) = V2 r i+  tagsR = let tR = eltR @a+           in case complexR tR of+               ComplexVec s -> [ TagRsingle (VectorScalarType (VectorType 2 s)) ]+               ComplexTup   -> let go :: TypeR t -> [TagR t]+                                   go TupRunit         = [TagRunit]+                                   go (TupRsingle s)   = [TagRsingle s]+                                   go (TupRpair ta tb) = [TagRpair a b | a <- go ta, b <- go tb]+                                in+                                [ TagRunit `TagRpair` ta `TagRpair` tb | ta <- go tR, tb <- go tR ] -instance Elt (Complex Float) where-  eltType _        = TypeRscalar scalarType-  toElt (V2 r i)   = r :+ i-  fromElt (r :+ i) = V2 r i+  toElt = case complexR $ eltR @a of+    ComplexVec _ -> \(Vec2 r i)   -> toElt r :+ toElt i+    ComplexTup   -> \(((), r), i) -> toElt r :+ toElt i -instance Elt (Complex Double) where-  eltType _        = TypeRscalar scalarType-  toElt (V2 r i)   = r :+ i-  fromElt (r :+ i) = V2 r i+  fromElt (r :+ i) = case complexR $ eltR @a of+    ComplexVec _ -> Vec2 (fromElt r) (fromElt i)+    ComplexTup   -> (((), fromElt r), fromElt i) -instance Elt (Complex CFloat) where-  eltType _        = TypeRscalar scalarType-  toElt (V2 r i)   = r :+ i-  fromElt (r :+ i) = V2 r i+type family ComplexR a where+  ComplexR Half   = Vec2 Half+  ComplexR Float  = Vec2 Float+  ComplexR Double = Vec2 Double+  ComplexR Int    = Vec2 Int+  ComplexR Int8   = Vec2 Int8+  ComplexR Int16  = Vec2 Int16+  ComplexR Int32  = Vec2 Int32+  ComplexR Int64  = Vec2 Int64+  ComplexR Word   = Vec2 Word+  ComplexR Word8  = Vec2 Word8+  ComplexR Word16 = Vec2 Word16+  ComplexR Word32 = Vec2 Word32+  ComplexR Word64 = Vec2 Word64+  ComplexR a      = (((), a), a) -instance Elt (Complex CDouble) where-  eltType _        = TypeRscalar scalarType-  toElt (V2 r i)   = r :+ i-  fromElt (r :+ i) = V2 r i+-- This isn't ideal because we gather the evidence based on the+-- representation type, so we really get the evidence (VecElt (EltR a)),+-- which is not very useful...+--    - TLM 2020-07-16+data ComplexType a c where+  ComplexVec :: VecElt a => SingleType a -> ComplexType a (Vec2 a)+  ComplexTup ::                             ComplexType a (((), a), a) -instance cst a => IsProduct cst (Complex a) where-  type ProdRepr (Complex a) = ProdRepr (V2 a)-  fromProd cst (r :+ i) = fromProd cst (V2 r i)-  toProd cst p          = let (V2 r i) = toProd cst p in (r :+ i)-  prod cst _            = prod cst (undefined :: (V2 a))+complexR :: TypeR a -> ComplexType a (ComplexR a)+complexR = tuple+  where+    tuple :: TypeR a -> ComplexType a (ComplexR a)+    tuple TupRunit       = ComplexTup+    tuple TupRpair{}     = ComplexTup+    tuple (TupRsingle s) = scalar s -instance (Lift Exp a, Elt (Plain a), Elt (Complex (Plain a))) => Lift Exp (Complex a) where+    scalar :: ScalarType a -> ComplexType a (ComplexR a)+    scalar (SingleScalarType t) = single t+    scalar VectorScalarType{}   = ComplexTup++    single :: SingleType a -> ComplexType a (ComplexR a)+    single (NumSingleType t) = num t++    num :: NumType a -> ComplexType a (ComplexR a)+    num (IntegralNumType t) = integral t+    num (FloatingNumType t) = floating t++    integral :: IntegralType a -> ComplexType a (ComplexR a)+    integral TypeInt    = ComplexVec singleType+    integral TypeInt8   = ComplexVec singleType+    integral TypeInt16  = ComplexVec singleType+    integral TypeInt32  = ComplexVec singleType+    integral TypeInt64  = ComplexVec singleType+    integral TypeWord   = ComplexVec singleType+    integral TypeWord8  = ComplexVec singleType+    integral TypeWord16 = ComplexVec singleType+    integral TypeWord32 = ComplexVec singleType+    integral TypeWord64 = ComplexVec singleType++    floating :: FloatingType a -> ComplexType a (ComplexR a)+    floating TypeHalf   = ComplexVec singleType+    floating TypeFloat  = ComplexVec singleType+    floating TypeDouble = ComplexVec singleType+++constructComplex :: forall a. Elt a => Exp a -> Exp a -> Exp (Complex a)+constructComplex r i =+  case complexR (eltR @a) of+    ComplexTup   -> coerce $ T2 r i+    ComplexVec _ -> V2 (coerce @a @(EltR a) r) (coerce @a @(EltR a) i)++deconstructComplex :: forall a. Elt a => Exp (Complex a) -> (Exp a, Exp a)+deconstructComplex c@(Exp c') =+  case complexR (eltR @a) of+    ComplexTup   -> let T2 r i = coerce c in (r, i)+    ComplexVec t -> let T2 r i = Exp (SmartExp (VecUnpack (VecRsucc (VecRsucc (VecRnil t))) c'))+                     in (r, i)++coerce :: EltR a ~ EltR b => Exp a -> Exp b+coerce (Exp e) = Exp e++instance (Lift Exp a, Elt (Plain a)) => Lift Exp (Complex a) where   type Plain (Complex a) = Complex (Plain a)-  lift (r :+ i)          = Exp $ Tuple (NilTup `SnocTup` lift r `SnocTup` lift i)+  lift (r :+ i) = lift r ::+ lift i -instance (Elt a, Elt (Complex a)) => Unlift Exp (Complex (Exp a)) where-  unlift e-    = let r     = Exp $ SuccTupIdx ZeroTupIdx `Prj` e-          i     = Exp $ ZeroTupIdx `Prj` e-      in-      r :+ i+instance Elt a => Unlift Exp (Complex (Exp a)) where+  unlift (r ::+ i) = r :+ i  -instance (Eq a, Elt (Complex 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 Eq a => Eq (Complex a) where+  r1 ::+ c1 == r2 ::+ c2 = r1 == r2 && c1 == c2+  r1 ::+ c1 /= r2 ::+ c2 = r1 /= r2 || c1 /= c2 -instance (RealFloat a, Elt (Complex 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 z      = if z == 0-                    then z-                    else let x :+ y = unlift z-                             r      = magnitude z-                         in-                         lift (x/r :+ y/r)-  abs z         = lift (magnitude z :+ 0)-  fromInteger n = lift (fromInteger n :+ 0)+instance 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 z@(x ::+ y) =+    if z == 0+       then z+       else let r = magnitude z+             in x/r ::+ y/r+  abs z         = magnitude z ::+ 0+  fromInteger n = fromInteger n ::+ 0 -instance (RealFloat a, Elt (Complex a)) => P.Fractional (Exp (Complex a)) where-  fromRational x  = lift (fromRational x :+ 0)-  z / z'          = lift ((x*x''+y*y'') / d :+ (y*x''-x*y'') / d)+instance RealFloat a => P.Fractional (Exp (Complex a)) where+  fromRational x  = fromRational x ::+ 0+  z / z'          = (x*x''+y*y'') / d ::+ (y*x''-x*y'') / d     where       x  :+ y   = unlift z       x' :+ y'  = unlift z'@@ -143,70 +216,67 @@       k   = - max (exponent x') (exponent y')       d   = x'*x'' + y'*y'' -instance (RealFloat a, Elt (Complex a)) => P.Floating (Exp (Complex a)) where-  pi                      = lift $ pi :+ 0--  exp (unlift -> x :+ y)  = let expx = exp x-                            in  complex $ expx * cos y :+ expx * sin y--  log z                   = lift $ log (magnitude z) :+ phase z--  sqrt z@(unlift -> x :+ y) =+instance RealFloat a => P.Floating (Exp (Complex a)) where+  pi                = pi ::+ 0+  exp (x ::+ y)     = let expx = exp x+                       in expx * cos y ::+ expx * sin y+  log z             = log (magnitude z) ::+ phase z+  sqrt z@(x ::+ y)  =     if z == 0       then 0-      else lift $ u :+ (y < 0 ? (-v, v))+      else u ::+ (y < 0 ? (-v, v))     where-      (u,v) = unlift (x < 0 ? (lift (v',u'), lift (u',v')))-      v'    = abs y / (u'*2)-      u'    = sqrt ((magnitude z + abs x) / 2)+      T2 u v = x < 0 ? (T2 v' u', T2 u' v')+      v'     = abs y / (u'*2)+      u'     = sqrt ((magnitude z + abs x) / 2)    x ** y =     if y == 0 then 1 else     if x == 0 then if exp_r > 0 then 0 else-                   if exp_r < 0 then lift (inf :+ 0)-                                else lift (nan :+ nan)+                   if exp_r < 0 then inf ::+ 0+                                else nan ::+ nan               else if isInfinite r || isInfinite i-                     then if exp_r > 0 then lift (inf :+ 0) else+                     then if exp_r > 0 then inf ::+ 0 else                           if exp_r < 0 then 0-                                       else lift (nan :+ nan)+                                       else nan ::+ nan                      else exp (log x * y)     where-      r     :+ i  = unlift x-      exp_r :+ _  = unlift y+      r     ::+ i  = x+      exp_r ::+ _  = y       --       inf = 1 / 0       nan = 0 / 0 -  sin (unlift -> x :+ y)  = complex $ sin x * cosh y :+ cos x * sinh y-  cos (unlift -> x :+ y)  = complex $ cos x * cosh y :+ (- sin x * sinh y)-  tan (unlift -> x :+ y)  = (complex $ sinx*coshy :+ cosx*sinhy) / (complex $ cosx*coshy :+ (-sinx*sinhy))+  sin (x ::+ y)  = sin x * cosh y ::+ cos x * sinh y+  cos (x ::+ y)  = cos x * cosh y ::+ (- sin x * sinh y)+  tan (x ::+ y)  = (sinx*coshy ::+ cosx*sinhy) / (cosx*coshy ::+ (-sinx*sinhy))     where       sinx  = sin x       cosx  = cos x       sinhy = sinh y       coshy = cosh y -  sinh (unlift -> x :+ y) = complex $ cos y * sinh x :+ sin  y * cosh x-  cosh (unlift -> x :+ y) = complex $ cos y * cosh x :+ sin y * sinh x-  tanh (unlift -> x :+ y) = (complex $ cosy*sinhx :+ siny*coshx) / (complex $ cosy*coshx :+ siny*sinhx)+  sinh (x ::+ y) = cos y * sinh x ::+ sin  y * cosh x+  cosh (x ::+ y) = cos y * cosh x ::+ sin y * sinh x+  tanh (x ::+ y) = (cosy*sinhx ::+ siny*coshx) / (cosy*coshx ::+ siny*sinhx)     where       siny  = sin y       cosy  = cos y       sinhx = sinh x       coshx = cosh x -  asin z@(unlift -> x :+ y) = complex $ y' :+ (-x')+  asin z@(x ::+ y) = y' ::+ (-x')     where-      x' :+ y' = unlift $ log ((complex ((-y):+x)) + sqrt (1 - z*z))+      x' ::+ y' = log (((-y) ::+ x) + sqrt (1 - z*z)) -  acos z                    = complex $ y'' :+ (-x'')+  acos z                    = y'' ::+ (-x'')     where-      x'' :+ y''  = unlift $ log (z + (complex ((-y') :+ x')))-      x'  :+ y'   = unlift $ sqrt (1 - z*z)+      x'' ::+ y''  = log (z + ((-y') ::+ x'))+      x'  ::+ y'   = sqrt (1 - z*z) -  atan z@(unlift -> x :+ y) = complex $ y' :+ (-x')+  atan z@(x ::+ y) = y' ::+ (-x')     where-      x' :+ y' = unlift $ log ((complex ((1-y):+x)) / sqrt (1+z*z))+      x' ::+ y' = log (((1-y) ::+ x) / sqrt (1+z*z))    asinh z =  log (z + sqrt (1+z*z))   acosh z =  log (z + (z+1) * sqrt ((z-1)/(z+1)))@@ -214,33 +284,36 @@   instance (FromIntegral a b, Num b, Elt (Complex b)) => FromIntegral a (Complex b) where-  fromIntegral x = lift (fromIntegral x :+ 0)+  fromIntegral x = fromIntegral x ::+ 0  -- | @since 1.2.0.0+-- instance Functor Complex where-  fmap f (unlift -> r :+ i) = lift (f r :+ f i)+  fmap f (r ::+ i) = f r ::+ f i  --- Helper function to fix the types for lift (ugh)----complex :: (Elt a, Elt (Complex a)) => Complex (Exp a) -> Exp (Complex a)-complex = lift- -- | The non-negative magnitude of a complex number ---magnitude :: (RealFloat a, Elt (Complex a)) => Exp (Complex a) -> Exp a--- magnitude (unlift -> r :+ i) = sqrt (r*r + i*i)-magnitude (unlift -> r :+ i) = scaleFloat k (sqrt (sqr (scaleFloat mk r) + sqr (scaleFloat mk i)))+magnitude :: RealFloat a => Exp (Complex a) -> Exp a+magnitude (r ::+ i) = scaleFloat k (sqrt (sqr (scaleFloat mk r) + sqr (scaleFloat mk i)))   where     k     = max (exponent r) (exponent i)     mk    = -k     sqr z = z * z +-- | As 'magnitude', but ignore floating point rounding and use the traditional+-- (simpler to evaluate) definition.+--+-- @since 1.3.0.0+--+magnitude' :: RealFloat a => Exp (Complex a) -> Exp a+magnitude' (r ::+ i) = sqrt (r*r + i*i)+ -- | The phase of a complex number, in the range @(-'pi', 'pi']@. If the -- magnitude is zero, then so is the phase. ---phase :: (RealFloat a, Elt (Complex a)) => Exp (Complex a) -> Exp a-phase z@(unlift -> r :+ i) =+phase :: RealFloat a => Exp (Complex a) -> Exp a+phase z@(r ::+ i) =   if z == 0     then 0     else atan2 i r@@ -249,42 +322,34 @@ -- phase) pair in canonical form: the magnitude is non-negative, and the phase -- in the range @(-'pi', 'pi']@; if the magnitude is zero, then so is the phase. ---polar :: (RealFloat a, Elt (Complex a)) => Exp (Complex a) -> Exp (a,a)-polar z =  lift (magnitude z, phase z)+polar :: RealFloat a => Exp (Complex a) -> Exp (a,a)+polar z =  T2 (magnitude z) (phase z)  -- | Form a complex number from polar components of magnitude and phase. ---#if __GLASGOW_HASKELL__ <= 708-mkPolar :: forall a. (RealFloat a, Elt (Complex a)) => Exp a -> Exp a -> Exp (Complex a)-#else-mkPolar :: forall a. (Floating a,  Elt (Complex a)) => Exp a -> Exp a -> Exp (Complex a)-#endif+mkPolar :: forall a. Floating a => Exp a -> Exp a -> Exp (Complex a) 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'@). ---#if __GLASGOW_HASKELL__ <= 708-cis :: forall a. (RealFloat a, Elt (Complex a)) => Exp a -> Exp (Complex a)-#else-cis :: forall a. (Floating a,  Elt (Complex a)) => Exp a -> Exp (Complex a)-#endif+cis :: forall a. Floating a => Exp a -> Exp (Complex a) cis = lift1 (C.cis :: Exp a -> Complex (Exp a))  -- | Return the real part of a complex number ---real :: (Elt a, Elt (Complex a)) => Exp (Complex a) -> Exp a-real (unlift -> r :+ _) = r+real :: Elt a => Exp (Complex a) -> Exp a+real (r ::+ _) = r  -- | Return the imaginary part of a complex number ---imag :: (Elt a, Elt (Complex a)) => Exp (Complex a) -> Exp a-imag (unlift -> _ :+ i) = i+imag :: Elt a => Exp (Complex a) -> Exp a+imag (_ ::+ i) = i  -- | Return the complex conjugate of a complex number, defined as -- -- > conjugate(Z) = X - iY ---conjugate :: (Num a, Elt (Complex a)) => Exp (Complex a) -> Exp (Complex a)-conjugate z = lift $ real z :+ (- imag z)+conjugate :: Num a => Exp (Complex a) -> Exp (Complex a)+conjugate z = real z ::+ (- imag z) 
src/Data/Array/Accelerate/Data/Either.hs view
@@ -1,18 +1,24 @@-{-# LANGUAGE CPP                   #-}+{-# LANGUAGE BlockArguments        #-} {-# LANGUAGE FlexibleInstances     #-}+{-# LANGUAGE GADTs                 #-}+{-# LANGUAGE LambdaCase            #-} {-# LANGUAGE MultiParamTypeClasses #-} {-# LANGUAGE PatternGuards         #-}+{-# LANGUAGE PatternSynonyms       #-} {-# LANGUAGE ScopedTypeVariables   #-}+{-# LANGUAGE TemplateHaskell       #-}+{-# LANGUAGE TypeApplications      #-} {-# LANGUAGE TypeFamilies          #-} {-# LANGUAGE TypeOperators         #-} {-# LANGUAGE UndecidableInstances  #-}+{-# LANGUAGE ViewPatterns          #-} {-# OPTIONS_GHC -fno-warn-orphans #-} -- | -- Module      : Data.Array.Accelerate.Data.Either--- Copyright   : [2018] Trevor L. McDonell+-- Copyright   : [2018..2020] The Accelerate Team -- License     : BSD3 ----- Maintainer  : Trevor L. McDonell <tmcdonell@cse.unsw.edu.au>+-- Maintainer  : Trevor L. McDonell <trevor.mcdonell@gmail.com> -- Stability   : experimental -- Portability : non-portable (GHC extensions) --@@ -21,83 +27,67 @@  module Data.Array.Accelerate.Data.Either ( -  Either(..),-  left, right,+  Either(..), pattern Left_, pattern Right_,   either, isLeft, isRight, fromLeft, fromRight, lefts, rights,  ) where -import Data.Array.Accelerate.Analysis.Match-import Data.Array.Accelerate.Array.Sugar                            hiding ( (!), shape, ignore, toIndex )-import Data.Array.Accelerate.Language                               hiding ( chr )-import Data.Array.Accelerate.Prelude                                hiding ( filter )-import Data.Array.Accelerate.Product+import Data.Array.Accelerate.AST.Idx+import Data.Array.Accelerate.Language+import Data.Array.Accelerate.Lift+import Data.Array.Accelerate.Pattern.Either+import Data.Array.Accelerate.Prelude import Data.Array.Accelerate.Smart+import Data.Array.Accelerate.Sugar.Array                            ( Array, Vector )+import Data.Array.Accelerate.Sugar.Elt+import Data.Array.Accelerate.Sugar.Shape                            ( Shape, Slice, (:.) ) import Data.Array.Accelerate.Type  import Data.Array.Accelerate.Classes.Eq-import Data.Array.Accelerate.Classes.Num import Data.Array.Accelerate.Classes.Ord  import Data.Array.Accelerate.Data.Functor import Data.Array.Accelerate.Data.Monoid-#if __GLASGOW_HASKELL__ >= 800 import Data.Array.Accelerate.Data.Semigroup-#endif -import Data.Char import Data.Either                                                  ( Either(..) )-import Data.Maybe-import Data.Typeable-import Foreign.C.Types-import Prelude                                                      ( (.), ($), const, undefined, otherwise )----- | Lift a value into the 'Left' constructor----left :: forall a b. (Elt a, Elt b) => Exp a -> Exp (Either a b)-left a = lift (Left a :: Either (Exp a) (Exp b))---- | Lift a value into the 'Right' constructor----right :: forall a b. (Elt a, Elt b) => Exp b -> Exp (Either a b)-right b = lift (Right b :: Either (Exp a) (Exp b))------ See Note: [lifting Nothing]+import Prelude                                                      ( (.), ($) )   -- | Return 'True' if the argument is a 'Left'-value -- isLeft :: (Elt a, Elt b) => Exp (Either a b) -> Exp Bool-isLeft x = tag x == 0+isLeft = not . isRight  -- | Return 'True' if the argument is a 'Right'-value -- isRight :: (Elt a, Elt b) => Exp (Either a b) -> Exp Bool-isRight x = tag x == 1+isRight (Exp e) = Exp $ SmartExp $ (SmartExp $ Prj PairIdxLeft e) `Pair` SmartExp Nil+  -- TLM: This is a sneaky hack because we know that the tag bits for Right+  -- and True are identical.  -- | The 'fromLeft' function extracts the element out of the 'Left' constructor. -- If the argument was actually 'Right', you will get an undefined value -- instead. -- fromLeft :: (Elt a, Elt b) => Exp (Either a b) -> Exp a-fromLeft x = Exp $ SuccTupIdx ZeroTupIdx `Prj` x+fromLeft (Exp e) = Exp $ SmartExp $ Prj PairIdxRight $ SmartExp $ Prj PairIdxLeft $ SmartExp $ Prj PairIdxRight e  -- | The 'fromRight' function extracts the element out of the 'Right' -- constructor. If the argument was actually 'Left', you will get an undefined -- value instead. -- fromRight :: (Elt a, Elt b) => Exp (Either a b) -> Exp b-fromRight x = Exp $ ZeroTupIdx `Prj` x+fromRight (Exp e) = Exp $ SmartExp $ Prj PairIdxRight $ SmartExp $ Prj PairIdxRight e  -- | The 'either' function performs case analysis on the 'Either' type. If the -- value is @'Left' a@, apply the first function to @a@; if it is @'Right' b@, -- apply the second function to @b@. -- either :: (Elt a, Elt b, Elt c) => (Exp a -> Exp c) -> (Exp b -> Exp c) -> Exp (Either a b) -> Exp c-either f g x =-  cond (isLeft x) (f (fromLeft x)) (g (fromRight x))-+either f g = match \case+  Left_  x -> f x+  Right_ x -> g x  -- | Extract from the array of 'Either' all of the 'Left' elements, together -- with a segment descriptor indicating how many elements along each dimension@@ -106,7 +96,7 @@ lefts :: (Shape sh, Slice sh, Elt a, Elt b)       => Acc (Array (sh:.Int) (Either a b))       -> Acc (Vector a, Array sh Int)-lefts es = filter' (map isLeft es) (map fromLeft es)+lefts es = compact (map isLeft es) (map fromLeft es)  -- | Extract from the array of 'Either' all of the 'Right' elements, together -- with a segment descriptor indicating how many elements along each dimension@@ -115,131 +105,32 @@ rights :: (Shape sh, Slice sh, Elt a, Elt b)        => Acc (Array (sh:.Int) (Either a b))        -> Acc (Vector b, Array sh Int)-rights es = filter' (map isRight es) (map fromRight es)+rights es = compact (map isRight es) (map fromRight es)   instance Elt a => Functor (Either a) where-  fmap f = either left (right . f)+  fmap f = either Left_ (Right_ . f)  instance (Eq a, Eq b) => Eq (Either a b) where-  ex == ey = isLeft  ex && isLeft  ey ? ( fromLeft ex  == fromLeft ey-           , isRight ex && isRight ey ? ( fromRight ex == fromRight ey-           , {- else -}                   constant False ))+  (==) = match go+    where+      go (Left_ x)  (Left_ y)  = x == y+      go (Right_ x) (Right_ y) = x == y+      go _          _          = False_  instance (Ord a, Ord b) => Ord (Either a b) where-  compare ex ey = isLeft  ex && isLeft  ey ? ( compare (fromLeft ex) (fromLeft ey)-                , isRight ex && isRight ey ? ( compare (fromRight ex) (fromRight ey)-                , {- else -}                   compare (tag ex) (tag ey) ))+  compare = match go+    where+      go (Left_ x)  (Left_ y)  = compare x y+      go (Right_ x) (Right_ y) = compare x y+      go Left_{}    Right_{}   = LT_+      go Right_{}   Left_{}    = GT_ -#if __GLASGOW_HASKELL__ >= 800 instance (Elt a, Elt b) => Semigroup (Exp (Either a b)) where   ex <> ey = isLeft ex ? ( ey, ex )-#endif -tag :: (Elt a, Elt b) => Exp (Either a b) -> Exp Word8-tag x = Exp $ SuccTupIdx (SuccTupIdx ZeroTupIdx) `Prj` x--type instance EltRepr (Either a b) = TupleRepr (Word8, EltRepr a, EltRepr b)--instance (Elt a, Elt b) => Elt (Either a b) where-  eltType _ = eltType (undefined::(Word8,a,b))-  toElt ((((),0),a),_)  = Left  (toElt a)-  toElt (_         ,b)  = Right (toElt b)-  fromElt (Left a)      = ((((),0), fromElt a), undef' (eltType (undefined::b)))-  fromElt (Right b)     = ((((),1), undef' (eltType (undefined::a))), fromElt b)--instance (Elt a, Elt b) => IsProduct Elt (Either a b) where-  type ProdRepr (Either a b) = ProdRepr (Word8, a, b)-  toProd _ ((((),0),a),_) = Left a-  toProd _ (_         ,b) = Right b-  fromProd _ (Left a)   = ((((), 0), a), toElt (undef' (eltType (undefined::b))))-  fromProd _ (Right b)  = ((((), 1), toElt (undef' (eltType (undefined::a)))), b)-  prod cst _ = prod cst (undefined::(Word8,a,b))- instance (Lift Exp a, Lift Exp b, Elt (Plain a), Elt (Plain b)) => Lift Exp (Either a b) where   type Plain (Either a b) = Either (Plain a) (Plain b)-  lift (Left a)  = Exp . Tuple $ NilTup `SnocTup` constant 0 `SnocTup` lift a `SnocTup` undef-  lift (Right b) = Exp . Tuple $ NilTup `SnocTup` constant 1 `SnocTup` undef  `SnocTup` lift b----- Utilities--- ------------- We need an undefined value for the Nothing case. We just fill this with--- zeros, though it would be better if we can actually do nothing, and leave--- those value in memory undefined.----undef' :: TupleType t -> t-undef' TypeRunit         = ()-undef' (TypeRpair ta tb) = (undef' ta, undef' tb)-undef' (TypeRscalar s)   = scalar s--scalar :: ScalarType t -> t-scalar (SingleScalarType t) = single t-scalar (VectorScalarType t) = vector t--single :: SingleType t -> t-single (NumSingleType    t) = num t-single (NonNumSingleType t) = nonnum t--vector :: VectorType t -> t-vector (Vector2Type t)  = let x = single t in V2 x x-vector (Vector3Type t)  = let x = single t in V3 x x x-vector (Vector4Type t)  = let x = single t in V4 x x x x-vector (Vector8Type t)  = let x = single t in V8 x x x x x x x x-vector (Vector16Type t) = let x = single t in V16 x x x x x x x x x x x x x x x x--num :: NumType t -> t-num (IntegralNumType t) | IntegralDict <- integralDict t = 0-num (FloatingNumType t) | FloatingDict <- floatingDict t = 0--nonnum :: NonNumType t -> t-nonnum TypeBool{}   = False-nonnum TypeChar{}   = chr 0-nonnum TypeCChar{}  = CChar 0-nonnum TypeCSChar{} = CSChar 0-nonnum TypeCUChar{} = CUChar 0---filter'-    :: forall sh e. (Shape sh, Slice sh, Elt e)-    => Acc (Array (sh:.Int) Bool)     -- tags-    -> Acc (Array (sh:.Int) e)        -- values-    -> Acc (Vector e, Array sh Int)-filter' keep arr-  | Just Refl <- matchShapeType (undefined::sh) (undefined::Z)-  = let-        (target, len)   = unlift $ scanl' (+) 0 (map boolToInt keep)-        prj ix          = keep!ix ? ( index1 (target!ix), ignore )-        dummy           = fill (index1 (the len)) undef-        result          = permute const dummy prj arr-    in-    null keep ?| ( lift (emptyArray, fill (constant Z) 0)-                 , lift (result, len)-                 )-  | otherwise-  = let-        sz              = indexTail (shape arr)-        (target, len)   = unlift $ scanl' (+) 0 (map boolToInt keep)-        (offset, valid) = unlift $ scanl' (+) 0 (flatten len)-        prj ix          = cond (keep!ix)-                               (index1 $ offset!index1 (toIndex sz (indexTail ix)) + target!ix)-                               ignore-        dummy           = fill (index1 (the valid)) undef-        result          = permute const dummy prj arr-    in-    null keep ?| ( lift (emptyArray, fill sz 0)-                 , lift (result, len)-                 )--emptyArray :: (Shape sh, Elt e) => Acc (Array sh e)-emptyArray = fill (constant empty) undef--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+  lift (Left a)  = Left_ (lift a)+  lift (Right b) = Right_ (lift b) 
src/Data/Array/Accelerate/Data/Fold.hs view
@@ -5,10 +5,10 @@ {-# LANGUAGE TypeOperators     #-} -- | -- Module      : Data.Array.Accelerate.Data.Fold--- Copyright   : [2016..2017] Trevor L. McDonell+-- Copyright   : [2016..2020] The Accelerate Team -- License     : BSD3 ----- Maintainer  : Trevor L. McDonell <tmcdonell@cse.unsw.edu.au>+-- Maintainer  : Trevor L. McDonell <trevor.mcdonell@gmail.com> -- Stability   : experimental -- Portability : non-portable (GHC extensions) --@@ -26,12 +26,19 @@  ) where -import Data.Array.Accelerate                                        hiding ( fold, sum, product, length )+import Data.Array.Accelerate.Classes.Floating                       as A+import Data.Array.Accelerate.Classes.Fractional                     as A+import Data.Array.Accelerate.Classes.Num                            as A import Data.Array.Accelerate.Data.Monoid-import qualified Data.Array.Accelerate                              as A+import Data.Array.Accelerate.Language                               as A+import Data.Array.Accelerate.Lift+import Data.Array.Accelerate.Smart                                  ( Acc, Exp, constant )+import Data.Array.Accelerate.Sugar.Array+import Data.Array.Accelerate.Sugar.Elt+import Data.Array.Accelerate.Sugar.Shape -import Control.Applicative                                          as P import Prelude                                                      hiding ( sum, product, length )+import Control.Applicative                                          as P import qualified Prelude                                            as P  
src/Data/Array/Accelerate/Data/Functor.hs view
@@ -1,18 +1,17 @@-{-# LANGUAGE CPP              #-} {-# LANGUAGE RebindableSyntax #-} -- | -- Module      : Data.Array.Accelerate.Data.Functor--- Copyright   : [2018] Trevor L. McDonell+-- Copyright   : [2018..2020] The Accelerate Team -- License     : BSD3 ----- Maintainer  : Trevor L. McDonell <tmcdonell@cse.unsw.edu.au>+-- Maintainer  : Trevor L. McDonell <trevor.mcdonell@gmail.com> -- Stability   : experimental -- Portability : non-portable (GHC extensions) -- -- A functor performs a uniform action over a parameterised type -- -- This is essentially the same as the standard Haskell 'Prelude.Functor' class,--- lifted to Accelarete 'Exp' terms.+-- lifted to Accelerate 'Exp' terms. -- -- @since 1.2.0.0 --@@ -26,16 +25,13 @@  ) where -import Data.Array.Accelerate.Array.Sugar+import Data.Array.Accelerate.Sugar.Elt import Data.Array.Accelerate.Lift import Data.Array.Accelerate.Smart  import Data.Monoid-import Prelude                                                      ( flip )-#if __GLASGOW_HASKELL__ >= 800 import Data.Semigroup-#endif-import Prelude                                                      ( (.), const )+import Prelude                                                      ( (.), const, flip )   -- | The 'Functor' class is used for scalar types which can be mapped over.@@ -91,11 +87,9 @@ instance Functor Product where   fmap f = lift1 (fmap f) -#if __GLASGOW_HASKELL__ >= 800 instance Functor Min where   fmap f = lift1 (fmap f)  instance Functor Max where   fmap f = lift1 (fmap f)-#endif 
src/Data/Array/Accelerate/Data/Maybe.hs view
@@ -1,18 +1,24 @@-{-# LANGUAGE CPP                   #-}+{-# LANGUAGE BlockArguments        #-} {-# LANGUAGE FlexibleInstances     #-}+{-# LANGUAGE GADTs                 #-}+{-# LANGUAGE LambdaCase            #-} {-# LANGUAGE MultiParamTypeClasses #-} {-# LANGUAGE PatternGuards         #-}+{-# LANGUAGE PatternSynonyms       #-} {-# LANGUAGE ScopedTypeVariables   #-}+{-# LANGUAGE TemplateHaskell       #-}+{-# LANGUAGE TypeApplications      #-} {-# LANGUAGE TypeFamilies          #-} {-# LANGUAGE TypeOperators         #-} {-# LANGUAGE UndecidableInstances  #-}+{-# LANGUAGE ViewPatterns          #-} {-# OPTIONS_GHC -fno-warn-orphans #-} -- | -- Module      : Data.Array.Accelerate.Data.Maybe--- Copyright   : [2018] Trevor L. McDonell+-- Copyright   : [2018..2020] The Accelerate Team -- License     : BSD3 ----- Maintainer  : Trevor L. McDonell <tmcdonell@cse.unsw.edu.au>+-- Maintainer  : Trevor L. McDonell <trevor.mcdonell@gmail.com> -- Stability   : experimental -- Portability : non-portable (GHC extensions) --@@ -21,79 +27,60 @@  module Data.Array.Accelerate.Data.Maybe ( -  Maybe(..),-  just, nothing,+  Maybe(..), pattern Nothing_, pattern Just_,   maybe, isJust, isNothing, fromMaybe, fromJust, justs,  ) where -import Data.Array.Accelerate.Analysis.Match-import Data.Array.Accelerate.Array.Sugar                            hiding ( (!), shape, ignore, toIndex )-import Data.Array.Accelerate.Language                               hiding ( chr )-import Data.Array.Accelerate.Prelude                                hiding ( filter )-import Data.Array.Accelerate.Product+import Data.Array.Accelerate.AST.Idx+import Data.Array.Accelerate.Language+import Data.Array.Accelerate.Lift+import Data.Array.Accelerate.Pattern.Maybe+import Data.Array.Accelerate.Prelude import Data.Array.Accelerate.Smart+import Data.Array.Accelerate.Sugar.Array                            ( Array, Vector )+import Data.Array.Accelerate.Sugar.Elt+import Data.Array.Accelerate.Sugar.Shape                            ( Shape, Slice, (:.) ) import Data.Array.Accelerate.Type  import Data.Array.Accelerate.Classes.Eq-import Data.Array.Accelerate.Classes.Num import Data.Array.Accelerate.Classes.Ord  import Data.Array.Accelerate.Data.Functor import Data.Array.Accelerate.Data.Monoid-#if __GLASGOW_HASKELL__ >= 800 import Data.Array.Accelerate.Data.Semigroup-#endif -import Data.Char import Data.Maybe                                                   ( Maybe(..) )-import Data.Typeable-import Foreign.C.Types-import Prelude                                                      ( (.), ($), const, undefined, otherwise )+import Prelude                                                      ( ($), (.) )  --- | Lift a value into a 'Just' constructor----just :: Elt a => Exp a -> Exp (Maybe a)-just x = lift (Just x)---- | The 'Nothing' constructor----nothing :: forall a. Elt a => Exp (Maybe a)-nothing = lift (Nothing :: Maybe (Exp a))------ Note: [lifting Nothing]------ The lift instance for 'Nothing' uses our magic 'undef' term, meaning that our--- backends will know that we can leave this slot in the values array undefined.--- If we had instead written 'constant Nothing' this would result in writing an--- actual (unspecified) value into the values array, which is what we want to--- avoid.---- -- | Returns 'True' if the argument is 'Nothing' -- isNothing :: Elt a => Exp (Maybe a) -> Exp Bool-isNothing x = tag x == 0+isNothing = not . isJust  -- | Returns 'True' if the argument is of the form @Just _@ -- isJust :: Elt a => Exp (Maybe a) -> Exp Bool-isJust x = tag x == 1+isJust (Exp x) = Exp $ SmartExp $ (SmartExp $ Prj PairIdxLeft x) `Pair` SmartExp Nil+  -- TLM: This is a sneaky hack because we know that the tag bits for Just+  -- and True are identical.  -- | The 'fromMaybe' function takes a default value and a 'Maybe' value. If the -- 'Maybe' is 'Nothing', the default value is returned; otherwise, it returns -- the value contained in the 'Maybe'. -- fromMaybe :: Elt a => Exp a -> Exp (Maybe a) -> Exp a-fromMaybe d x = cond (isNothing x) d (fromJust x)+fromMaybe d = match \case+  Nothing_ -> d+  Just_ x  -> x  -- | The 'fromJust' function extracts the element out of the 'Just' constructor. -- If the argument was actually 'Nothing', you will get an undefined value -- instead. -- fromJust :: Elt a => Exp (Maybe a) -> Exp a-fromJust x = Exp $ ZeroTupIdx `Prj` x+fromJust (Exp x) = Exp $ SmartExp (PairIdxRight `Prj` SmartExp (PairIdxRight `Prj` x))  -- | The 'maybe' function takes a default value, a function, and a 'Maybe' -- value. If the 'Maybe' value is nothing, the default value is returned;@@ -101,8 +88,9 @@ -- the result -- maybe :: (Elt a, Elt b) => Exp b -> (Exp a -> Exp b) -> Exp (Maybe a) -> Exp b-maybe d f x = cond (isNothing x) d (f (fromJust x))-+maybe d f = match \case+  Nothing_ -> d+  Just_ x  -> f x  -- | Extract from an array all of the 'Just' values, together with a segment -- descriptor indicating how many elements along each dimension were returned.@@ -110,143 +98,39 @@ justs :: (Shape sh, Slice sh, Elt a)       => Acc (Array (sh:.Int) (Maybe a))       -> Acc (Vector a, Array sh Int)-justs xs = filter' (map isJust xs) (map fromJust xs)+justs xs = compact (map isJust xs) (map fromJust xs)   instance Functor Maybe where-  fmap f x = cond (isNothing x) (constant Nothing) (lift (Just (f (fromJust x))))+  fmap f = match \case+    Nothing_ -> Nothing_+    Just_ x  -> Just_ (f x)  instance Eq a => Eq (Maybe a) where-  ma == mb = cond (isNothing ma && isNothing mb) (constant True)-           $ cond (isJust ma    && isJust mb)    (fromJust ma == fromJust mb)-           $ constant False+  (==) = match go+    where+      go Nothing_  Nothing_  = True_+      go (Just_ x) (Just_ y) = x == y+      go _         _         = False_  instance Ord a => Ord (Maybe a) where-  compare ma mb = cond (isJust ma && isJust mb)-                       (compare (fromJust ma) (fromJust mb))-                       (compare (tag ma) (tag mb))+  compare = match go+    where+      go (Just_ x) (Just_ y)  = compare x y+      go Nothing_  Nothing_   = EQ_+      go Nothing_  Just_{}    = LT_+      go Just_{}   Nothing_{} = GT_  instance (Monoid (Exp a), Elt a) => Monoid (Exp (Maybe a)) where-  mempty        = constant Nothing-#if __GLASGOW_HASKELL__ < 804-  mappend ma mb = cond (isNothing ma) mb-                $ cond (isNothing mb) ma-                $ lift (Just (fromJust ma `mappend` fromJust mb))-#endif+  mempty = Nothing_ -#if __GLASGOW_HASKELL__ >= 800 instance (Semigroup (Exp a), Elt a) => Semigroup (Exp (Maybe a)) where   ma <> mb = cond (isNothing ma) mb            $ cond (isNothing mb) mb            $ lift (Just (fromJust ma <> fromJust mb))-#endif --tag :: Elt a => Exp (Maybe a) -> Exp Word8-tag x = Exp $ SuccTupIdx ZeroTupIdx `Prj` x---type instance EltRepr (Maybe a) = TupleRepr (Word8, EltRepr a)--instance Elt a => Elt (Maybe a) where-  eltType _        = eltType (undefined::(Word8,a))-  toElt (((),0),_) = Nothing-  toElt (_     ,x) = Just (toElt x)-  fromElt Nothing  = (((),0), undef' (eltType (undefined::a)))-  fromElt (Just a) = (((),1), fromElt a)--instance Elt a => IsProduct Elt (Maybe a) where-  type ProdRepr (Maybe a) = ProdRepr (Word8, a)-  toProd _ (((),0),_) = Nothing-  toProd _ (_,     x) = Just x-  fromProd _ Nothing  = (((), 0), toElt (undef' (eltType (undefined::a))))-  fromProd _ (Just a) = (((), 1), a)-  prod cst _ = prod cst (undefined :: (Word8,a))- instance (Lift Exp a, Elt (Plain a)) => Lift Exp (Maybe a) where   type Plain (Maybe a) = Maybe (Plain a)-  lift Nothing  = Exp . Tuple $ NilTup `SnocTup` constant 0 `SnocTup` undef-  lift (Just x) = Exp . Tuple $ NilTup `SnocTup` constant 1 `SnocTup` lift x----- Utilities--- ------------- We need an undefined value for the Nothing case. We just fill this with--- zeros, though it would be better if we can actually do nothing, and leave--- those value in memory undefined.----undef' :: TupleType t -> t-undef' TypeRunit         = ()-undef' (TypeRpair ta tb) = (undef' ta, undef' tb)-undef' (TypeRscalar s)   = scalar s--scalar :: ScalarType t -> t-scalar (SingleScalarType t) = single t-scalar (VectorScalarType t) = vector t--single :: SingleType t -> t-single (NumSingleType    t) = num t-single (NonNumSingleType t) = nonnum t--vector :: VectorType t -> t-vector (Vector2Type t)  = let x = single t in V2 x x-vector (Vector3Type t)  = let x = single t in V3 x x x-vector (Vector4Type t)  = let x = single t in V4 x x x x-vector (Vector8Type t)  = let x = single t in V8 x x x x x x x x-vector (Vector16Type t) = let x = single t in V16 x x x x x x x x x x x x x x x x--num :: NumType t -> t-num (IntegralNumType t) | IntegralDict <- integralDict t = 0-num (FloatingNumType t) | FloatingDict <- floatingDict t = 0--nonnum :: NonNumType t -> t-nonnum TypeBool{}   = False-nonnum TypeChar{}   = chr 0-nonnum TypeCChar{}  = CChar 0-nonnum TypeCSChar{} = CSChar 0-nonnum TypeCUChar{} = CUChar 0---filter'-    :: forall sh e. (Shape sh, Slice sh, Elt e)-    => Acc (Array (sh:.Int) Bool)     -- tags-    -> Acc (Array (sh:.Int) e)        -- values-    -> Acc (Vector e, Array sh Int)-filter' keep arr-  | Just Refl <- matchShapeType (undefined::sh) (undefined::Z)-  = let-        (target, len)   = unlift $ scanl' (+) 0 (map boolToInt keep)-        prj ix          = keep!ix ? ( index1 (target!ix), ignore )-        dummy           = fill (index1 (the len)) undef-        result          = permute const dummy prj arr-    in-    null keep ?| ( lift (emptyArray, fill (constant Z) 0)-                 , lift (result, len)-                 )-  | otherwise-  = let-        sz              = indexTail (shape arr)-        (target, len)   = unlift $ scanl' (+) 0 (map boolToInt keep)-        (offset, valid) = unlift $ scanl' (+) 0 (flatten len)-        prj ix          = cond (keep!ix)-                               (index1 $ offset!index1 (toIndex sz (indexTail ix)) + target!ix)-                               ignore-        dummy           = fill (index1 (the valid)) undef-        result          = permute const dummy prj arr-    in-    null keep ?| ( lift (emptyArray, fill sz 0)-                 , lift (result, len)-                 )--emptyArray :: (Shape sh, Elt e) => Acc (Array sh e)-emptyArray = fill (constant empty) undef--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+  lift Nothing  = Nothing_+  lift (Just a) = Just_ (lift a) 
src/Data/Array/Accelerate/Data/Monoid.hs view
@@ -3,18 +3,21 @@ {-# LANGUAGE FlexibleContexts      #-} {-# LANGUAGE FlexibleInstances     #-} {-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE PatternSynonyms       #-} {-# LANGUAGE ScopedTypeVariables   #-}+{-# LANGUAGE TypeApplications      #-} {-# LANGUAGE TypeFamilies          #-}+{-# LANGUAGE ViewPatterns          #-} {-# OPTIONS_GHC -fno-warn-orphans #-} #if __GLASGOW_HASKELL__ >= 806 {-# LANGUAGE UndecidableInstances  #-} #endif -- | -- Module      : Data.Array.Accelerate.Data.Monoid--- Copyright   : [2016..2017] Trevor L. McDonell+-- Copyright   : [2016..2020] The Accelerate Team -- License     : BSD3 ----- Maintainer  : Trevor L. McDonell <tmcdonell@cse.unsw.edu.au>+-- Maintainer  : Trevor L. McDonell <trevor.mcdonell@gmail.com> -- Stability   : experimental -- Portability : non-portable (GHC extensions) --@@ -27,62 +30,48 @@    Monoid(..), (<>), -  Sum(..),-  Product(..),+  Sum(..), pattern Sum_,+  Product(..), pattern Product_,  ) where -import Data.Array.Accelerate.Array.Sugar import Data.Array.Accelerate.Classes.Bounded import Data.Array.Accelerate.Classes.Eq import Data.Array.Accelerate.Classes.Num import Data.Array.Accelerate.Classes.Ord+import Data.Array.Accelerate.Data.Semigroup                         () import Data.Array.Accelerate.Language import Data.Array.Accelerate.Lift-import Data.Array.Accelerate.Product+import Data.Array.Accelerate.Pattern import Data.Array.Accelerate.Smart+import Data.Array.Accelerate.Sugar.Elt import Data.Array.Accelerate.Type-#if __GLASGOW_HASKELL__ >= 800-import Data.Array.Accelerate.Data.Semigroup                         ()-#endif  import Data.Function-#if __GLASGOW_HASKELL__ >= 800 import Data.Monoid                                                  hiding ( (<>) ) import Data.Semigroup-#else-import Data.Monoid-#endif-import Prelude                                                      ( undefined ) import qualified Prelude                                            as P   -- Sum: Monoid under addition -- -------------------------- -type instance EltRepr (Sum a) = ((), EltRepr a)--instance Elt a => Elt (Sum a) where-  eltType _       = TypeRpair TypeRunit (eltType (undefined::a))-  toElt ((),x)    = Sum (toElt x)-  fromElt (Sum x) = ((), fromElt x)+pattern Sum_ :: Elt a => Exp a -> Exp (Sum a)+pattern Sum_ x = Pattern x+{-# COMPLETE Sum_ #-} -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 Elt a => Elt (Sum a)  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+  lift (Sum a)       = Sum_ (lift a)  instance Elt a => Unlift Exp (Sum (Exp a)) where-  unlift t = Sum . Exp $ ZeroTupIdx `Prj` t+  unlift (Sum_ a) = Sum a  instance Bounded a => P.Bounded (Exp (Sum a)) where-  minBound = lift $ Sum (minBound :: Exp a)-  maxBound = lift $ Sum (maxBound :: Exp a)+  minBound = Sum_ minBound+  maxBound = Sum_ maxBound  instance Num a => P.Num (Exp (Sum a)) where   (+)             = lift2 ((+) :: Sum (Exp a) -> Sum (Exp a) -> Sum (Exp a))@@ -102,53 +91,37 @@   (>)     = 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+  min x y = Sum_ $ lift2 (min `on` getSum) x y+  max x y = Sum_ $ lift2 (max `on` getSum) x y  instance Num a => Monoid (Exp (Sum a)) where-  mempty  = 0-#if __GLASGOW_HASKELL__ <  804-#if __GLASGOW_HASKELL__ >= 800-  mappend = (<>)-#else-  mappend = lift2 (mappend :: Sum (Exp a) -> Sum (Exp a) -> Sum (Exp a))-#endif-#endif+  mempty = 0 -#if __GLASGOW_HASKELL__ >= 800 -- | @since 1.2.0.0 instance Num a => Semigroup (Exp (Sum a)) where-  (<>)       = (+)-  stimes n x = lift . Sum $ P.fromIntegral n * getSum (unlift x :: Sum (Exp a))-#endif+  (<>)              = (+)+  stimes n (Sum_ x) = Sum_ $ P.fromIntegral n * x   -- Product: Monoid under multiplication -- ------------------------------------ -type instance EltRepr (Product a) = ((), EltRepr a)--instance Elt a => Elt (Product a) where-  eltType _       = TypeRpair TypeRunit (eltType (undefined::a))-  toElt ((),x)    = Product (toElt x)-  fromElt (Product x) = ((), fromElt x)+pattern Product_ :: Elt a => Exp a -> Exp (Product a)+pattern Product_ x = Pattern x+{-# COMPLETE Product_ #-} -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 Elt a => Elt (Product a)  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+  lift (Product a)       = Product_ (lift a)  instance Elt a => Unlift Exp (Product (Exp a)) where-  unlift t = Product . Exp $ ZeroTupIdx `Prj` t+  unlift (Product_ a) = Product a  instance Bounded a => P.Bounded (Exp (Product a)) where-  minBound = lift $ Product (minBound :: Exp a)-  maxBound = lift $ Product (maxBound :: Exp a)+  minBound = Product_ minBound+  maxBound = Product_ maxBound  instance Num a => P.Num (Exp (Product a)) where   (+)             = lift2 ((+) :: Product (Exp a) -> Product (Exp a) -> Product (Exp a))@@ -168,77 +141,33 @@   (>)     = 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+  min x y = Product_ $ lift2 (min `on` getProduct) x y+  max x y = Product_ $ lift2 (max `on` getProduct) x y  instance Num a => Monoid (Exp (Product a)) where-  mempty  = 1-#if __GLASGOW_HASKELL__ <  804-#if __GLASGOW_HASKELL__ >= 800-  mappend = (<>)-#else-  mappend = lift2 (mappend :: Product (Exp a) -> Product (Exp a) -> Product (Exp a))-#endif-#endif+  mempty = 1 -#if __GLASGOW_HASKELL__ >= 800 -- | @since 1.2.0.0 instance Num a => Semigroup (Exp (Product a)) where-  (<>)       = (*)-  stimes n x = lift . Product $ getProduct (unlift x :: Product (Exp a)) ^ (P.fromIntegral n :: Exp Int)-#endif+  (<>)                  = (*)+  stimes n (Product_ x) = Product_ $ x ^ (P.fromIntegral n :: Exp Int)   -- Instances for unit and tuples -- -----------------------------  instance Monoid (Exp ()) where-  mempty      = constant ()-#if __GLASGOW_HASKELL__ <  804-#if __GLASGOW_HASKELL__ >= 800-  mappend     = (<>)-#else-  mappend _ _ = constant ()-#endif-#endif+  mempty = constant () --- TLM: despite what -Wcompat tells us, we can not use the canonical--- implementation `mappend = (<>)` on GHC-8.0 and 8.2 without changing the--- instance heads to include a `Semigroup` constraint.--- instance (Elt a, Elt b, Monoid (Exp a), Monoid (Exp b)) => Monoid (Exp (a,b)) where-  mempty      = lift (mempty :: Exp a, mempty :: Exp b)-#if __GLASGOW_HASKELL__ < 804-  mappend x y = let (a1,b1) = unlift x  :: (Exp a, Exp b)-                    (a2,b2) = unlift y-                in-                lift (a1 `mappend` a2, b1 `mappend` b2)-#endif+  mempty = T2 mempty mempty  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)-#if __GLASGOW_HASKELL__ < 804-  mappend x y = let (a1,b1,c1) = unlift x  :: (Exp a, Exp b, Exp c)-                    (a2,b2,c2) = unlift y-                in-                lift (a1 `mappend` a2, b1 `mappend` b2, c1 `mappend` c2)-#endif+  mempty = T3 mempty mempty mempty  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)-#if __GLASGOW_HASKELL__ < 804-  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 `mappend` a2, b1 `mappend` b2, c1 `mappend` c2, d1 `mappend` d2)-#endif+  mempty = T4 mempty mempty mempty mempty  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)-#if __GLASGOW_HASKELL__ < 804-  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 `mappend` a2, b1 `mappend` b2, c1 `mappend` c2, d1 `mappend` d2, e1 `mappend` e2)-#endif+  mempty = T5 mempty mempty mempty mempty mempty 
+ src/Data/Array/Accelerate/Data/Ratio.hs view
@@ -0,0 +1,141 @@+{-# LANGUAGE FlexibleContexts      #-}+{-# LANGUAGE FlexibleInstances     #-}+{-# LANGUAGE MonoLocalBinds        #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE PatternSynonyms       #-}+{-# LANGUAGE RebindableSyntax      #-}+{-# LANGUAGE StandaloneDeriving    #-}+{-# LANGUAGE TypeApplications      #-}+{-# LANGUAGE UndecidableInstances  #-}+{-# OPTIONS_GHC -fno-warn-orphans #-}+-- |+-- Module      : Data.Array.Accelerate.Data.Ratio+-- Copyright   : [2019..2020] The Accelerate Team+-- License     : BSD3+--+-- Maintainer  : Trevor L. McDonell <trevor.mcdonell@gmail.com>+-- Stability   : experimental+-- Portability : non-portable (GHC extensions)+--+-- Standard functions on rational numbers+--+-- @since 1.3.0.0+--++module Data.Array.Accelerate.Data.Ratio (++  Ratio, (%),+  pattern (:%), numerator, denominator,++) where++import Data.Array.Accelerate.Language+import Data.Array.Accelerate.Pattern+import Data.Array.Accelerate.Prelude+import Data.Array.Accelerate.Smart+import Data.Array.Accelerate.Sugar.Elt+import Data.Array.Accelerate.Type++import Data.Array.Accelerate.Classes.Enum+import Data.Array.Accelerate.Classes.Eq+import Data.Array.Accelerate.Classes.Fractional+import Data.Array.Accelerate.Classes.FromIntegral+import Data.Array.Accelerate.Classes.Integral+import Data.Array.Accelerate.Classes.Num+import Data.Array.Accelerate.Classes.Ord+import Data.Array.Accelerate.Classes.RealFrac+import Data.Array.Accelerate.Classes.ToFloating++import Text.Printf+import Data.Ratio                                                   ( Ratio )+import Prelude                                                      ( ($), String, error, unlines )+import qualified Data.Ratio                                         as P+import qualified Prelude                                            as P+++instance Elt a => Elt (Ratio a)++pattern (:%) :: Elt a => Exp a -> Exp a -> Exp (Ratio a)+pattern (:%) { numerator, denominator } = Pattern (numerator, denominator)+{-# COMPLETE (:%) #-}+++-- | 'reduce' is a subsidiary function used only in this module. It normalises+-- a ratio by dividing both numerator and denominator by their greatest common+-- divisor.+--+reduce ::  Integral a => Exp a -> Exp a -> Exp (Ratio a)+reduce x y =+  if y == 0+    then infinity+    else let d = gcd x y+         in  (x `quot` d) :% (y `quot` d)++-- | Form the ratio of two integral numbers+--+infixl 7 %+(%) :: Integral a => Exp a -> Exp a -> Exp (Ratio a)+x % y =  reduce (x * signum y) (abs y)++infinity :: Integral a => Exp (Ratio a)+infinity = 1 :% 0+++-- Instances+-- ---------++instance Integral a => Eq (Ratio a) where+  (x :% y) == (z :% w) = x == z && y == w+  (x :% y) /= (z :% w) = x /= z || y /= w++instance Integral a => Ord (Ratio a)  where+  (x :% y) <= (z :% w)  =  x * w <= z * y+  (x :% y) <  (z :% w)  =  x * w <  z * y++instance Integral a => P.Num (Exp (Ratio a)) where+  (x :% y) + (z :% w) = reduce (x*w + z*y) (y*w)+  (x :% y) - (z :% w) = reduce (x*w - z*y) (y*w)+  (x :% y) * (z :% w) = reduce (x * z) (y * w)+  negate (x:%y)       = (-x) :% y+  abs (x:%y)          = abs x :% y+  signum (x:%_)       = signum x :% 1+  fromInteger x       = fromInteger x :% 1++instance Integral a => P.Fractional (Exp (Ratio a))  where+  (x :% y) / (z :% w) = (x*w) % (y*z)+  recip (x :% y)      =+    if x == 0 then infinity else+    if x <  0 then negate y :% negate x+              else y :% x+  fromRational r = fromInteger (P.numerator r) % fromInteger (P.denominator r)++instance (Integral a, FromIntegral a Int64) => RealFrac (Ratio a) where+  properFraction (x :% y) =+    let (q,r) = quotRem x y+    in  (fromIntegral (fromIntegral q :: Exp Int64), r :% y)+++instance (Integral a, ToFloating a b) => ToFloating (Ratio a) b where+  toFloating (x :% y) =+    let x' :% y' = reduce x y+    in  toFloating x' / toFloating y'++instance (FromIntegral a b, Integral b) => FromIntegral a (Ratio b) where+  fromIntegral x = fromIntegral x :% 1++instance Integral a => P.Enum (Exp (Ratio a))  where+  succ x   = x + 1+  pred x   = x - 1+  toEnum   = preludeError "Enum" "toEnum"+  fromEnum = preludeError "Enum" "fromEnum"+++preludeError :: String -> String -> a+preludeError x y+  = error+  $ unlines [ printf "Prelude.%s is not supported for Accelerate types" y+            , ""+            , printf "These Prelude.%s instances are present only to fulfil superclass" x+            , "constraints for subsequent classes in the standard Haskell numeric hierarchy."+            ]+
src/Data/Array/Accelerate/Data/Semigroup.hs view
@@ -3,8 +3,10 @@ {-# LANGUAGE FlexibleContexts      #-} {-# LANGUAGE FlexibleInstances     #-} {-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE PatternSynonyms       #-} {-# LANGUAGE RebindableSyntax      #-} {-# LANGUAGE ScopedTypeVariables   #-}+{-# LANGUAGE TypeApplications      #-} {-# LANGUAGE TypeFamilies          #-} {-# LANGUAGE ViewPatterns          #-} {-# OPTIONS_GHC -fno-warn-orphans #-}@@ -13,10 +15,10 @@ #endif -- | -- Module      : Data.Array.Accelerate.Data.Semigroup--- Copyright   : [2018] Trevor L. McDonell+-- Copyright   : [2018..2020] The Accelerate Team -- License     : BSD3 ----- Maintainer  : Trevor L. McDonell <tmcdonell@cse.unsw.edu.au>+-- Maintainer  : Trevor L. McDonell <trevor.mcdonell@gmail.com> -- Stability   : experimental -- Portability : non-portable (GHC extensions) --@@ -29,47 +31,38 @@    Semigroup(..), -  Min(..),-  Max(..),+  Min(..), pattern Min_,+  Max(..), pattern Max_,  ) where -import Data.Array.Accelerate.Array.Sugar import Data.Array.Accelerate.Classes.Bounded import Data.Array.Accelerate.Classes.Eq import Data.Array.Accelerate.Classes.Num import Data.Array.Accelerate.Classes.Ord import Data.Array.Accelerate.Lift-import Data.Array.Accelerate.Product+import Data.Array.Accelerate.Pattern import Data.Array.Accelerate.Smart-import Data.Array.Accelerate.Type+import Data.Array.Accelerate.Sugar.Elt  import Data.Function import Data.Monoid                                                  ( Monoid(..) ) import Data.Semigroup-import Prelude                                                      ( undefined ) import qualified Prelude                                            as P  -type instance EltRepr (Min a) = ((), EltRepr a)--instance Elt a => Elt (Min a) where-  eltType _       = TypeRpair TypeRunit (eltType (undefined::a))-  toElt ((),x)    = Min (toElt x)-  fromElt (Min x) = ((), fromElt x)+pattern Min_ :: Elt a => Exp a -> Exp (Min a)+pattern Min_ x = Pattern x+{-# COMPLETE Min_ #-} -instance Elt a => IsProduct Elt (Min a) where-  type ProdRepr (Min a) = ((), a)-  toProd _ ((),a)    = Min a-  fromProd _ (Min a) = ((),a)-  prod _ _           = ProdRsnoc ProdRunit+instance Elt a => Elt (Min a)  instance (Lift Exp a, Elt (Plain a)) => Lift Exp (Min a) where   type Plain (Min a) = Min (Plain a)-  lift (Min a)       = Exp $ Tuple $ NilTup `SnocTup` lift a+  lift (Min a)       = Min_ (lift a)  instance Elt a => Unlift Exp (Min (Exp a)) where-  unlift t = Min . Exp $ ZeroTupIdx `Prj` t+  unlift (Min_ a) = Min a  instance Bounded a => P.Bounded (Exp (Min a)) where   minBound = lift $ Min (minBound :: Exp a)@@ -105,29 +98,22 @@   mappend = (<>)  -type instance EltRepr (Max a) = ((), EltRepr a)--instance Elt a => Elt (Max a) where-  eltType _       = TypeRpair TypeRunit (eltType (undefined::a))-  toElt ((),x)    = Max (toElt x)-  fromElt (Max x) = ((), fromElt x)+pattern Max_ :: Elt a => Exp a -> Exp (Max a)+pattern Max_ x = Pattern x+{-# COMPLETE Max_ #-} -instance Elt a => IsProduct Elt (Max a) where-  type ProdRepr (Max a) = ((), a)-  toProd _ ((),a)    = Max a-  fromProd _ (Max a) = ((),a)-  prod _ _           = ProdRsnoc ProdRunit+instance Elt a => Elt (Max a)  instance (Lift Exp a, Elt (Plain a)) => Lift Exp (Max a) where   type Plain (Max a) = Max (Plain a)-  lift (Max a)       = Exp $ Tuple $ NilTup `SnocTup` lift a+  lift (Max a)       = Max_ (lift a)  instance Elt a => Unlift Exp (Max (Exp a)) where-  unlift t = Max . Exp $ ZeroTupIdx `Prj` t+  unlift (Max_ a) = Max a  instance Bounded a => P.Bounded (Exp (Max a)) where-  minBound = lift $ Max (minBound :: Exp a)-  maxBound = lift $ Max (maxBound :: Exp a)+  minBound = Max_ minBound+  maxBound = Max_ maxBound  instance Num a => P.Num (Exp (Max a)) where   (+)           = lift2 ((+) :: Max (Exp a) -> Max (Exp a) -> Max (Exp a))@@ -147,11 +133,11 @@   (>)     = lift2 ((>) `on` getMax)   (<=)    = lift2 ((<=) `on` getMax)   (>=)    = lift2 ((>=) `on` getMax)-  min x y = lift . Max $ lift2 (min `on` getMax) x y-  max x y = lift . Max $ lift2 (max `on` getMax) x y+  min x y = Max_ $ lift2 (min `on` getMax) x y+  max x y = Max_ $ lift2 (max `on` getMax) x y  instance Ord a => Semigroup (Exp (Max a)) where-  x <> y  = lift . Max $ lift2 (max `on` getMax) x y+  x <> y  = Max_ $ lift2 (max `on` getMax) x y   stimes  = stimesIdempotent  instance (Ord a, Bounded a) => Monoid (Exp (Max a)) where
src/Data/Array/Accelerate/Debug.hs view
@@ -2,11 +2,10 @@ {-# OPTIONS_HADDOCK hide #-} -- | -- Module      : Data.Array.Accelerate.Debug--- Copyright   : [2008..2017] Manuel M T Chakravarty, Gabriele Keller---               [2009..2017] Trevor L. McDonell+-- Copyright   : [2008..2020] The Accelerate Team -- License     : BSD3 ----- Maintainer  : Trevor L. McDonell <tmcdonell@cse.unsw.edu.au>+-- Maintainer  : Trevor L. McDonell <trevor.mcdonell@gmail.com> -- Stability   : experimental -- Portability : non-portable (GHC extensions) --@@ -20,8 +19,6 @@   module Debug,    dumpGraph,-  dumpSimplStats,-   debuggingIsEnabled,   monitoringIsEnabled,   boundsChecksAreEnabled,@@ -98,21 +95,6 @@ #endif  --- | Display simplifier statistics. The counts are reset afterwards.----{-# INLINEABLE dumpSimplStats #-}-dumpSimplStats :: MonadIO m => m ()-#ifdef ACCELERATE_DEBUG-dumpSimplStats = do-  liftIO $ Debug.when dump_simpl_stats $ do-    stats <- simplCount-    putTraceMsg (show stats)-    resetSimplCount-#else-dumpSimplStats = return ()-#endif-- -- | Write a representation of the given input (a closed array expression or -- function) to file in Graphviz dot format in the temporary directory. --@@ -147,3 +129,4 @@ getProcessID = return 0xaaaa #endif #endif+
+ src/Data/Array/Accelerate/Debug/Clock.hs view
@@ -0,0 +1,27 @@+{-# LANGUAGE ForeignFunctionInterface #-}+{-# LANGUAGE TemplateHaskell          #-}+{-# OPTIONS_GHC -fobject-code #-}+-- |+-- Module      : Data.Array.Accelerate.Debug.Clock+-- Copyright   : [2016..2020] The Accelerate Team+-- License     : BSD3+--+-- Maintainer  : Trevor L. McDonell <trevor.mcdonell@gmail.com>+-- Stability   : experimental+-- Portability : non-portable (GHC extensions)+--++module Data.Array.Accelerate.Debug.Clock+  where++import Language.Haskell.TH.Syntax++foreign import ccall unsafe "clock_gettime_monotonic_seconds" getMonotonicTime :: IO Double+foreign import ccall unsafe "clock_gettime_elapsed_seconds"   getProgramTime   :: IO Double++-- SEE: [linking to .c files]+--+runQ $ do+  addForeignFilePath LangC "cbits/clock.c"+  return []+
src/Data/Array/Accelerate/Debug/Flags.hs view
@@ -1,17 +1,17 @@ {-# LANGUAGE CPP                      #-} {-# LANGUAGE ForeignFunctionInterface #-}+{-# LANGUAGE TemplateHaskell          #-} {-# LANGUAGE TypeOperators            #-}-{-# OPTIONS_GHC -fno-warn-unused-imports #-}-#if __GLASGOW_HASKELL__ >= 800-{-# OPTIONS_GHC -fno-warn-unused-top-binds #-}-#endif+{-# OPTIONS_GHC -fno-warn-missing-signatures #-}+{-# OPTIONS_GHC -fno-warn-unused-imports     #-}+{-# OPTIONS_GHC -fno-warn-unused-top-binds   #-}+{-# OPTIONS_GHC -fobject-code                #-} -- SEE: [linking to .c files] -- | -- Module      : Data.Array.Accelerate.Debug.Flags--- Copyright   : [2008..2017] Manuel M T Chakravarty, Gabriele Keller---               [2009..2017] Trevor L. McDonell+-- Copyright   : [2008..2020] The Accelerate Team -- License     : BSD3 ----- Maintainer  : Trevor L. McDonell <tmcdonell@cse.unsw.edu.au>+-- Maintainer  : Trevor L. McDonell <trevor.mcdonell@gmail.com> -- Stability   : experimental -- Portability : non-portable (GHC extensions) --@@ -22,12 +22,13 @@    Value,   unfolding_use_threshold,+  max_simplifier_iterations,   getValue,   setValue, -  Flag,-  acc_sharing, exp_sharing, fusion, simplify, flush_cache, force_recomp,-  fast_math, debug, verbose, dump_phases, dump_sharing, dump_fusion,+  Flag(..),+  seq_sharing, acc_sharing, exp_sharing, array_fusion, simplify, inplace, flush_cache, force_recomp,+  fast_math, fast_permute_const, debug, verbose, dump_phases, dump_sharing, dump_fusion,   dump_simpl_stats, dump_simpl_iterations, dump_vectorisation, dump_dot,   dump_simpl_dot, dump_gc, dump_gc_stats, dump_cc, dump_ld, dump_asm, dump_exec,   dump_sched,@@ -39,20 +40,66 @@   when,   unless, +  __cmd_line_flags,+ ) where  +import Control.Monad.IO.Class                                       ( MonadIO, liftIO )+import Data.Bits import Data.Int+import Data.Word import Foreign.Ptr import Foreign.Storable--import Control.Monad.IO.Class                                       ( MonadIO, liftIO )+import Language.Haskell.TH.Syntax+import System.Directory+import System.FilePath import qualified Control.Monad                                      as M -newtype Flag  = Flag  (Ptr Int32)-newtype Value = Value (Ptr Int32)+newtype Flag  = Flag  Int+newtype Value = Value (Ptr Word32)    -- see flags.c +-- We aren't using a "real" enum so that we can make use of the unused top+-- bits for other configuration options, not controlled by the command line+-- flags.+--+instance Enum Flag where+  toEnum            = Flag+  fromEnum (Flag x) = x +-- SEE: [layout of command line options bitfield]+instance Show Flag where+  show (Flag x) =+    case x of+      0  -> "seq-sharing"+      1  -> "acc-sharing"+      2  -> "exp-sharing"+      3  -> "fusion"+      4  -> "simplify"+      5  -> "inplace"+      6  -> "fast-math"+      7  -> "fast-permute-const"+      8  -> "flush_cache"+      9  -> "force-recomp"+      10 -> "debug"+      11 -> "verbose"+      12 -> "dump-phases"+      13 -> "dump-sharing"+      14 -> "dump-fusion"+      15 -> "dump-simpl_stats"+      16 -> "dump-simpl_iterations"+      17 -> "dump-vectorisation"+      18 -> "dump-dot"+      19 -> "dump-simpl_dot"+      20 -> "dump-gc"+      21 -> "dump-gc_stats"+      22 -> "dump-cc"+      23 -> "dump-ld"+      24 -> "dump-asm"+      25 -> "dump-exec"+      26 -> "dump-sched"+      _  -> show x+ -- | Conditional execution of a monadic debugging expression. -- -- This does nothing unless the program is compiled in debug mode.@@ -83,40 +130,26 @@ #endif  -setValue   :: Value -> Int -> IO ()-#ifdef ACCELERATE_DEBUG-setValue (Value f) v = poke f (fromIntegral v)-#else-setValue _         _ = notEnabled-#endif+setValue   :: Value -> Word32 -> IO ()+setValue (Value f) v = poke f v -getValue   :: Value -> IO Int-#ifdef ACCELERATE_DEBUG-getValue (Value f) = fromIntegral `fmap` peek f-#else-getValue _         = notEnabled-#endif+getValue   :: Value -> IO Word32+getValue (Value f) = peek f  getFlag    :: Flag -> IO Bool-#ifdef ACCELERATE_DEBUG-getFlag (Flag f) = toBool `fmap` peek f-#else-getFlag _        = notEnabled-#endif+getFlag (Flag i) = do+  flags  <- peek __cmd_line_flags+  return $! testBit flags i  setFlag    :: Flag -> IO ()-#ifdef ACCELERATE_DEBUG-setFlag (Flag f) = poke f (fromBool True)-#else-setFlag _        = notEnabled-#endif+setFlag (Flag i) = do+  flags <- peek __cmd_line_flags+  poke __cmd_line_flags (setBit flags i)  clearFlag  :: Flag -> IO ()-#ifdef ACCELERATE_DEBUG-clearFlag (Flag f) = poke f (fromBool False)-#else-clearFlag _        = notEnabled-#endif+clearFlag (Flag i) = do+  flags <- peek __cmd_line_flags+  poke __cmd_line_flags (clearBit flags i)  setFlags   :: [Flag] -> IO () setFlags = mapM_ setFlag@@ -124,53 +157,79 @@ clearFlags :: [Flag] -> IO () clearFlags = mapM_ clearFlag -notEnabled :: a-notEnabled = error $ unlines [ "Data.Array.Accelerate: Debugging options are disabled."-                             , "Reinstall package 'accelerate' with '-fdebug' to enable them." ]--toBool :: Int32 -> Bool-toBool 0 = False-toBool _ = True--fromBool :: Bool -> Int32-fromBool False = 0-fromBool True  = 1-+-- notEnabled :: a+-- notEnabled = error $ unlines [ "Data.Array.Accelerate: Debugging options are disabled."+--                              , "Reinstall package 'accelerate' with '-fdebug' to enable them." ]  -- Import the underlying flag variables. These are defined in the file--- cbits/flags.c and initialised at program initialisation.+-- cbits/flags.h as a bitfield and initialised at program initialisation.+--+-- SEE: [layout of command line options bitfield]+-- SEE: [linking to .c files]+--+foreign import ccall "&__cmd_line_flags" __cmd_line_flags :: Ptr Word32  -- These @-f<blah>=INT@ values are used by the compiler ---foreign import ccall "&__unfolding_use_threshold" unfolding_use_threshold :: Value  -- the magic cut-off figure for inlining+foreign import ccall "&__unfolding_use_threshold"   unfolding_use_threshold   :: Value  -- the magic cut-off figure for inlining+foreign import ccall "&__max_simplifier_iterations" max_simplifier_iterations :: Value  -- maximum number of scalar simplification passes  -- These @-f<blah>@ flags can be reversed with @-fno-<blah>@ ---foreign import ccall "&__acc_sharing"             acc_sharing             :: Flag   -- recover sharing of array computations-foreign import ccall "&__exp_sharing"             exp_sharing             :: Flag   -- recover sharing of scalar expressions-foreign import ccall "&__fusion"                  fusion                  :: Flag   -- fuse array expressions-foreign import ccall "&__simplify"                simplify                :: Flag   -- simplify scalar expressions-foreign import ccall "&__fast_math"               fast_math               :: Flag   -- delete persistent compilation cache(s)-foreign import ccall "&__flush_cache"             flush_cache             :: Flag   -- force recompilation of array programs-foreign import ccall "&__force_recomp"            force_recomp            :: Flag   -- use faster, less precise math library operations-foreign import ccall "&__debug"                   debug                   :: Flag   -- compile code with debugging symbols (-g)+seq_sharing           = Flag  0 -- recover sharing of sequence expressions+acc_sharing           = Flag  1 -- recover sharing of array computations+exp_sharing           = Flag  2 -- recover sharing of scalar expressions+array_fusion          = Flag  3 -- fuse array expressions+simplify              = Flag  4 -- simplify scalar expressions+inplace               = Flag  5 -- allow (safe) in-place array updates+fast_math             = Flag  6 -- use faster, less precise math library operations+fast_permute_const    = Flag  7 -- allow non-atomic permute const for product types+flush_cache           = Flag  8 -- delete persistent compilation cache(s)+force_recomp          = Flag  9 -- force recompilation of array programs  -- These debugging flags are disable by default and are enabled with @-d<blah>@ ---foreign import ccall "&__verbose"                 verbose                 :: Flag   -- be very chatty-foreign import ccall "&__dump_phases"             dump_phases             :: Flag   -- print information about each phase of the compiler-foreign import ccall "&__dump_sharing"            dump_sharing            :: Flag   -- sharing recovery phase-foreign import ccall "&__dump_fusion"             dump_fusion             :: Flag   -- array fusion phase-foreign import ccall "&__dump_simpl_stats"        dump_simpl_stats        :: Flag   -- statistics form fusion/simplification-foreign import ccall "&__dump_simpl_iterations"   dump_simpl_iterations   :: Flag   -- output from each simplifier iteration-foreign import ccall "&__dump_vectorisation"      dump_vectorisation      :: Flag   -- output from the vectoriser-foreign import ccall "&__dump_dot"                dump_dot                :: Flag   -- generate dot output of the program-foreign import ccall "&__dump_simpl_dot"          dump_simpl_dot          :: Flag   -- generate simplified dot output-foreign import ccall "&__dump_gc"                 dump_gc                 :: Flag   -- trace garbage collector-foreign import ccall "&__dump_gc_stats"           dump_gc_stats           :: Flag   -- print final GC statistics-foreign import ccall "&__dump_cc"                 dump_cc                 :: Flag   -- trace code generation & compilation-foreign import ccall "&__dump_ld"                 dump_ld                 :: Flag   -- trace runtime linker-foreign import ccall "&__dump_asm"                dump_asm                :: Flag   -- trace assembler-foreign import ccall "&__dump_exec"               dump_exec               :: Flag   -- trace execution-foreign import ccall "&__dump_sched"              dump_sched              :: Flag   -- trace scheduler+debug                 = Flag 10 -- compile code with debugging symbols (-g)+verbose               = Flag 11 -- be very chatty+dump_phases           = Flag 12 -- print information about each phase of the compiler+dump_sharing          = Flag 13 -- sharing recovery phase+dump_fusion           = Flag 14 -- array fusion phase+dump_simpl_stats      = Flag 15 -- statistics form fusion/simplification+dump_simpl_iterations = Flag 16 -- output from each simplifier iteration+dump_vectorisation    = Flag 17 -- output from the vectoriser+dump_dot              = Flag 18 -- generate dot output of the program+dump_simpl_dot        = Flag 19 -- generate simplified dot output+dump_gc               = Flag 20 -- trace garbage collector+dump_gc_stats         = Flag 21 -- print final GC statistics+dump_cc               = Flag 22 -- trace code generation & compilation+dump_ld               = Flag 23 -- trace runtime linker+dump_asm              = Flag 24 -- trace assembler+dump_exec             = Flag 25 -- trace execution+dump_sched            = Flag 26 -- trace scheduler+++-- Note: [linking to .c files]+--+-- We use Template Haskell to tell GHC which .c files need to be compiled+-- for a particular module, rather than relying on Cabal as is traditional.+-- Using Cabal:+--+--  * loading Accelerate into GHCi only works _after_ compiling the entire+--    package (which defeats the purpose), presumably because the .c files+--    are compiled last. This would often lead to errors such "can not find+--    symbol __cmd_line_flags" etc.+--+--  * Cabal would refuse to re-compile .c files when changing command+--    line flags, see: https://github.com/haskell/cabal/issues/4937+--+--  * Linking problems also prevented us from using Template Haskell in+--    some locations, because GHC was unable to load the project into the+--    interpreter to run the splices.+--+-- Note that for this fix to work in GHCi we also require modules using it+-- to be loaded as object code.+--+runQ $ do+  addForeignFilePath LangC "cbits/flags.c"+  return [] 
src/Data/Array/Accelerate/Debug/Monitoring.hs view
@@ -3,13 +3,15 @@ {-# LANGUAGE ForeignFunctionInterface #-} {-# LANGUAGE OverloadedStrings        #-} {-# LANGUAGE RecordWildCards          #-}+{-# LANGUAGE TemplateHaskell          #-}+{-# OPTIONS_GHC -fobject-code #-} {-# OPTIONS_HADDOCK hide #-} -- | -- Module      : Data.Array.Accelerate.Debug.Monitoring--- Copyright   : [2016..2017] Manuel M T Chakravarty, Gabriele Keller, Trevor L. McDonell+-- Copyright   : [2016..2020] The Accelerate Team -- License     : BSD3 ----- Maintainer  : Trevor L. McDonell <tmcdonell@cse.unsw.edu.au>+-- Maintainer  : Trevor L. McDonell <trevor.mcdonell@gmail.com> -- Stability   : experimental -- Portability : non-portable (GHC extensions) --@@ -34,6 +36,8 @@ ) where  #ifdef ACCELERATE_MONITORING+import Data.Array.Accelerate.Debug.Clock+ import System.Metrics import System.Remote.Monitoring @@ -45,12 +49,15 @@ import qualified Data.HashMap.Strict                                as Map #endif +#if defined(ACCELERATE_MONITORING) || defined(ACCELERATE_DEBUG)+import Control.Monad+#endif+ import Data.Atomic                                                  ( Atomic ) import qualified Data.Atomic                                        as Atomic -import Control.Monad import Data.Int-import Prelude+import Language.Haskell.TH.Syntax   -- | Launch a monitoring server that will collect statistics on the running@@ -226,7 +233,7 @@  -- Allocations in the number of bytes of /new/ memory in the remote memory space ---{-# INLINE didAllocateBytesRemote #-}+{-# INLINE didAllocateBytesRemote     #-} {-# INLINE increaseCurrentBytesRemote #-} {-# INLINE decreaseCurrentBytesRemote #-} didAllocateBytesRemote     :: Int64 -> IO ()@@ -345,9 +352,6 @@   writeIORef ref (ES time new_inst new_avg)   return (round new_avg) --- cbits/clock.c-foreign import ccall unsafe "clock_gettime_monotonic_seconds" getMonotonicTime :: IO Double- {-- -- 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@@ -408,4 +412,10 @@ foreign import ccall "&__total_bytes_evicted_from_remote" __total_bytes_evicted_from_remote :: Atomic -- total bytes copied from the remote due to evictions foreign import ccall "&__num_remote_gcs"                  __num_remote_gcs                  :: Atomic -- number of times the remote memory space was forcibly garbage collected foreign import ccall "&__num_evictions"                   __num_evictions                   :: Atomic -- number of LRU eviction events++-- SEE: [linking to .c files]+--+runQ $ do+  addForeignFilePath LangC "cbits/monitoring.c"+  return [] 
src/Data/Array/Accelerate/Debug/Stats.hs view
@@ -1,13 +1,13 @@-{-# LANGUAGE CPP #-}+{-# LANGUAGE CPP               #-}+{-# LANGUAGE OverloadedStrings #-} {-# 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+-- Copyright   : [2008..2020] The Accelerate Team -- License     : BSD3 ----- Maintainer  : Trevor L. McDonell <tmcdonell@cse.unsw.edu.au>+-- Maintainer  : Trevor L. McDonell <trevor.mcdonell@gmail.com> -- Stability   : experimental -- Portability : non-portable (GHC extensions) --@@ -17,31 +17,37 @@  module Data.Array.Accelerate.Debug.Stats ( -  simplCount, resetSimplCount,-  inline, ruleFired, knownBranch, betaReduce, substitution, simplifierDone, fusionDone,+  simplCount, resetSimplCount, dumpSimplStats,+  inline, ruleFired, knownBranch, caseElim, caseDefault, betaReduce, substitution, simplifierDone, fusionDone,  ) where  import Data.Array.Accelerate.Debug.Flags+import Data.Array.Accelerate.Debug.Trace -import Data.Function                            ( on )+import Data.Function                                      ( on ) import Data.IORef-import Data.List                                ( groupBy, sortBy )-import Data.Ord                                 ( comparing )-import Data.Map                                 ( Map )-import Text.PrettyPrint.ANSI.Leijen+import Data.List                                          ( groupBy, sortBy )+import Data.Map                                           ( Map )+import Data.Ord                                           ( comparing )+import Data.Text                                          ( Text )+import Data.Text.Prettyprint.Doc                          hiding ( annotate, Doc )+-- import Data.Text.Prettyprint.Doc.Render.Terminal+import Data.Text.Prettyprint.Doc.Render.String import System.IO.Unsafe--import qualified Data.Map                       as Map+import qualified Data.Map                                 as Map+import qualified Data.Text.Prettyprint.Doc                as Pretty   -- Recording statistics -- -------------------- -ruleFired, inline, knownBranch, betaReduce, substitution :: String -> a -> a+ruleFired, inline, knownBranch, caseElim, caseDefault, betaReduce, substitution :: Text -> a -> a inline          = annotate Inline ruleFired       = annotate RuleFired knownBranch     = annotate KnownBranch+caseElim        = annotate CaseElim+caseDefault     = annotate CaseDefault betaReduce      = annotate BetaReduce substitution    = annotate Substitution @@ -64,7 +70,7 @@  -- Add an entry to the statistics counters with an annotation ---annotate :: (Id -> Tick) -> String -> a -> a+annotate :: (Id -> Tick) -> Text -> a -> a annotate name ctx = tick (name (Id ctx))  @@ -113,7 +119,22 @@ resetSimplCount = return () #endif +-- Display simplifier statistics. The counts are reset afterwards.+--+{-# INLINEABLE dumpSimplStats #-}+dumpSimplStats :: IO ()+#ifdef ACCELERATE_DEBUG+dumpSimplStats = do+  when dump_simpl_stats $ do+    stats <- simplCount+    putTraceMsg (renderString (layoutPretty defaultLayoutOptions stats))+    resetSimplCount+#else+dumpSimplStats = return ()+#endif ++ -- Tick a counter -- simplTick :: Tick -> SimplStats -> SimplStats@@ -123,10 +144,10 @@ -- Pretty print the tick counts. Remarkably reminiscent of GHC style... -- pprSimplCount :: SimplStats -> Doc-pprSimplCount (Simple n)     = text "Total ticks:" <+> int n+pprSimplCount (Simple n)     = "Total ticks:" <+> pretty n pprSimplCount (Detail n dts)-  = vcat [ text "Total ticks:" <+> int n-         , text ""+  = vcat [ "Total ticks:" <+> pretty n+         , mempty          , pprTickCount dts          ] @@ -137,15 +158,18 @@ -- Ticks -- ----- +type Doc       = Pretty.Doc () type TickCount = Map Tick Int -data Id = Id String+data Id = Id Text   deriving (Eq, Ord)  data Tick   = Inline              Id   | RuleFired           Id   | KnownBranch         Id+  | CaseElim            Id+  | CaseDefault         Id   | BetaReduce          Id   | Substitution        Id @@ -172,8 +196,8 @@ pprTickGroup :: [(Tick,Int)] -> Doc pprTickGroup []  = error "pprTickGroup" pprTickGroup grp =-  hang 2 (vcat $ (int groupTotal <+> text groupName)-               : [ int n <+> pprTickCtx t | (t,n) <- sortBy (flip (comparing snd)) grp ])+  hang 2 (vcat $ (pretty groupTotal <+> groupName)+               : [ pretty n <+> pprTickCtx t | (t,n) <- sortBy (flip (comparing snd)) grp ])   where     groupName  = tickToStr (fst (head grp))     groupTotal = sum [n | (_,n) <- grp]@@ -182,15 +206,19 @@ tickToTag Inline{}              = 0 tickToTag RuleFired{}           = 1 tickToTag KnownBranch{}         = 2-tickToTag BetaReduce{}          = 3-tickToTag Substitution{}        = 4+tickToTag CaseElim{}            = 3+tickToTag CaseDefault{}         = 4+tickToTag BetaReduce{}          = 5+tickToTag Substitution{}        = 6 tickToTag SimplifierDone        = 99 tickToTag FusionDone            = 100 -tickToStr :: Tick -> String+tickToStr :: Tick -> Doc tickToStr Inline{}              = "Inline" tickToStr RuleFired{}           = "RuleFired" tickToStr KnownBranch{}         = "KnownBranch"+tickToStr CaseElim{}            = "CaseElim"+tickToStr CaseDefault{}         = "CaseDefault" tickToStr BetaReduce{}          = "BetaReduce" tickToStr Substitution{}        = "Substitution" tickToStr SimplifierDone        = "SimplifierDone"@@ -200,11 +228,13 @@ pprTickCtx (Inline v)           = pprId v pprTickCtx (RuleFired v)        = pprId v pprTickCtx (KnownBranch v)      = pprId v+pprTickCtx (CaseElim v)         = pprId v+pprTickCtx (CaseDefault v)      = pprId v pprTickCtx (BetaReduce v)       = pprId v pprTickCtx (Substitution v)     = pprId v-pprTickCtx SimplifierDone       = empty-pprTickCtx FusionDone           = empty+pprTickCtx SimplifierDone       = mempty+pprTickCtx FusionDone           = mempty  pprId :: Id -> Doc-pprId (Id s) = text s+pprId (Id s) = pretty s 
src/Data/Array/Accelerate/Debug/Timed.hs view
@@ -1,11 +1,11 @@-{-# LANGUAGE CPP                      #-}-{-# LANGUAGE ForeignFunctionInterface #-}+{-# LANGUAGE CPP       #-}+{-# LANGUAGE MagicHash #-} -- | -- Module      : Data.Array.Accelerate.Debug.Timed--- Copyright   : [2016..2017] Manuel M T Chakravarty, Gabriele Keller, Trevor L. McDonell+-- Copyright   : [2016..2020] The Accelerate Team -- License     : BSD3 ----- Maintainer  : Trevor L. McDonell <tmcdonell@cse.unsw.edu.au>+-- Maintainer  : Trevor L. McDonell <trevor.mcdonell@gmail.com> -- Stability   : experimental -- Portability : non-portable (GHC extensions) --@@ -17,20 +17,26 @@  ) where -import Data.Array.Accelerate.Debug.Trace import Data.Array.Accelerate.Debug.Flags+import Data.Array.Accelerate.Debug.Trace  import Control.Monad.Trans                              ( MonadIO ) import Text.Printf  #if ACCELERATE_DEBUG+import Data.Array.Accelerate.Debug.Clock+ import Control.Applicative import Control.Monad.Trans                              ( liftIO )-import Data.List+import Data.List                                        ( intercalate ) import System.CPUTime import Prelude +import GHC.Base+import GHC.Int+import GHC.Num import GHC.Stats+import GHC.Word #endif  @@ -66,51 +72,32 @@   cpu1  <- liftIO getCPUTime   --   let wallTime = wall1 - wall0-      cpuTime  = fromIntegral (cpu1 - cpu0) * 1E-12+      cpuTime  = D# (doubleFromInteger (cpu1 - cpu0) *## 1E-12##)   --   liftIO $ putTraceMsg (fmt wallTime cpuTime)   return res -foreign import ccall unsafe "clock_gettime_monotonic_seconds" getMonotonicTime :: IO Double - {-# INLINEABLE timed_gc #-} timed_gc :: MonadIO m => (Double -> Double -> String) -> m a -> m a timed_gc fmt action = do-#if __GLASGOW_HASKELL__ < 802-  gc0   <- liftIO getGCStats-  res   <- action-  gc1   <- liftIO getGCStats-#else   rts0  <- liftIO getRTSStats   res   <- action   rts1  <- liftIO getRTSStats-#endif   ---  let toDouble :: Integral a => a -> Double-      toDouble = fromIntegral+  let+      w64 (W64# w#) = D# (word2Double# w#)+      i64 (I64# i#) = D# (int2Double# i#)       ---#if __GLASGOW_HASKELL__ < 802-      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-      totalGCs    = numGcs gc1 - numGcs gc0-#else-      allocated   = toDouble (allocated_bytes rts1 - allocated_bytes rts0)-      copied      = toDouble (copied_bytes rts1 - copied_bytes rts0)-      totalWall   = toDouble (elapsed_ns rts1 - elapsed_ns rts0) * 1.0E-9-      totalCPU    = toDouble (cpu_ns rts1 - cpu_ns rts0) * 1.0E-9-      mutatorWall = toDouble (mutator_elapsed_ns rts1 - mutator_elapsed_ns rts0) * 1.0E-9-      mutatorCPU  = toDouble (mutator_cpu_ns rts1 - mutator_cpu_ns rts0) * 1.0E-9-      gcWall      = toDouble (gc_elapsed_ns rts1 - gc_elapsed_ns rts0) * 1.0E-9-      gcCPU       = toDouble (gc_cpu_ns rts1 - gc_cpu_ns rts0) * 1.0E-9+      allocated   = w64 (allocated_bytes rts1 - allocated_bytes rts0)+      copied      = w64 (copied_bytes rts1 - copied_bytes rts0)+      totalWall   = i64 (elapsed_ns rts1 - elapsed_ns rts0) * 1.0E-9+      totalCPU    = i64 (cpu_ns rts1 - cpu_ns rts0) * 1.0E-9+      mutatorWall = i64 (mutator_elapsed_ns rts1 - mutator_elapsed_ns rts0) * 1.0E-9+      mutatorCPU  = i64 (mutator_cpu_ns rts1 - mutator_cpu_ns rts0) * 1.0E-9+      gcWall      = i64 (gc_elapsed_ns rts1 - gc_elapsed_ns rts0) * 1.0E-9+      gcCPU       = i64 (gc_cpu_ns rts1 - gc_cpu_ns rts0) * 1.0E-9       totalGCs    = gcs rts1 - gcs rts0-#endif    liftIO . putTraceMsg $ intercalate "\n"     [ fmt totalWall totalCPU@@ -121,11 +108,6 @@     ]   --   return res--#if __GLASGOW_HASKELL__ < 802-getRTSStatsEnabled :: IO Bool-getRTSStatsEnabled = getGCStatsEnabled-#endif #endif  elapsed :: Double -> Double -> String
src/Data/Array/Accelerate/Debug/Trace.hs view
@@ -3,11 +3,10 @@ {-# LANGUAGE ForeignFunctionInterface #-} -- | -- Module      : Data.Array.Accelerate.Debug.Trace--- Copyright   : [2008..2017] Manuel M T Chakravarty, Gabriele Keller---               [2009..2017] Trevor L. McDonell+-- Copyright   : [2008..2020] The Accelerate Team -- License     : BSD3 ----- Maintainer  : Trevor L. McDonell <tmcdonell@cse.unsw.edu.au>+-- Maintainer  : Trevor L. McDonell <trevor.mcdonell@gmail.com> -- Stability   : experimental -- Portability : non-portable (GHC extensions) --@@ -31,6 +30,7 @@ import Numeric  #ifdef ACCELERATE_DEBUG+import Data.Array.Accelerate.Debug.Clock import System.IO.Unsafe import Text.Printf import qualified Debug.Trace                            as D@@ -141,9 +141,5 @@ #else {-# INLINE traceEventIO #-} traceEventIO _ _ = return ()-#endif--#ifdef ACCELERATE_DEBUG-foreign import ccall unsafe "clock_gettime_elapsed_seconds" getProgramTime :: IO Double #endif 
src/Data/Array/Accelerate/Error.hs view
@@ -1,45 +1,45 @@ {-# LANGUAGE CPP             #-}-{-# LANGUAGE QuasiQuotes     #-} {-# LANGUAGE RecordWildCards #-}-{-# LANGUAGE TemplateHaskell #-} {-# OPTIONS_HADDOCK hide #-} -- | -- Module      : Data.Array.Accelerate.Error--- Copyright   : [2009..2017] Manuel M T Chakravarty, Gabriele Keller, Trevor L. McDonell+-- Copyright   : [2009..2020] The Accelerate Team -- License     : BSD3 ----- Maintainer  : Trevor L. McDonell <tmcdonell@cse.unsw.edu.au>+-- Maintainer  : Trevor L. McDonell <trevor.mcdonell@gmail.com> -- Stability   : experimental -- Portability : non-portable (GHC extensions) --  module Data.Array.Accelerate.Error ( +  HasCallStack,   internalError,   boundsError,   unsafeError,   internalCheck,   boundsCheck,   unsafeCheck,   indexCheck,   internalWarning, boundsWarning, unsafeWarning,  ) where -import Data.List import Debug.Trace-import Language.Haskell.TH                              hiding ( Unsafe )+import Data.List                                          ( intercalate )+import Text.Printf+import Prelude                                            hiding ( error ) +import GHC.Stack+ data Check = Bounds | Unsafe | Internal   -- | Issue an internal error message -----   $internalError :: String -> String -> a----internalError :: Q Exp-internalError = appE errorQ [| Internal |]+internalError :: HasCallStack => String -> a+internalError = withFrozenCallStack $ error Internal -boundsError :: Q Exp-boundsError = appE errorQ [| Bounds |]+boundsError :: HasCallStack => String -> a+boundsError = withFrozenCallStack $ error Bounds -unsafeError :: Q Exp-unsafeError = appE errorQ [| Unsafe |]+unsafeError :: HasCallStack => String -> a+unsafeError = withFrozenCallStack $ error Unsafe   -- | Throw an error if the condition evaluates to False, otherwise evaluate the@@ -47,96 +47,81 @@ -- --   $internalCheck :: String -> String -> Bool -> a -> a ---internalCheck :: Q Exp-internalCheck = appE checkQ [| Internal |]+internalCheck :: HasCallStack => String -> Bool -> a -> a+internalCheck = withFrozenCallStack $ check Internal -boundsCheck :: Q Exp-boundsCheck = appE checkQ [| Bounds |]+boundsCheck :: HasCallStack => String -> Bool -> a -> a+boundsCheck = withFrozenCallStack $ check Bounds -unsafeCheck :: Q Exp-unsafeCheck = appE checkQ [| Unsafe |]+unsafeCheck :: HasCallStack => String -> Bool -> a -> a+unsafeCheck = withFrozenCallStack $ check Unsafe   -- | Throw an error if the index is not in range, otherwise evaluate the result. -----   $boundsCheck :: String -> Int -> Int -> a -> a----indexCheck :: Q Exp-indexCheck = withLocation-  [| \format fn i n x ->-        case not (doChecks Bounds) || (i >= 0 && i < n) of-           True  -> x-           False -> errorWithoutStackTrace (format Bounds (call fn ("index out of bounds: " ++ show (i,n)))) x |]-+indexCheck :: HasCallStack => Int -> Int -> a -> a+indexCheck i n =+  boundsCheck (printf "index out of bounds: i=%d, n=%d" i n) (i >= 0 && i < n)  -- | Print a warning message if the condition evaluates to False. -- --   $internalWarning :: String -> String -> Bool -> a -> a ---internalWarning :: Q Exp-internalWarning = appE warningQ [| Internal |]+internalWarning :: HasCallStack => String -> Bool -> a -> a+internalWarning = withFrozenCallStack $ warning Internal -boundsWarning :: Q Exp-boundsWarning = appE warningQ [| Bounds |]+boundsWarning :: HasCallStack => String -> Bool -> a -> a+boundsWarning = withFrozenCallStack $ warning Bounds -unsafeWarning :: Q Exp-unsafeWarning = appE warningQ [| Unsafe |]+unsafeWarning :: HasCallStack => String -> Bool -> a -> a+unsafeWarning = withFrozenCallStack $ warning Unsafe  --- Template Haskell implementation--- ---------------------------------call :: String -> String -> String-call f m = concat ["(", f, "): ", m]--errorQ :: Q Exp-errorQ = withLocation-  [| \format kind fn msg -> errorWithoutStackTrace (format kind (call fn msg)) |]--checkQ :: Q Exp-checkQ = withLocation-  [| \format kind fn msg cond x ->-        case not (doChecks kind) || cond of-          True  -> x-          False -> errorWithoutStackTrace (format kind (call fn msg)) |]--warningQ :: Q Exp-warningQ = withLocation-  [| \format kind fn msg cond x ->-        case not (doChecks kind) || cond of-          True  -> x-          False -> trace (format kind (call fn msg)) x |]+error :: HasCallStack => Check -> String -> a+error kind msg = errorWithoutStackTrace (format kind msg) -withLocation :: Q Exp -> Q Exp-withLocation f =-  appE f (locatedMessage =<< location)+check :: HasCallStack => Check -> String -> Bool -> a -> a+check kind msg cond k =+  case not (doChecks kind) || cond of+    True  -> k+    False -> errorWithoutStackTrace (format kind msg) -locatedMessage :: Loc -> Q Exp-locatedMessage loc =-  [| \kind msg -> message kind ($(litE (stringL (formatLoc loc))) ++ msg) |]+warning :: HasCallStack => Check -> String -> Bool -> a -> a+warning kind msg cond k =+  case not (doChecks kind) || cond of+    True  -> k+    False -> trace (format kind msg) k -formatLoc :: Loc -> String-formatLoc loc =-  let   file            = loc_filename loc-        (line,col)      = loc_start loc-  in-  intercalate ":" [file, show line, show col, " "]+format :: HasCallStack => Check -> String -> String+format kind msg = intercalate "\n" [ header, msg, ppCallStack callStack ]+  where+    header+      = intercalate "\n"+      $ case kind of+          Internal -> [""+                      ,"*** Internal error in package accelerate ***"+                      ,"*** Please submit a bug report at https://github.com/AccelerateHS/accelerate/issues"+                      ,""]+          _        -> [] -message :: Check -> String -> String-message kind msg = unlines header ++ msg+ppCallStack :: CallStack -> String+ppCallStack = intercalate "\n" . ppLines   where-    header =-      case kind of-        Internal -> [""-                    ,"*** Internal error in package accelerate ***"-                    ,"*** Please submit a bug report at https://github.com/AccelerateHS/accelerate/issues"]-        _        -> []+    ppLines cs =+      case getCallStack cs of+        [] -> []+        st -> ""+            : "CallStack (from HasCallStack):"+            : map (("  " ++) . ppCallSite) st -#if __GLASGOW_HASKELL__ < 800-errorWithoutStackTrace :: String -> a-errorWithoutStackTrace = error-#endif+    ppCallSite (f, loc) = f ++ ": " ++ ppSrcLoc loc +    ppSrcLoc SrcLoc{..} =+      foldr (++) ""+        [ srcLocModule, ":"+        , show srcLocStartLine, ":"+        , show srcLocStartCol+        ]  -- CPP malarky -- -----------
src/Data/Array/Accelerate/Interpreter.hs view
@@ -1,2016 +1,1777 @@ {-# 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..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)------ This interpreter is meant to be a reference implementation of the semantics--- of the embedded array language. The emphasis is on defining the semantics--- clearly, not on performance.------- [/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.-----module Data.Array.Accelerate.Interpreter (--  -- * Interpret an array expression-  Sugar.Acc, Arrays,-  run, run1, runN,--  -- Internal (hidden)-  evalPrj,-  evalPrim, evalPrimConst, evalUndef, evalCoerce,--) where---- standard libraries-import Control.DeepSeq-import Control.Exception-import Control.Monad-import Data.Bits-import Data.Char                                                    ( chr, ord )-import Data.Constraint-import Data.Typeable-import Foreign.C.Types-import Foreign.ForeignPtr-import System.IO.Unsafe                                             ( unsafePerformIO )-import Text.Printf                                                  ( printf )-import Prelude                                                      hiding ( sum )---- friends-import Data.Array.Accelerate.AST                                    hiding ( Boundary, PreBoundary(..) )-import Data.Array.Accelerate.Analysis.Match-import Data.Array.Accelerate.Analysis.Type-import Data.Array.Accelerate.Array.Data-import Data.Array.Accelerate.Array.Representation                   ( SliceIndex(..) )-import Data.Array.Accelerate.Array.Sugar-import Data.Array.Accelerate.Array.Unique-import Data.Array.Accelerate.Error-import Data.Array.Accelerate.Lifetime-import Data.Array.Accelerate.Product-import Data.Array.Accelerate.Trafo                                  hiding ( Delayed )-import Data.Array.Accelerate.Type-import qualified Data.Array.Accelerate.AST                          as AST-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 a = unsafePerformIO execute-  where-    !acc    = convertAccWith config a-    execute = do-      D.dumpGraph $!! acc-      D.dumpSimplStats-      phase "execute" D.elapsed (evaluate (evalOpenAcc acc Empty))---- | This is 'runN' specialised to an array program of one argument.----run1 :: (Arrays a, Arrays b) => (Sugar.Acc a -> Sugar.Acc b) -> a -> b-run1 = runN---- | Prepare and execute an embedded array program.----runN :: Afunction f => f -> AfunctionR f-runN f = go-  where-    !acc    = convertAfunWith config f-    !afun   = unsafePerformIO $ do-                D.dumpGraph $!! acc-                D.dumpSimplStats-                return acc-    !go     = eval afun Empty-    ---    eval :: DelayedOpenAfun aenv f -> Val aenv -> f-    eval (Alam f)  aenv = \a -> eval f (aenv `Push` a)-    eval (Abody b) aenv = unsafePerformIO $ phase "execute" D.elapsed (evaluate (evalOpenAcc b aenv))----- -- | 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--- ------------------ Note that in contrast to the representation used in the optimised AST, the--- delayed array representation used here is _only_ for delayed arrays --- we do--- not require an optional Manifest|Delayed data type to evaluate the program.----data Delayed a where-  Delayed :: (Shape sh, Elt e)-          => sh-          -> (sh -> e)-          -> (Int -> e)-          -> Delayed (Array sh e)----- Array expression evaluation--- -----------------------------type EvalAcc acc = forall aenv a. acc aenv a -> Val aenv -> a---- Evaluate an open array function----evalOpenAfun :: DelayedOpenAfun aenv f -> Val aenv -> f-evalOpenAfun (Alam  f) aenv = \a -> evalOpenAfun f (aenv `Push` a)-evalOpenAfun (Abody b) aenv = evalOpenAcc b aenv----- The core interpreter for optimised array programs----evalOpenAcc-    :: forall aenv a.-       DelayedOpenAcc aenv a-    -> Val aenv-    -> a-evalOpenAcc AST.Delayed{}       _    = $internalError "evalOpenAcc" "expected manifest array"-evalOpenAcc (AST.Manifest pacc) aenv =-  let-      manifest :: Arrays a' => DelayedOpenAcc aenv a' -> a'-      manifest acc =-        let a' = evalOpenAcc acc aenv-        in  rnfArrays (arrays a') (fromArr a') `seq` a'--      delayed :: DelayedOpenAcc aenv (Array sh e) -> Delayed (Array sh e)-      delayed AST.Manifest{}  = $internalError "evalOpenAcc" "expected delayed array"-      delayed AST.Delayed{..} = Delayed (evalE extentD) (evalF indexD) (evalF linearIndexD)--      evalE :: DelayedExp aenv t -> t-      evalE exp = evalPreExp evalOpenAcc exp aenv--      evalF :: DelayedFun aenv f -> f-      evalF fun = evalPreFun evalOpenAcc fun aenv--      evalB :: AST.PreBoundary DelayedOpenAcc aenv t -> Boundary t-      evalB bnd = evalPreBoundary evalOpenAcc bnd aenv-  in-  case pacc of-    Avar ix                     -> prj ix aenv-    Alet acc1 acc2              -> evalOpenAcc acc2 (aenv `Push` manifest acc1)-    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-      | evalE p                 -> manifest acc1-      | otherwise               -> manifest acc2--    Awhile cond body acc        -> go (manifest acc)-      where-        p       = evalOpenAfun cond aenv-        f       = evalOpenAfun body aenv-        go !x-          | p x ! Z     = go (f x)-          | otherwise   = x--    Use arr                     -> toArr arr-    Unit e                      -> unitOp (evalE e)-    -- Collect s                   -> evalSeq defaultSeqConfig s aenv--    -- Producers-    -- ----------    Map f acc                   -> mapOp (evalF f) (delayed acc)-    Generate sh f               -> generateOp (evalE sh) (evalF f)-    Transform sh p f acc        -> transformOp (evalE sh) (evalF p) (evalF f) (delayed acc)-    Backpermute sh p acc        -> backpermuteOp (evalE sh) (evalF p) (delayed acc)-    Reshape sh acc              -> reshapeOp (evalE sh) (manifest acc)--    ZipWith f acc1 acc2         -> zipWithOp (evalF f) (delayed acc1) (delayed acc2)-    Replicate slice slix acc    -> replicateOp slice (evalE slix) (manifest acc)-    Slice slice acc slix        -> sliceOp slice (manifest acc) (evalE slix)--    -- Consumers-    -- ----------    Fold f z acc                -> foldOp (evalF f) (evalE z) (delayed acc)-    Fold1 f acc                 -> fold1Op (evalF f) (delayed acc)-    FoldSeg f z acc seg         -> foldSegOp (evalF f) (evalE z) (delayed acc) (delayed seg)-    Fold1Seg f acc seg          -> fold1SegOp (evalF f) (delayed acc) (delayed seg)-    Scanl f z acc               -> scanlOp (evalF f) (evalE z) (delayed acc)-    Scanl' f z acc              -> scanl'Op (evalF f) (evalE z) (delayed acc)-    Scanl1 f acc                -> scanl1Op (evalF f) (delayed acc)-    Scanr f z acc               -> scanrOp (evalF f) (evalE z) (delayed acc)-    Scanr' f z acc              -> scanr'Op (evalF f) (evalE z) (delayed acc)-    Scanr1 f acc                -> scanr1Op (evalF f) (delayed acc)-    Permute f def p acc         -> permuteOp (evalF f) (manifest def) (evalF p) (delayed acc)-    Stencil sten b acc          -> stencilOp (evalF sten) (evalB b) (delayed acc)-    Stencil2 sten b1 a1 b2 a2   -> stencil2Op (evalF sten) (evalB b1) (delayed a1) (evalB b2) (delayed a2)---- Array tuple construction and projection----evalAtuple :: Atuple (DelayedOpenAcc aenv) t -> Val aenv -> t-evalAtuple NilAtup        _    = ()-evalAtuple (SnocAtup t a) aenv = (evalAtuple t aenv, evalOpenAcc a aenv)----- Array primitives--- ------------------unitOp :: Elt e => e -> Scalar e-unitOp e = fromFunction Z (const e)---generateOp-    :: (Shape sh, Elt e)-    => sh-    -> (sh -> e)-    -> Array sh e-generateOp = fromFunction---transformOp-    :: (Shape sh', Elt b)-    => sh'-    -> (sh' -> sh)-    -> (a -> b)-    -> Delayed (Array sh a)-    -> Array sh' b-transformOp sh' p f (Delayed _ xs _)-  = fromFunction sh' (\ix -> f (xs $ p ix))---reshapeOp-    :: (Shape sh, Shape sh', Elt e)-    => sh-    -> Array sh' e-    -> Array sh  e-reshapeOp newShape arr@(Array _ adata)-  = $boundsCheck "reshape" "shape mismatch" (size newShape == size (shape arr))-  $ Array (fromElt newShape) adata---replicateOp-    :: (Shape sh, Shape sl, Elt slix, Elt e)-    => SliceIndex (EltRepr slix) (EltRepr sl) co (EltRepr sh)-    -> slix-    -> Array sl e-    -> Array sh e-replicateOp slice slix arr-  = fromFunction (toElt sh) (\ix -> arr ! liftToElt pf ix)-  where-    (sh, pf) = extend slice (fromElt slix) (fromElt (shape arr))--    extend :: SliceIndex slix sl co dim-           -> slix-           -> sl-           -> (dim, dim -> sl)-    extend SliceNil              ()        ()-      = ((), const ())-    extend (SliceAll sliceIdx)   (slx, ()) (sl, sz)-      = let (dim', f') = extend sliceIdx slx sl-        in  ((dim', sz), \(ix, i) -> (f' ix, i))-    extend (SliceFixed sliceIdx) (slx, sz) sl-      = let (dim', f') = extend sliceIdx slx sl-        in  ((dim', sz), \(ix, _) -> f' ix)---sliceOp-    :: (Shape sh, Shape sl, Elt slix, Elt e)-    => SliceIndex (EltRepr slix) (EltRepr sl) co (EltRepr sh)-    -> Array sh e-    -> slix-    -> Array sl e-sliceOp slice arr slix-  = fromFunction (toElt sh') (\ix -> arr ! liftToElt pf ix)-  where-    (sh', pf) = restrict slice (fromElt slix) (fromElt (shape arr))--    restrict :: SliceIndex slix sl co sh-             -> slix-             -> sh-             -> (sl, sl -> sh)-    restrict SliceNil              ()        ()-      = ((), const ())-    restrict (SliceAll sliceIdx)   (slx, ()) (sl, sz)-      = let (sl', f') = restrict sliceIdx slx sl-        in  ((sl', sz), \(ix, i) -> (f' ix, i))-    restrict (SliceFixed sliceIdx) (slx, i)  (sl, sz)-      = let (sl', f') = restrict sliceIdx slx sl-        in  $indexCheck "slice" i sz $ (sl', \ix -> (f' ix, i))---mapOp :: (Shape sh, Elt b)-      => (a -> b)-      -> Delayed (Array sh a)-      -> Array sh b-mapOp f (Delayed sh xs _)-  = fromFunction sh (\ix -> f (xs ix))---zipWithOp-    :: (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 _)-  = 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)-    -> e-    -> Delayed (Array (sh :. Int) e)-    -> Array sh e-foldOp f z (Delayed (sh :. n) arr _)-  = fromFunction sh (\ix -> iter (Z:.n) (\(Z:.i) -> arr (ix :. i)) f z)---fold1Op-    :: (Shape sh, Elt e)-    => (e -> e -> e)-    -> Delayed (Array (sh :. Int) e)-    -> Array sh e-fold1Op f (Delayed (sh :. n) arr _)-  = $boundsCheck "fold1" "empty array" (n > 0)-  $ fromFunction sh (\ix -> iter1 (Z:.n) (\(Z:.i) -> arr (ix :. i)) f)---foldSegOp-    :: forall sh e i. (Elt e, Elt i, IsIntegral i)-    => (e -> e -> e)-    -> e-    -> Delayed (Array (sh :. Int) e)-    -> Delayed (Segments i)-    -> Array (sh :. Int) e-foldSegOp f z (Delayed (sh :. _) arr _) seg@(Delayed (Z :. n) _ _)-  | IntegralDict <- integralDict (integralType :: IntegralType i)-  = fromFunction (sh :. n)-  $ \(sz :. ix) -> let start = fromIntegral $ offset ! (Z :. ix)-                       end   = fromIntegral $ offset ! (Z :. ix+1)-                   in-                   iter (Z :. end-start) (\(Z:.i) -> arr (sz :. start+i)) f z-  where-    offset      = scanlOp (+) 0 seg---fold1SegOp-    :: forall sh e i. (Shape sh, Elt e, Elt i, IsIntegral i)-    => (e -> e -> e)-    -> Delayed (Array (sh :. Int) e)-    -> Delayed (Segments i)-    -> Array (sh :. Int) e-fold1SegOp f (Delayed (sh :. _) arr _) seg@(Delayed (Z :. n) _ _)-  | IntegralDict <- integralDict (integralType :: IntegralType i)-  = fromFunction (sh :. n)-  $ \(sz :. ix) -> let start = fromIntegral $ offset ! (Z :. ix)-                       end   = fromIntegral $ offset ! (Z :. ix+1)-                   in-                   $boundsCheck "fold1Seg" "empty segment" (end > start)-                   $ iter1 (Z :. end-start) (\(Z:.i) -> arr (sz :. start+i)) f-  where-    offset      = scanlOp (+) 0 seg---scanl1Op-    :: (Shape sh, Elt e)-    => (e -> e -> e)-    -> 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 (size sh)--      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)--      iter sh write (>>) (return ())-      return (aout, undefined)---scanlOp-    :: (Shape sh, Elt e)-    => (e -> e -> e)-    -> e-    -> Delayed (Array (sh:.Int) e)-    -> Array (sh:.Int) e-scanlOp f z (Delayed (sh :. n) ain _)-  = adata `seq` Array (fromElt sh') adata-  where-    sh'         = sh :. n+1-    f'          = sinkFromElt2 f-    ---    (adata, _)  = runArrayData $ do-      aout <- newArrayData (size sh')--      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-    :: (Shape sh, Elt e)-    => (e -> e -> e)-    -> e-    -> 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-    :: (Shape sh, Elt e)-    => (e -> e -> e)-    -> e-    -> Delayed (Array (sh:.Int) e)-    -> Array (sh:.Int) e-scanrOp f z (Delayed (sz :. n) ain _)-  = adata `seq` Array (fromElt sh') adata-  where-    sh'         = sz :. n+1-    f'          = sinkFromElt2 f-    ---    (adata, _)  = runArrayData $ do-      aout <- newArrayData (size sh')--      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-    :: (Shape sh, Elt e)-    => (e -> e -> e)-    -> 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 (size sh)--      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)--      iter sh write (>>) (return ())-      return (aout, undefined)---scanr'Op-    :: forall sh e. (Shape sh, Elt e)-    => (e -> e -> e)-    -> e-    -> 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'          = 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:.n-1)) (fromElt z)--          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)-    -> Array sh' e-    -> (sh -> sh')-    -> Delayed (Array sh  e)-    -> Array sh' e-permuteOp f def@(Array _ adef) p (Delayed sh _ ain)-  = adata `seq` Array (fromElt sh') adata-  where-    sh'         = shape def-    n'          = size sh'-    f'          = sinkFromElt2 f-    ---    (adata, _)  = runArrayData $ do-      aout <- newArrayData n'--      let -- initialise array with default values-          init i-            | i >= n'   = return ()-            | otherwise = do-                x <- unsafeReadArrayData adef i-                unsafeWriteArrayData aout i x-                init (i+1)--          -- project each element onto the destination array and update-          update src-            = let dst   = p src-                  i     = toIndex sh  src-                  j     = toIndex sh' dst-              in-              unless (fromElt dst == R.ignore) $ do-                x <- return . fromElt $  ain  i-                y <- unsafeReadArrayData aout j-                unsafeWriteArrayData aout j (f' x y)--      init 0-      iter sh update (>>) (return ())-      return (aout, undefined)---backpermuteOp-    :: (Shape sh', Elt e)-    => sh'-    -> (sh' -> sh)-    -> Delayed (Array sh e)-    -> Array sh' e-backpermuteOp sh' p (Delayed _ arr _)-  = fromFunction sh' (\ix -> arr $ p ix)---stencilOp-    :: (Stencil sh a stencil, Elt b)-    => (stencil -> b)-    -> Boundary (Array sh a)-    -> Delayed  (Array sh a)-    -> Array sh b-stencilOp stencil bnd arr@(Delayed sh _ _)-  = fromFunction sh-  $ stencil . stencilAccess (bounded bnd arr)---stencil2Op-    :: (Stencil sh a stencil1, Stencil sh b stencil2, Elt c)-    => (stencil1 -> stencil2 -> c)-    -> Boundary (Array sh a)-    -> Delayed  (Array sh a)-    -> Boundary (Array sh b)-    -> Delayed  (Array sh b)-    -> Array sh c-stencil2Op stencil bnd1 arr1@(Delayed sh1 _ _) bnd2 arr2@(Delayed sh2 _ _)-  = fromFunction (sh1 `intersect` sh2) f-  where-    f ix  = stencil (stencilAccess (bounded bnd1 arr1) ix)-                    (stencilAccess (bounded bnd2 arr2) ix)--stencilAccess-    :: Stencil sh e stencil-    => (sh -> e)-    -> sh-    -> stencil-stencilAccess = goR stencil-  where-    -- Base cases, nothing interesting to do here since we know the lower-    -- dimension is Z.-    ---    goR :: StencilR sh e stencil -> (sh -> e) -> sh -> stencil-    goR StencilRunit3 rf ix =-      let-          z :. i = ix-          rf' d  = rf (z :. i+d)-      in-      ( rf' (-1)-      , rf'   0-      , rf'   1-      )--    goR StencilRunit5 rf ix =-      let z :. i = ix-          rf' d  = rf (z :. i+d)-      in-      ( rf' (-2)-      , rf' (-1)-      , rf'   0-      , rf'   1-      , rf'   2-      )--    goR StencilRunit7 rf ix =-      let z :. i = ix-          rf' d  = rf (z :. i+d)-      in-      ( rf' (-3)-      , rf' (-2)-      , rf' (-1)-      , rf'   0-      , rf'   1-      , rf'   2-      , rf'   3-      )--    goR StencilRunit9 rf ix =-      let z :. i = ix-          rf' d  = rf (z :. i+d)-      in-      ( rf' (-4)-      , rf' (-3)-      , rf' (-2)-      , rf' (-1)-      , rf'   0-      , rf'   1-      , rf'   2-      , rf'   3-      , rf'   4-      )--    -- Recursive cases. Note that because the stencil pattern is defined with-    -- cons ordering, whereas shapes (and indices) are defined as a snoc-list,-    -- when we recurse on the stencil structure we must manipulate the-    -- _left-most_ index component.-    ---    goR (StencilRtup3 s1 s2 s3) rf ix =-      let (i, ix') = uncons ix-          rf' d ds = rf (cons (i+d) ds)-      in-      ( goR s1 (rf' (-1)) ix'-      , goR s2 (rf'   0)  ix'-      , goR s3 (rf'   1)  ix'-      )--    goR (StencilRtup5 s1 s2 s3 s4 s5) rf ix =-      let (i, ix') = uncons ix-          rf' d ds = rf (cons (i+d) ds)-      in-      ( goR s1 (rf' (-2)) ix'-      , goR s2 (rf' (-1)) ix'-      , goR s3 (rf'   0)  ix'-      , goR s4 (rf'   1)  ix'-      , goR s5 (rf'   2)  ix'-      )--    goR (StencilRtup7 s1 s2 s3 s4 s5 s6 s7) rf ix =-      let (i, ix') = uncons ix-          rf' d ds = rf (cons (i+d) ds)-      in-      ( goR s1 (rf' (-3)) ix'-      , goR s2 (rf' (-2)) ix'-      , goR s3 (rf' (-1)) ix'-      , goR s4 (rf'   0)  ix'-      , goR s5 (rf'   1)  ix'-      , goR s6 (rf'   2)  ix'-      , goR s7 (rf'   3)  ix'-      )--    goR (StencilRtup9 s1 s2 s3 s4 s5 s6 s7 s8 s9) rf ix =-      let (i, ix') = uncons ix-          rf' d ds = rf (cons (i+d) ds)-      in-      ( goR s1 (rf' (-4)) ix'-      , goR s2 (rf' (-3)) ix'-      , goR s3 (rf' (-2)) ix'-      , goR s4 (rf' (-1)) ix'-      , goR s5 (rf'   0)  ix'-      , goR s6 (rf'   1)  ix'-      , goR s7 (rf'   2)  ix'-      , goR s8 (rf'   3)  ix'-      , goR s9 (rf'   4)  ix'-      )--    -- Add a left-most component to an index-    ---    cons :: forall sh. Shape sh => Int -> sh -> (sh :. Int)-    cons ix extent = toElt $ go (eltType (undefined::sh)) (fromElt extent)-      where-        go :: TupleType t -> t -> (t, Int)-        go TypeRunit         ()       = ((), ix)-        go (TypeRpair th tz) (sh, sz)-          | TypeRscalar t <- tz-          , Just Refl     <- matchScalarType t (scalarType :: ScalarType Int)-          = (go th sh, sz)-        go _ _-          = $internalError "cons" "expected index with Int components"--    -- Remove the left-most index of an index, and return the remainder-    ---    uncons :: forall sh. Shape sh => sh :. Int -> (Int, sh)-    uncons extent = let (i,ix) = go (eltType (undefined::(sh:.Int))) (fromElt extent)-                    in  (i, toElt ix)-      where-        go :: TupleType (t, Int) -> (t, Int) -> (Int, t)-        go (TypeRpair TypeRunit _)           ((), v) = (v, ())-        go (TypeRpair t1@(TypeRpair _ t2) _) (v1,v3)-          | TypeRscalar t <- t2-          , Just Refl     <- matchScalarType t (scalarType :: ScalarType Int)-          = let (i, v1') = go t1 v1-            in  (i, (v1', v3))-        go _ _-          = $internalError "uncons" "expected index with Int components"---bounded-    :: (Shape sh, Elt e)-    => Boundary (Array sh e)-    -> Delayed (Array sh e)-    -> sh-    -> e-bounded bnd (Delayed sh f _) ix =-  if inside sh ix-    then f ix-    else-      case bnd of-        Function g -> g ix-        Constant v -> toElt v-        _          -> f (bound sh ix)--  where-    -- Whether the index (second argument) is inside the bounds of the given-    -- shape (first argument).-    ---    inside :: forall sh. Shape sh => sh -> sh -> Bool-    inside sh1 ix1 = go (eltType (undefined::sh)) (fromElt sh1) (fromElt ix1)-      where-        go :: TupleType t -> t -> t -> Bool-        go TypeRunit          ()       ()      = True-        go (TypeRpair tsh ti) (sh, sz) (ih,iz)-          = if go ti sz iz-              then go tsh sh ih-              else False-        go (TypeRscalar t) sz iz-          | Just Refl <- matchScalarType t (scalarType :: ScalarType Int)-          = if iz < 0 || iz >= sz-              then False-              else True-          ---          | otherwise-          = $internalError "inside" "expected index with Int components"--    -- Return the index (second argument), updated to obey the given boundary-    -- conditions when outside the bounds of the given shape (first argument)-    ---    bound :: forall sh. Shape sh => sh -> sh -> sh-    bound sh1 ix1 = toElt $ go (eltType (undefined::sh)) (fromElt sh1) (fromElt ix1)-      where-        go :: TupleType t -> t -> t -> t-        go TypeRunit          ()       ()       = ()-        go (TypeRpair tsh ti) (sh, sz) (ih, iz) = (go tsh sh ih, go ti sz iz)-        go (TypeRscalar t)    sz       iz-          | Just Refl <- matchScalarType t (scalarType :: ScalarType Int)-          = let i | iz < 0    = case bnd of-                                  Clamp  -> 0-                                  Mirror -> -iz-                                  Wrap   -> sz + iz-                                  _      -> $internalError "bound" "unexpected boundary condition"-                  | iz >= sz  = case bnd of-                                  Clamp  -> sz - 1-                                  Mirror -> sz - (iz - sz + 2)-                                  Wrap   -> iz - sz-                                  _      -> $internalError "bound" "unexpected boundary condition"-                  | otherwise = iz-            in i-          | otherwise-          = $internalError "bound" "expected index with Int components"----- 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))----- Stencil boundary conditions--- -----------------------------data Boundary t where-  Clamp    :: Boundary t-  Mirror   :: Boundary t-  Wrap     :: Boundary t-  Constant :: Elt t => EltRepr t -> Boundary (Array sh t)-  Function :: (Shape sh, Elt e) => (sh -> e) -> Boundary (Array sh e)---evalPreBoundary :: EvalAcc acc -> AST.PreBoundary acc aenv t -> Val aenv -> Boundary t-evalPreBoundary evalAcc bnd aenv =-  case bnd of-    AST.Clamp      -> Clamp-    AST.Mirror     -> Mirror-    AST.Wrap       -> Wrap-    AST.Constant v -> Constant v-    AST.Function f -> Function (evalPreFun evalAcc f aenv)----- Scalar expression evaluation--- -------------------------------- Evaluate a closed scalar expression----evalPreExp :: EvalAcc acc -> PreExp acc aenv t -> Val aenv -> t-evalPreExp evalAcc e aenv = evalPreOpenExp evalAcc e EmptyElt aenv---- Evaluate a closed scalar function----evalPreFun :: EvalAcc acc -> PreFun acc aenv t -> Val aenv -> t-evalPreFun evalAcc f aenv = evalPreOpenFun evalAcc f EmptyElt aenv---- Evaluate an open scalar function----evalPreOpenFun :: EvalAcc acc -> PreOpenFun acc env aenv t -> ValElt env -> Val aenv -> t-evalPreOpenFun evalAcc (Body e) env aenv = evalPreOpenExp evalAcc e env aenv-evalPreOpenFun evalAcc (Lam f)  env aenv =-  \x -> evalPreOpenFun evalAcc f (env `PushElt` fromElt x) aenv----- Evaluate an open scalar expression------ NB: The implementation of 'Index' and 'Shape' demonstrate clearly why---     array expressions must be hoisted out of scalar expressions before code---     execution. If these operations are in the body of a function that gets---     mapped over an array, the array argument would be evaluated many times---     leading to a large amount of wasteful recomputation.----evalPreOpenExp-    :: forall acc env aenv t.-       EvalAcc acc-    -> PreOpenExp acc env aenv t-    -> ValElt env-    -> Val aenv-    -> t-evalPreOpenExp evalAcc pexp env aenv =-  let-      evalE :: PreOpenExp acc env aenv t' -> t'-      evalE e = evalPreOpenExp evalAcc e env aenv--      evalF :: PreOpenFun acc env aenv f' -> f'-      evalF f = evalPreOpenFun evalAcc f env aenv--      evalA :: acc aenv a -> a-      evalA a = evalAcc a aenv-  in-  case pexp of-    Let exp1 exp2               -> let !v1  = evalE exp1-                                       env' = env `PushElt` fromElt v1-                                   in  evalPreOpenExp evalAcc exp2 env' aenv-    Var ix                      -> prjElt ix env-    Const c                     -> toElt c-    Undef                       -> evalUndef-    PrimConst c                 -> evalPrimConst c-    PrimApp f x                 -> evalPrim f (evalE x)-    Tuple tup                   -> toTuple $ evalTuple evalAcc tup env aenv-    Prj ix tup                  -> evalPrj ix . fromTuple $ evalE tup-    IndexNil                    -> Z-    IndexAny                    -> Any-    IndexCons sh sz             -> evalE sh :. evalE sz-    IndexHead sh                -> let _  :. ix = evalE sh in ix-    IndexTail sh                -> let ix :. _  = evalE sh in ix-    IndexSlice slice slix sh    -> toElt $ restrict slice (fromElt (evalE slix))-                                                          (fromElt (evalE sh))-      where-        restrict :: SliceIndex slix sl co sh -> slix -> sh -> sl-        restrict SliceNil              ()        ()         = ()-        restrict (SliceAll sliceIdx)   (slx, ()) (sl, sz)   =-          let sl' = restrict sliceIdx slx sl-          in  (sl', sz)-        restrict (SliceFixed sliceIdx) (slx, _i)  (sl, _sz) =-          restrict sliceIdx slx sl--    IndexFull slice slix sh     -> toElt $ extend slice (fromElt (evalE slix))-                                                        (fromElt (evalE sh))-      where-        extend :: SliceIndex slix sl co sh -> slix -> sl -> sh-        extend SliceNil              ()        ()       = ()-        extend (SliceAll sliceIdx)   (slx, ()) (sl, sz) =-          let sh' = extend sliceIdx slx sl-          in  (sh', sz)-        extend (SliceFixed sliceIdx) (slx, sz) sl       =-          let sh' = extend sliceIdx slx sl-          in  (sh', sz)--    ToIndex sh ix               -> toIndex (evalE sh) (evalE ix)-    FromIndex sh ix             -> fromIndex (evalE sh) (evalE ix)-    Cond c t e-      | evalE c                 -> evalE t-      | otherwise               -> evalE e--    While cond body seed        -> go (evalE seed)-      where-        f       = evalF body-        p       = evalF cond-        go !x-          | p x         = go (f x)-          | otherwise   = x--    Index acc ix                -> evalA acc ! evalE ix-    LinearIndex acc i           -> let a  = evalA acc-                                       ix = fromIndex (shape a) (evalE i)-                                   in a ! ix-    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-    Coerce e                    -> evalCoerce (evalE e)----- Constant values--- -----------------evalUndef :: forall a. Elt a => a-evalUndef = toElt (undef (eltType (undefined::a)))-  where-    undef :: TupleType t -> t-    undef TypeRunit       = ()-    undef (TypeRpair a b) = (undef a, undef b)-    undef (TypeRscalar t) = scalar t--    scalar :: ScalarType t -> t-    scalar (SingleScalarType t) = single t-    scalar (VectorScalarType t) = vector t--    single :: SingleType t -> t-    single (NumSingleType    t) = num t-    single (NonNumSingleType t) = nonnum t--    vector :: VectorType t -> t-    vector (Vector2Type t)  = let x = single t in V2 x x-    vector (Vector3Type t)  = let x = single t in V3 x x x-    vector (Vector4Type t)  = let x = single t in V4 x x x x-    vector (Vector8Type t)  = let x = single t in V8 x x x x x x x x-    vector (Vector16Type t) = let x = single t in V16 x x x x x x x x x x x x x x x x--    num :: NumType t -> t-    num (IntegralNumType t) | IntegralDict <- integralDict t = 0-    num (FloatingNumType t) | FloatingDict <- floatingDict t = 0--    nonnum :: NonNumType t -> t-    nonnum TypeBool{}   = False-    nonnum TypeChar{}   = chr 0-    nonnum TypeCChar{}  = CChar 0-    nonnum TypeCSChar{} = CSChar 0-    nonnum TypeCUChar{} = CUChar 0----- Coercions--- -----------evalCoerce :: forall a b. (Elt a, Elt b) => a -> b-evalCoerce = toElt . go (eltType (undefined::a)) (eltType (undefined::b)) . fromElt-  where-    go :: TupleType s -> TupleType t -> s -> t-    go TypeRunit        TypeRunit          ()    = ()-    go (TypeRscalar s)   (TypeRscalar t)   x     = evalCoerceScalar s t x-    go (TypeRpair s1 s2) (TypeRpair t1 t2) (x,y) = (go s1 t1 x, go s2 t2 y)-    ---    -- newtype wrappers are typically declared similarly to `EltRepr (T a) = ((), EltRepr a)'-    ---    go (TypeRpair TypeRunit s) t@TypeRscalar{}         ((), x) = go s t x-    go s@TypeRscalar{}         (TypeRpair TypeRunit t) x       = ((), go s t x)-    ---    go _ _ _-      = error $ printf "could not coerce type `%s' to `%s'"-                  (show (typeOf (undefined::a)))-                  (show (typeOf (undefined::b)))----- Coerce a value by writing that data into memory and reading it back at--- a different type. This seems the most robust way to do it in the presence of--- packed vector types (which Haskell does not represent in the same way as--- C due to alignment of the fields, even at specialised UNPACKed types).----evalCoerceScalar :: ScalarType a -> ScalarType b -> a -> b-evalCoerceScalar ta tb a-  = $internalCheck "evalCoerce" "sizes not equal" (sizeOf (TypeRscalar ta) == sizeOf (TypeRscalar tb))-  $ withDict (scalar ta)-  $ withDict (scalar tb)-  $ let (adata, _)  = runArrayData $ do-                        arr <- newArrayData 1-                        unsafeWriteArrayData arr 0 a-                        return (arr, undefined)-        adata'      = fromUA arrayElt (toUA arrayElt adata)-    in-    unsafeIndexArrayData adata' 0-  where--    toUA :: ArrayEltR e -> ArrayData e -> UniqueArray ()-    toUA ArrayEltRint       (AD_Int ua)     = castUniqueArray ua-    toUA ArrayEltRint8      (AD_Int8 ua)    = castUniqueArray ua-    toUA ArrayEltRint16     (AD_Int16 ua)   = castUniqueArray ua-    toUA ArrayEltRint32     (AD_Int32 ua)   = castUniqueArray ua-    toUA ArrayEltRint64     (AD_Int64 ua)   = castUniqueArray ua-    toUA ArrayEltRword      (AD_Word ua)    = castUniqueArray ua-    toUA ArrayEltRword8     (AD_Word8 ua)   = castUniqueArray ua-    toUA ArrayEltRword16    (AD_Word16 ua)  = castUniqueArray ua-    toUA ArrayEltRword32    (AD_Word32 ua)  = castUniqueArray ua-    toUA ArrayEltRword64    (AD_Word64 ua)  = castUniqueArray ua-    toUA ArrayEltRcshort    (AD_CShort ua)  = castUniqueArray ua-    toUA ArrayEltRcushort   (AD_CUShort ua) = castUniqueArray ua-    toUA ArrayEltRcint      (AD_CInt ua)    = castUniqueArray ua-    toUA ArrayEltRcuint     (AD_CUInt ua)   = castUniqueArray ua-    toUA ArrayEltRclong     (AD_CLong ua)   = castUniqueArray ua-    toUA ArrayEltRculong    (AD_CULong ua)  = castUniqueArray ua-    toUA ArrayEltRcllong    (AD_CLLong ua)  = castUniqueArray ua-    toUA ArrayEltRcullong   (AD_CULLong ua) = castUniqueArray ua-    toUA ArrayEltRhalf      (AD_Half ua)    = castUniqueArray ua-    toUA ArrayEltRfloat     (AD_Float ua)   = castUniqueArray ua-    toUA ArrayEltRdouble    (AD_Double ua)  = castUniqueArray ua-    toUA ArrayEltRcfloat    (AD_CFloat ua)  = castUniqueArray ua-    toUA ArrayEltRcdouble   (AD_CDouble ua) = castUniqueArray ua-    toUA ArrayEltRbool      (AD_Bool ua)    = castUniqueArray ua-    toUA ArrayEltRchar      (AD_Char ua)    = castUniqueArray ua-    toUA ArrayEltRcchar     (AD_CChar ua)   = castUniqueArray ua-    toUA ArrayEltRcschar    (AD_CSChar ua)  = castUniqueArray ua-    toUA ArrayEltRcuchar    (AD_CUChar ua)  = castUniqueArray ua-    toUA (ArrayEltRvec2 r)  (AD_V2 a)       = toUA r a-    toUA (ArrayEltRvec3 r)  (AD_V3 a)       = toUA r a-    toUA (ArrayEltRvec4 r)  (AD_V4 a)       = toUA r a-    toUA (ArrayEltRvec8 r)  (AD_V8 a)       = toUA r a-    toUA (ArrayEltRvec16 r) (AD_V16 a)      = toUA r a-    ---    toUA ArrayEltRunit      _               = error "What sane person could live in this world and not be crazy?"-    toUA ArrayEltRpair{}    _               = error "  --- Ursula K. Le Guin"--    fromUA :: ArrayEltR e -> UniqueArray () -> ArrayData e-    fromUA ArrayEltRint       = AD_Int     . castUniqueArray-    fromUA ArrayEltRint8      = AD_Int8    . castUniqueArray-    fromUA ArrayEltRint16     = AD_Int16   . castUniqueArray-    fromUA ArrayEltRint32     = AD_Int32   . castUniqueArray-    fromUA ArrayEltRint64     = AD_Int64   . castUniqueArray-    fromUA ArrayEltRword      = AD_Word    . castUniqueArray-    fromUA ArrayEltRword8     = AD_Word8   . castUniqueArray-    fromUA ArrayEltRword16    = AD_Word16  . castUniqueArray-    fromUA ArrayEltRword32    = AD_Word32  . castUniqueArray-    fromUA ArrayEltRword64    = AD_Word64  . castUniqueArray-    fromUA ArrayEltRcshort    = AD_CShort  . castUniqueArray-    fromUA ArrayEltRcushort   = AD_CUShort . castUniqueArray-    fromUA ArrayEltRcint      = AD_CInt    . castUniqueArray-    fromUA ArrayEltRcuint     = AD_CUInt   . castUniqueArray-    fromUA ArrayEltRclong     = AD_CLong   . castUniqueArray-    fromUA ArrayEltRculong    = AD_CULong  . castUniqueArray-    fromUA ArrayEltRcllong    = AD_CLLong  . castUniqueArray-    fromUA ArrayEltRcullong   = AD_CULLong . castUniqueArray-    fromUA ArrayEltRhalf      = AD_Half    . castUniqueArray-    fromUA ArrayEltRfloat     = AD_Float   . castUniqueArray-    fromUA ArrayEltRdouble    = AD_Double  . castUniqueArray-    fromUA ArrayEltRcfloat    = AD_CFloat  . castUniqueArray-    fromUA ArrayEltRcdouble   = AD_CDouble . castUniqueArray-    fromUA ArrayEltRbool      = AD_Bool    . castUniqueArray-    fromUA ArrayEltRchar      = AD_Char    . castUniqueArray-    fromUA ArrayEltRcchar     = AD_CChar   . castUniqueArray-    fromUA ArrayEltRcschar    = AD_CSChar  . castUniqueArray-    fromUA ArrayEltRcuchar    = AD_CUChar  . castUniqueArray-    fromUA (ArrayEltRvec2 r)  = AD_V2      . fromUA r-    fromUA (ArrayEltRvec3 r)  = AD_V3      . fromUA r-    fromUA (ArrayEltRvec4 r)  = AD_V4      . fromUA r-    fromUA (ArrayEltRvec8 r)  = AD_V8      . fromUA r-    fromUA (ArrayEltRvec16 r) = AD_V16     . fromUA r-    ---    fromUA ArrayEltRunit      = error "I talk about the gods, I am an atheist. But I am an artist too, and therefore a liar. Distrust everything I say. I am telling the truth."-    fromUA ArrayEltRpair{}    = error "  --- Ursula K. Le Guin, The Left Hand of Darkness"--    castUniqueArray :: UniqueArray x -> UniqueArray y-    castUniqueArray (UniqueArray uid (Lifetime r w p)) =-      UniqueArray uid (Lifetime r w (castForeignPtr p))--    scalar :: ScalarType e -> Dict (ArrayElt e)-    scalar (SingleScalarType t) = single t-    scalar (VectorScalarType t) = vector t--    single :: SingleType e -> Dict (ArrayElt e)-    single (NumSingleType t)    = num t-    single (NonNumSingleType t) = nonnum t--    vector :: VectorType e -> Dict (ArrayElt e)-    vector (Vector2Type t)  = withDict (single t) Dict-    vector (Vector3Type t)  = withDict (single t) Dict-    vector (Vector4Type t)  = withDict (single t) Dict-    vector (Vector8Type t)  = withDict (single t) Dict-    vector (Vector16Type t) = withDict (single t) Dict--    num :: NumType e -> Dict (ArrayElt e)-    num (IntegralNumType t) = integral t-    num (FloatingNumType t) = floating t--    integral :: IntegralType e -> Dict (ArrayElt e)-    integral TypeInt{}     = Dict-    integral TypeInt8{}    = Dict-    integral TypeInt16{}   = Dict-    integral TypeInt32{}   = Dict-    integral TypeInt64{}   = Dict-    integral TypeWord{}    = Dict-    integral TypeWord8{}   = Dict-    integral TypeWord16{}  = Dict-    integral TypeWord32{}  = Dict-    integral TypeWord64{}  = Dict-    integral TypeCShort{}  = Dict-    integral TypeCUShort{} = Dict-    integral TypeCInt{}    = Dict-    integral TypeCUInt{}   = Dict-    integral TypeCLong{}   = Dict-    integral TypeCULong{}  = Dict-    integral TypeCLLong{}  = Dict-    integral TypeCULLong{} = Dict--    floating :: FloatingType e -> Dict (ArrayElt e)-    floating TypeHalf{}    = Dict-    floating TypeFloat{}   = Dict-    floating TypeDouble{}  = Dict-    floating TypeCFloat{}  = Dict-    floating TypeCDouble{} = Dict--    nonnum :: NonNumType e -> Dict (ArrayElt e)-    nonnum TypeBool{}   = Dict-    nonnum TypeChar{}   = Dict-    nonnum TypeCChar{}  = Dict-    nonnum TypeCSChar{} = Dict-    nonnum TypeCUChar{} = Dict----- Scalar primitives--- -------------------evalPrimConst :: PrimConst a -> a-evalPrimConst (PrimMinBound ty) = evalMinBound ty-evalPrimConst (PrimMaxBound ty) = evalMaxBound ty-evalPrimConst (PrimPi       ty) = evalPi ty--evalPrim :: (Elt a, Elt r) => PrimFun (a -> r) -> (a -> r)-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 (PrimIsInfinite         ty) = evalIsInfinite 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----- Tuple construction and projection--- -----------------------------------evalTuple :: EvalAcc acc -> Tuple (PreOpenExp acc env aenv) t -> ValElt env -> Val aenv -> t-evalTuple _       NilTup            _env _aenv = ()-evalTuple evalAcc (tup `SnocTup` e) env  aenv  =-  (evalTuple evalAcc tup env aenv, evalPreOpenExp evalAcc e env aenv)--evalPrj :: TupleIdx t e -> t -> e-evalPrj ZeroTupIdx       (!_, v)   = v-evalPrj (SuccTupIdx idx) (tup, !_) = evalPrj idx tup-  -- FIXME: Strictly speaking, we ought to force all components of a tuples;-  --        not only those that we happen to encounter during the recursive-  --        walk.----- Implementation of scalar primitives--- -------------------------------------evalLAnd :: (Bool, Bool) -> Bool-evalLAnd (x, y) = x && y--evalLOr  :: (Bool, Bool) -> Bool-evalLOr (x, y) = x || y--evalLNot :: Bool -> Bool-evalLNot = not--evalOrd :: Char -> Int-evalOrd = ord--evalChr :: Int -> Char-evalChr = chr--evalBoolToInt :: Bool -> Int-evalBoolToInt True  = 1-evalBoolToInt False = 0--evalFromIntegral :: IntegralType a -> NumType b -> a -> b-evalFromIntegral ta (IntegralNumType tb)-  | IntegralDict <- integralDict ta-  , IntegralDict <- integralDict tb-  = fromIntegral--evalFromIntegral ta (FloatingNumType tb)-  | IntegralDict <- integralDict ta-  , 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------- Constant methods of Bounded-----evalMinBound :: BoundedType a -> a-evalMinBound (IntegralBoundedType ty)-  | IntegralDict <- integralDict ty-  = minBound--evalMinBound (NonNumBoundedType   ty)-  | NonNumDict   <- nonNumDict ty-  = minBound--evalMaxBound :: BoundedType a -> a-evalMaxBound (IntegralBoundedType ty)-  | IntegralDict <- integralDict ty-  = maxBound--evalMaxBound (NonNumBoundedType   ty)-  | NonNumDict   <- nonNumDict ty-  = maxBound---- Constant method of floating-----evalPi :: FloatingType a -> a-evalPi ty | FloatingDict <- floatingDict ty = pi--evalSin :: FloatingType a -> (a -> a)-evalSin ty | FloatingDict <- floatingDict ty = sin--evalCos :: FloatingType a -> (a -> a)-evalCos ty | FloatingDict <- floatingDict ty = cos--evalTan :: FloatingType a -> (a -> a)-evalTan ty | FloatingDict <- floatingDict ty = tan--evalAsin :: FloatingType a -> (a -> a)-evalAsin ty | FloatingDict <- floatingDict ty = asin--evalAcos :: FloatingType a -> (a -> a)-evalAcos ty | FloatingDict <- floatingDict ty = acos--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--evalAcosh :: FloatingType a -> (a -> a)-evalAcosh ty | FloatingDict <- floatingDict ty = acosh--evalAtanh :: FloatingType a -> (a -> a)-evalAtanh ty | FloatingDict <- floatingDict ty = atanh--evalExpFloating :: FloatingType a -> (a -> a)-evalExpFloating ty | FloatingDict <- floatingDict ty = exp--evalSqrt :: FloatingType a -> (a -> a)-evalSqrt ty | FloatingDict <- floatingDict ty = sqrt--evalLog :: FloatingType a -> (a -> a)-evalLog ty | FloatingDict <- floatingDict ty = log--evalFPow :: FloatingType a -> ((a, a) -> a)-evalFPow ty | FloatingDict <- floatingDict ty = uncurry (**)--evalLogBase :: FloatingType a -> ((a, a) -> a)-evalLogBase ty | FloatingDict <- floatingDict ty = uncurry logBase--evalTruncate :: FloatingType a -> IntegralType b -> (a -> b)-evalTruncate ta tb-  | FloatingDict <- floatingDict ta-  , IntegralDict <- integralDict tb-  = truncate--evalRound :: FloatingType a -> IntegralType b -> (a -> b)-evalRound ta tb-  | FloatingDict <- floatingDict ta-  , IntegralDict <- integralDict tb-  = round--evalFloor :: FloatingType a -> IntegralType b -> (a -> b)-evalFloor ta tb-  | FloatingDict <- floatingDict ta-  , IntegralDict <- integralDict tb-  = floor--evalCeiling :: FloatingType a -> IntegralType b -> (a -> b)-evalCeiling ta tb-  | FloatingDict <- floatingDict ta-  , IntegralDict <- integralDict tb-  = ceiling--evalAtan2 :: FloatingType a -> ((a, a) -> a)-evalAtan2 ty | FloatingDict <- floatingDict ty = uncurry atan2--evalIsNaN :: FloatingType a -> (a -> Bool)-evalIsNaN ty | FloatingDict <- floatingDict ty = isNaN--evalIsInfinite :: FloatingType a -> (a -> Bool)-evalIsInfinite ty | FloatingDict <- floatingDict ty = isInfinite----- Methods of Num-----evalAdd :: NumType a -> ((a, a) -> a)-evalAdd (IntegralNumType ty) | IntegralDict <- integralDict ty = uncurry (+)-evalAdd (FloatingNumType ty) | FloatingDict <- floatingDict ty = uncurry (+)--evalSub :: NumType a -> ((a, a) -> a)-evalSub (IntegralNumType ty) | IntegralDict <- integralDict ty = uncurry (-)-evalSub (FloatingNumType ty) | FloatingDict <- floatingDict ty = uncurry (-)--evalMul :: NumType a -> ((a, a) -> a)-evalMul (IntegralNumType ty) | IntegralDict <- integralDict ty = uncurry (*)-evalMul (FloatingNumType ty) | FloatingDict <- floatingDict ty = uncurry (*)--evalNeg :: NumType a -> (a -> a)-evalNeg (IntegralNumType ty) | IntegralDict <- integralDict ty = negate-evalNeg (FloatingNumType ty) | FloatingDict <- floatingDict ty = negate--evalAbs :: NumType a -> (a -> a)-evalAbs (IntegralNumType ty) | IntegralDict <- integralDict ty = abs-evalAbs (FloatingNumType ty) | FloatingDict <- floatingDict ty = abs--evalSig :: NumType a -> (a -> a)-evalSig (IntegralNumType ty) | IntegralDict <- integralDict ty = signum-evalSig (FloatingNumType ty) | FloatingDict <- floatingDict ty = signum--evalQuot :: IntegralType a -> ((a, a) -> a)-evalQuot ty | IntegralDict <- integralDict ty = uncurry quot--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 (.&.)--evalBOr :: IntegralType a -> ((a, a) -> a)-evalBOr ty | IntegralDict <- integralDict ty = uncurry (.|.)--evalBXor :: IntegralType a -> ((a, a) -> a)-evalBXor ty | IntegralDict <- integralDict ty = uncurry xor--evalBNot :: IntegralType a -> (a -> a)-evalBNot ty | IntegralDict <- integralDict ty = complement--evalBShiftL :: IntegralType a -> ((a, Int) -> a)-evalBShiftL ty | IntegralDict <- integralDict ty = uncurry shiftL--evalBShiftR :: IntegralType a -> ((a, Int) -> a)-evalBShiftR ty | IntegralDict <- integralDict ty = uncurry shiftR--evalBRotateL :: IntegralType a -> ((a, Int) -> a)-evalBRotateL ty | IntegralDict <- integralDict ty = uncurry rotateL--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 (/)--evalRecip :: FloatingType a -> (a -> a)-evalRecip ty | FloatingDict <- floatingDict ty = recip---evalLt :: SingleType a -> ((a, a) -> Bool)-evalLt (NumSingleType (IntegralNumType ty)) | IntegralDict <- integralDict ty = uncurry (<)-evalLt (NumSingleType (FloatingNumType ty)) | FloatingDict <- floatingDict ty = uncurry (<)-evalLt (NonNumSingleType ty)                | NonNumDict   <- nonNumDict ty   = uncurry (<)--evalGt :: SingleType a -> ((a, a) -> Bool)-evalGt (NumSingleType (IntegralNumType ty)) | IntegralDict <- integralDict ty = uncurry (>)-evalGt (NumSingleType (FloatingNumType ty)) | FloatingDict <- floatingDict ty = uncurry (>)-evalGt (NonNumSingleType ty)                | NonNumDict   <- nonNumDict ty   = uncurry (>)--evalLtEq :: SingleType a -> ((a, a) -> Bool)-evalLtEq (NumSingleType (IntegralNumType ty)) | IntegralDict <- integralDict ty = uncurry (<=)-evalLtEq (NumSingleType (FloatingNumType ty)) | FloatingDict <- floatingDict ty = uncurry (<=)-evalLtEq (NonNumSingleType ty)                | NonNumDict   <- nonNumDict ty   = uncurry (<=)--evalGtEq :: SingleType a -> ((a, a) -> Bool)-evalGtEq (NumSingleType (IntegralNumType ty)) | IntegralDict <- integralDict ty = uncurry (>=)-evalGtEq (NumSingleType (FloatingNumType ty)) | FloatingDict <- floatingDict ty = uncurry (>=)-evalGtEq (NonNumSingleType ty)                | NonNumDict   <- nonNumDict ty   = uncurry (>=)--evalEq :: SingleType a -> ((a, a) -> Bool)-evalEq (NumSingleType (IntegralNumType ty)) | IntegralDict <- integralDict ty = uncurry (==)-evalEq (NumSingleType (FloatingNumType ty)) | FloatingDict <- floatingDict ty = uncurry (==)-evalEq (NonNumSingleType ty)                | NonNumDict   <- nonNumDict ty   = uncurry (==)--evalNEq :: SingleType a -> ((a, a) -> Bool)-evalNEq (NumSingleType (IntegralNumType ty)) | IntegralDict <- integralDict ty = uncurry (/=)-evalNEq (NumSingleType (FloatingNumType ty)) | FloatingDict <- floatingDict ty = uncurry (/=)-evalNEq (NonNumSingleType ty)                | NonNumDict   <- nonNumDict ty   = uncurry (/=)--evalMax :: SingleType a -> ((a, a) -> a)-evalMax (NumSingleType (IntegralNumType ty)) | IntegralDict <- integralDict ty = uncurry max-evalMax (NumSingleType (FloatingNumType ty)) | FloatingDict <- floatingDict ty = uncurry max-evalMax (NonNumSingleType ty)                | NonNumDict   <- nonNumDict ty   = uncurry max--evalMin :: SingleType a -> ((a, a) -> a)-evalMin (NumSingleType (IntegralNumType ty)) | IntegralDict <- integralDict ty = uncurry min-evalMin (NumSingleType (FloatingNumType ty)) | FloatingDict <- floatingDict ty = uncurry min-evalMin (NonNumSingleType 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)+{-# LANGUAGE FlexibleContexts    #-}+{-# LANGUAGE GADTs               #-}+{-# LANGUAGE MagicHash           #-}+{-# LANGUAGE PatternGuards       #-}+{-# LANGUAGE RankNTypes          #-}+{-# LANGUAGE RecordWildCards     #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TypeApplications    #-}+{-# LANGUAGE TypeFamilies        #-}+{-# LANGUAGE TypeOperators       #-}+{-# LANGUAGE ViewPatterns        #-}+{-# OPTIONS_GHC -fno-warn-name-shadowing #-}+{-# OPTIONS_HADDOCK prune #-}+-- |+-- Module      : Data.Array.Accelerate.Interpreter+-- Description : Reference backend (interpreted)+-- Copyright   : [2008..2020] The Accelerate Team+-- License     : BSD3+--+-- Maintainer  : Trevor L. McDonell <trevor.mcdonell@gmail.com>+-- 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 clearly, not on performance.+--++module Data.Array.Accelerate.Interpreter (++  Smart.Acc, Sugar.Arrays,+  Afunction, AfunctionR,++  -- * Interpret an array expression+  run, run1, runN,++  -- Internal (hidden)+  evalPrim, evalPrimConst, evalCoerceScalar,++) where++import Data.Array.Accelerate.AST                                    hiding ( Boundary(..) )+import Data.Array.Accelerate.AST.Environment+import Data.Array.Accelerate.AST.Var+import Data.Array.Accelerate.Array.Data+import Data.Array.Accelerate.Error+import Data.Array.Accelerate.Representation.Array+import Data.Array.Accelerate.Representation.Elt+import Data.Array.Accelerate.Representation.Shape+import Data.Array.Accelerate.Representation.Slice+import Data.Array.Accelerate.Representation.Stencil+import Data.Array.Accelerate.Representation.Tag+import Data.Array.Accelerate.Representation.Type+import Data.Array.Accelerate.Representation.Vec+import Data.Array.Accelerate.Trafo+import Data.Array.Accelerate.Trafo.Delayed                          ( DelayedOpenAfun, DelayedOpenAcc )+import Data.Array.Accelerate.Trafo.Sharing                          ( AfunctionR, AfunctionRepr(..), afunctionRepr )+import Data.Array.Accelerate.Type+import Data.Primitive.Vec+import qualified Data.Array.Accelerate.AST                          as AST+import qualified Data.Array.Accelerate.Debug                        as D+import qualified Data.Array.Accelerate.Smart                        as Smart+import qualified Data.Array.Accelerate.Sugar.Array                  as Sugar+import qualified Data.Array.Accelerate.Sugar.Elt                    as Sugar+import qualified Data.Array.Accelerate.Trafo.Delayed                as AST++import Control.DeepSeq+import Control.Exception+import Control.Monad+import Control.Monad.ST+import Data.Bits+import Data.Primitive.ByteArray+import Data.Primitive.Types+import System.IO.Unsafe                                             ( unsafePerformIO )+import Text.Printf                                                  ( printf )+import Unsafe.Coerce+import Prelude                                                      hiding ( (!!), sum )+++-- Program execution+-- -----------------++-- | Run a complete embedded array program using the reference interpreter.+--+run :: (HasCallStack, Sugar.Arrays a) => Smart.Acc a -> a+run a = unsafePerformIO execute+  where+    !acc    = convertAcc a+    execute = do+      D.dumpGraph $!! acc+      D.dumpSimplStats+      res <- phase "execute" D.elapsed $ evaluate $ evalOpenAcc acc Empty+      return $ Sugar.toArr $ snd res++-- | This is 'runN' specialised to an array program of one argument.+--+run1 :: (HasCallStack, Sugar.Arrays a, Sugar.Arrays b) => (Smart.Acc a -> Smart.Acc b) -> a -> b+run1 = runN++-- | Prepare and execute an embedded array program.+--+runN :: forall f. (HasCallStack, Afunction f) => f -> AfunctionR f+runN f = go+  where+    !acc    = convertAfun f+    !afun   = unsafePerformIO $ do+                D.dumpGraph $!! acc+                D.dumpSimplStats+                return acc+    !go     = eval (afunctionRepr @f) afun Empty+    --+    eval :: AfunctionRepr g (AfunctionR g) (ArraysFunctionR g)+         -> DelayedOpenAfun aenv (ArraysFunctionR g)+         -> Val aenv+         -> AfunctionR g+    eval (AfunctionReprLam reprF) (Alam lhs f) aenv = \a -> eval reprF f $ aenv `push` (lhs, Sugar.fromArr a)+    eval AfunctionReprBody        (Abody b)    aenv = unsafePerformIO $ phase "execute" D.elapsed (Sugar.toArr . snd <$> evaluate (evalOpenAcc b aenv))+    eval _                        _aenv        _    = error "Two men say they're Jesus; one of them must be wrong"++-- -- | 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'+++-- 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+-- --------------++-- Note that in contrast to the representation used in the optimised AST, the+-- delayed array representation used here is _only_ for delayed arrays --- we do+-- not require an optional Manifest|Delayed data type to evaluate the program.+--+data Delayed a where+  Delayed :: ArrayR (Array sh e)+          -> sh+          -> (sh -> e)+          -> (Int -> e)+          -> Delayed (Array sh e)+++-- Array expression evaluation+-- ---------------------------++type WithReprs acc = (ArraysR acc, acc)++fromFunction' :: ArrayR (Array sh e) -> sh -> (sh -> e) -> WithReprs (Array sh e)+fromFunction' repr sh f = (TupRsingle repr, fromFunction repr sh f)++-- Evaluate an open array function+--+evalOpenAfun :: HasCallStack => DelayedOpenAfun aenv f -> Val aenv -> f+evalOpenAfun (Alam lhs f) aenv = \a -> evalOpenAfun f $ aenv `push` (lhs, a)+evalOpenAfun (Abody b)    aenv = snd $ evalOpenAcc b aenv+++-- The core interpreter for optimised array programs+--+evalOpenAcc+    :: forall aenv a. HasCallStack+    => DelayedOpenAcc aenv a+    -> Val aenv+    -> WithReprs a+evalOpenAcc AST.Delayed{}       _    = internalError "expected manifest array"+evalOpenAcc (AST.Manifest pacc) aenv =+  let+      manifest :: forall a'. HasCallStack => DelayedOpenAcc aenv a' -> WithReprs a'+      manifest acc =+        let (repr, a') = evalOpenAcc acc aenv+        in  rnfArraysR repr a' `seq` (repr, a')++      delayed :: DelayedOpenAcc aenv (Array sh e) -> Delayed (Array sh e)+      delayed AST.Delayed{..} = Delayed reprD (evalE extentD) (evalF indexD) (evalF linearIndexD)+      delayed a' = Delayed aR (shape a) (indexArray aR a) (linearIndexArray (arrayRtype aR) a)+        where+          (TupRsingle aR, a) = manifest a'++      evalE :: Exp aenv t -> t+      evalE exp = evalExp exp aenv++      evalF :: Fun aenv f -> f+      evalF fun = evalFun fun aenv++      evalB :: AST.Boundary aenv t -> Boundary t+      evalB bnd = evalBoundary bnd aenv++      dir :: Direction -> t -> t -> t+      dir LeftToRight l _ = l+      dir RightToLeft _ r = r+  in+  case pacc of+    Avar (Var repr ix)          -> (TupRsingle repr, prj ix aenv)+    Alet lhs acc1 acc2          -> evalOpenAcc acc2 $ aenv `push` (lhs, snd $ manifest acc1)+    Apair acc1 acc2             -> let+                                     (r1, a1) = manifest acc1+                                     (r2, a2) = manifest acc2+                                   in+                                     (TupRpair r1 r2, (a1, a2))+    Anil                        -> (TupRunit, ())+    Apply repr afun acc         -> (repr, evalOpenAfun afun aenv $ snd $ manifest acc)+    Aforeign repr _ afun acc    -> (repr, evalOpenAfun afun Empty $ snd $ manifest acc)+    Acond p acc1 acc2+      | toBool (evalE p)        -> manifest acc1+      | otherwise               -> manifest acc2++    Awhile cond body acc        -> (repr, go initial)+      where+        (repr, initial) = manifest acc+        p       = evalOpenAfun cond aenv+        f       = evalOpenAfun body aenv+        go !x+          | toBool (linearIndexArray (Sugar.eltR @Word8) (p x) 0) = go (f x)+          | otherwise                                             = x++    Use repr arr                -> (TupRsingle repr, arr)+    Unit tp e                   -> unitOp tp (evalE e)+    -- Collect s                   -> evalSeq defaultSeqConfig s aenv++    -- Producers+    -- ---------+    Map tp f acc                -> mapOp tp (evalF f) (delayed acc)+    Generate repr sh f          -> generateOp repr (evalE sh) (evalF f)+    Transform repr sh p f acc   -> transformOp repr (evalE sh) (evalF p) (evalF f) (delayed acc)+    Backpermute shr sh p acc    -> backpermuteOp shr (evalE sh) (evalF p) (delayed acc)+    Reshape shr sh acc          -> reshapeOp shr (evalE sh) (manifest acc)++    ZipWith tp f acc1 acc2      -> zipWithOp tp (evalF f) (delayed acc1) (delayed acc2)+    Replicate slice slix acc    -> replicateOp slice (evalE slix) (manifest acc)+    Slice slice acc slix        -> sliceOp slice (manifest acc) (evalE slix)++    -- Consumers+    -- ---------+    Fold f (Just z) acc         -> foldOp (evalF f) (evalE z) (delayed acc)+    Fold f Nothing  acc         -> fold1Op (evalF f) (delayed acc)+    FoldSeg i f (Just z) acc seg -> foldSegOp i (evalF f) (evalE z) (delayed acc) (delayed seg)+    FoldSeg i f Nothing acc seg -> fold1SegOp i (evalF f) (delayed acc) (delayed seg)+    Scan  d f (Just z) acc      -> dir d scanlOp  scanrOp  (evalF f) (evalE z) (delayed acc)+    Scan  d f Nothing  acc      -> dir d scanl1Op scanr1Op (evalF f)           (delayed acc)+    Scan' d f z acc             -> dir d scanl'Op scanr'Op (evalF f) (evalE z) (delayed acc)+    Permute f def p acc         -> permuteOp (evalF f) (manifest def) (evalF p) (delayed acc)+    Stencil s tp sten b acc     -> stencilOp s tp (evalF sten) (evalB b) (delayed acc)+    Stencil2 s1 s2 tp sten b1 a1 b2 a2+                                -> stencil2Op s1 s2 tp (evalF sten) (evalB b1) (delayed a1) (evalB b2) (delayed a2)+++-- Array primitives+-- ----------------++unitOp :: TypeR e -> e -> WithReprs (Scalar e)+unitOp tp e = fromFunction' (ArrayR ShapeRz tp) () (const e)+++generateOp+    :: ArrayR (Array sh e)+    -> sh+    -> (sh -> e)+    -> WithReprs (Array sh e)+generateOp = fromFunction'+++transformOp+    :: ArrayR (Array sh' b)+    -> sh'+    -> (sh' -> sh)+    -> (a -> b)+    -> Delayed (Array sh a)+    -> WithReprs (Array sh' b)+transformOp repr sh' p f (Delayed _ _ xs _)+  = fromFunction' repr sh' (\ix -> f (xs $ p ix))+++reshapeOp+    :: HasCallStack+    => ShapeR sh+    -> sh+    -> WithReprs (Array sh' e)+    -> WithReprs (Array sh  e)+reshapeOp newShapeR newShape (TupRsingle (ArrayR shr tp), (Array sh adata))+  = boundsCheck "shape mismatch" (size newShapeR newShape == size shr sh)+    ( TupRsingle (ArrayR newShapeR tp)+    , Array newShape adata+    )+++replicateOp+    :: SliceIndex slix sl co sh+    -> slix+    -> WithReprs (Array sl e)+    -> WithReprs (Array sh e)+replicateOp slice slix (TupRsingle repr@(ArrayR _ tp), arr)+  = fromFunction' repr' sh (\ix -> (repr, arr) ! pf ix)+  where+    repr' = ArrayR (sliceDomainR slice) tp+    (sh, pf) = extend slice slix (shape arr)++    extend :: SliceIndex slix sl co dim+           -> slix+           -> sl+           -> (dim, dim -> sl)+    extend SliceNil              ()        ()+      = ((), const ())+    extend (SliceAll sliceIdx)   (slx, ()) (sl, sz)+      = let (dim', f') = extend sliceIdx slx sl+        in  ((dim', sz), \(ix, i) -> (f' ix, i))+    extend (SliceFixed sliceIdx) (slx, sz) sl+      = let (dim', f') = extend sliceIdx slx sl+        in  ((dim', sz), \(ix, _) -> f' ix)+++sliceOp+    :: SliceIndex slix sl co sh+    -> WithReprs (Array sh e)+    -> slix+    -> WithReprs (Array sl e)+sliceOp slice (TupRsingle repr@(ArrayR _ tp), arr) slix+  = fromFunction' repr' sh' (\ix -> (repr, arr) ! pf ix)+  where+    repr' = ArrayR (sliceShapeR slice) tp+    (sh', pf) = restrict slice slix (shape arr)++    restrict+        :: HasCallStack+        => SliceIndex slix sl co sh+        -> slix+        -> sh+        -> (sl, sl -> sh)+    restrict SliceNil              ()        ()+      = ((), const ())+    restrict (SliceAll sliceIdx)   (slx, ()) (sl, sz)+      = let (sl', f') = restrict sliceIdx slx sl+        in  ((sl', sz), \(ix, i) -> (f' ix, i))+    restrict (SliceFixed sliceIdx) (slx, i)  (sl, sz)+      = let (sl', f') = restrict sliceIdx slx sl+        in  indexCheck i sz $ (sl', \ix -> (f' ix, i))+++mapOp :: TypeR b+      -> (a -> b)+      -> Delayed   (Array sh a)+      -> WithReprs (Array sh b)+mapOp tp f (Delayed (ArrayR shr _) sh xs _)+  = fromFunction' (ArrayR shr tp) sh (\ix -> f (xs ix))+++zipWithOp+    :: TypeR c+    -> (a -> b -> c)+    -> Delayed   (Array sh a)+    -> Delayed   (Array sh b)+    -> WithReprs (Array sh c)+zipWithOp tp f (Delayed (ArrayR shr _) shx xs _) (Delayed _ shy ys _)+  = fromFunction' (ArrayR shr tp) (intersect shr shx shy) (\ix -> f (xs ix) (ys ix))+++foldOp+    :: (e -> e -> e)+    -> e+    -> Delayed (Array (sh, Int) e)+    -> WithReprs (Array sh e)+foldOp f z (Delayed (ArrayR (ShapeRsnoc shr) tp) (sh, n) arr _)+  = fromFunction' (ArrayR shr tp) sh (\ix -> iter (ShapeRsnoc ShapeRz) ((), n) (\((), i) -> arr (ix, i)) f z)+++fold1Op+    :: HasCallStack+    => (e -> e -> e)+    -> Delayed (Array (sh, Int) e)+    -> WithReprs (Array sh e)+fold1Op f (Delayed (ArrayR (ShapeRsnoc shr) tp) (sh, n) arr _)+  = boundsCheck "empty array" (n > 0)+  $ fromFunction' (ArrayR shr tp) sh (\ix -> iter1 (ShapeRsnoc ShapeRz) ((), n) (\((), i) -> arr (ix, i)) f)+++foldSegOp+    :: HasCallStack+    => IntegralType i+    -> (e -> e -> e)+    -> e+    -> Delayed (Array (sh, Int) e)+    -> Delayed (Segments i)+    -> WithReprs (Array (sh, Int) e)+foldSegOp itp f z (Delayed repr (sh, _) arr _) (Delayed _ ((), n) _ seg)+  | IntegralDict <- integralDict itp+  = boundsCheck "empty segment descriptor" (n > 0)+  $ fromFunction' repr (sh, n-1)+  $ \(sz, ix) ->   let start = fromIntegral $ seg ix+                       end   = fromIntegral $ seg (ix+1)+                   in+                   boundsCheck "empty segment" (end >= start)+                   $ iter (ShapeRsnoc ShapeRz) ((), end-start) (\((), i) -> arr (sz, start+i)) f z+++fold1SegOp+    :: HasCallStack+    => IntegralType i+    -> (e -> e -> e)+    -> Delayed (Array (sh, Int) e)+    -> Delayed (Segments i)+    -> WithReprs (Array (sh, Int) e)+fold1SegOp itp f (Delayed repr (sh, _) arr _) (Delayed _ ((), n) _ seg)+  | IntegralDict <- integralDict itp+  = boundsCheck "empty segment descriptor" (n > 0)+  $ fromFunction' repr (sh, n-1)+  $ \(sz, ix)   -> let start = fromIntegral $ seg ix+                       end   = fromIntegral $ seg (ix+1)+                   in+                   boundsCheck "empty segment" (end > start)+                   $ iter1 (ShapeRsnoc ShapeRz) ((), end-start) (\((), i) -> arr (sz, start+i)) f+++scanl1Op+    :: forall sh e. HasCallStack+    => (e -> e -> e)+    -> Delayed (Array (sh, Int) e)+    -> WithReprs (Array (sh, Int) e)+scanl1Op f (Delayed (ArrayR shr tp) sh@(_, n) ain _)+  = boundsCheck "empty array" (n > 0)+    ( TupRsingle $ ArrayR shr tp+    , adata `seq` Array sh adata+    )+  where+    --+    (adata, _)  = runArrayData @e $ do+      aout <- newArrayData tp (size shr sh)++      let write (sz, 0) = writeArrayData tp aout (toIndex shr sh (sz, 0)) (ain (sz, 0))+          write (sz, i) = do+            x <- readArrayData tp aout (toIndex shr sh (sz, i-1))+            let y = ain (sz, i)+            writeArrayData tp aout (toIndex shr sh (sz, i)) (f x y)++      iter shr sh write (>>) (return ())+      return (aout, undefined)+++scanlOp+    :: forall sh e.+       (e -> e -> e)+    -> e+    -> Delayed (Array (sh, Int) e)+    -> WithReprs (Array (sh, Int) e)+scanlOp f z (Delayed (ArrayR shr tp) (sh, n) ain _)+  = ( TupRsingle $ ArrayR shr tp+    , adata `seq` Array sh' adata+    )+  where+    sh'         = (sh, n+1)+    --+    (adata, _)  = runArrayData @e $ do+      aout <- newArrayData tp (size shr sh')++      let write (sz, 0) = writeArrayData tp aout (toIndex shr sh' (sz, 0)) z+          write (sz, i) = do+            x <- readArrayData tp aout (toIndex shr sh' (sz, i-1))+            let y = ain (sz, i-1)+            writeArrayData tp aout (toIndex shr sh' (sz, i)) (f x y)++      iter shr sh' write (>>) (return ())+      return (aout, undefined)+++scanl'Op+    :: forall sh e.+       (e -> e -> e)+    -> e+    -> Delayed (Array (sh, Int) e)+    -> WithReprs (Array (sh, Int) e, Array sh e)+scanl'Op f z (Delayed (ArrayR shr@(ShapeRsnoc shr') tp) (sh, n) ain _)+  = ( TupRsingle (ArrayR shr tp) `TupRpair` TupRsingle (ArrayR shr' tp)+    , aout `seq` asum `seq` ( Array (sh, n) aout, Array sh asum )+    )+  where+    ((aout, asum), _) = runArrayData @(e, e) $ do+      aout <- newArrayData tp (size shr  (sh, n))+      asum <- newArrayData tp (size shr' sh)++      let write (sz, 0)+            | n == 0    = writeArrayData tp asum (toIndex shr' sh sz) z+            | otherwise = writeArrayData tp aout (toIndex shr  (sh, n) (sz, 0)) z+          write (sz, i) = do+            x <- readArrayData tp aout (toIndex shr (sh, n) (sz, i-1))+            let y = ain (sz, i-1)+            if i == n+              then writeArrayData tp asum (toIndex shr' sh      sz)      (f x y)+              else writeArrayData tp aout (toIndex shr  (sh, n) (sz, i)) (f x y)++      iter shr (sh, n+1) write (>>) (return ())+      return ((aout, asum), undefined)+++scanrOp+    :: forall sh e.+       (e -> e -> e)+    -> e+    -> Delayed (Array (sh, Int) e)+    -> WithReprs (Array (sh, Int) e)+scanrOp f z (Delayed (ArrayR shr tp) (sz, n) ain _)+  = ( TupRsingle (ArrayR shr tp)+    , adata `seq` Array sh' adata+    )+  where+    sh'         = (sz, n+1)+    --+    (adata, _)  = runArrayData @e $ do+      aout <- newArrayData tp (size shr sh')++      let write (sz, 0) = writeArrayData tp aout (toIndex shr sh' (sz, n)) z+          write (sz, i) = do+            let x = ain (sz, n-i)+            y <- readArrayData tp aout (toIndex shr sh' (sz, n-i+1))+            writeArrayData tp aout (toIndex shr sh' (sz, n-i)) (f x y)++      iter shr sh' write (>>) (return ())+      return (aout, undefined)+++scanr1Op+    :: forall sh e. HasCallStack+    => (e -> e -> e)+    -> Delayed (Array (sh, Int) e)+    -> WithReprs (Array (sh, Int) e)+scanr1Op f (Delayed (ArrayR shr tp) sh@(_, n) ain _)+  = boundsCheck "empty array" (n > 0)+    ( TupRsingle $ ArrayR shr tp+    , adata `seq` Array sh adata+    )+  where+    (adata, _)  = runArrayData @e $ do+      aout <- newArrayData tp (size shr sh)++      let write (sz, 0) = writeArrayData tp aout (toIndex shr sh (sz, n-1)) (ain (sz, n-1))+          write (sz, i) = do+            let x = ain (sz, n-i-1)+            y <- readArrayData tp aout (toIndex shr sh (sz, n-i))+            writeArrayData tp aout (toIndex shr sh (sz, n-i-1)) (f x y)++      iter shr sh write (>>) (return ())+      return (aout, undefined)+++scanr'Op+    :: forall sh e.+       (e -> e -> e)+    -> e+    -> Delayed (Array (sh, Int) e)+    -> WithReprs (Array (sh, Int) e, Array sh e)+scanr'Op f z (Delayed (ArrayR shr@(ShapeRsnoc shr') tp) (sh, n) ain _)+  = ( TupRsingle (ArrayR shr tp) `TupRpair` TupRsingle (ArrayR shr' tp)+    , aout `seq` asum `seq` ( Array (sh, n) aout, Array sh asum )+    )+  where+    ((aout, asum), _) = runArrayData @(e, e) $ do+      aout <- newArrayData tp (size shr  (sh, n))+      asum <- newArrayData tp (size shr' sh)++      let write (sz, 0)+            | n == 0    = writeArrayData tp asum (toIndex shr' sh sz) z+            | otherwise = writeArrayData tp aout (toIndex shr  (sh, n) (sz, n-1)) z++          write (sz, i) = do+            let x = ain (sz, n-i)+            y <- readArrayData tp aout (toIndex shr (sh, n) (sz, n-i))+            if i == n+              then writeArrayData tp asum (toIndex shr' sh      sz)          (f x y)+              else writeArrayData tp aout (toIndex shr  (sh, n) (sz, n-i-1)) (f x y)++      iter shr (sh, n+1) write (>>) (return ())+      return ((aout, asum), undefined)+++permuteOp+    :: forall sh sh' e. HasCallStack+    => (e -> e -> e)+    -> WithReprs (Array sh' e)+    -> (sh -> PrimMaybe sh')+    -> Delayed   (Array sh  e)+    -> WithReprs (Array sh' e)+permuteOp f (TupRsingle (ArrayR shr' _), def@(Array _ adef)) p (Delayed (ArrayR shr tp) sh _ ain)+  = (TupRsingle $ ArrayR shr' tp, adata `seq` Array sh' adata)+  where+    sh'         = shape def+    n'          = size shr' sh'+    --+    (adata, _)  = runArrayData @e $ do+      aout <- newArrayData tp n'++      let -- initialise array with default values+          init i+            | i >= n'   = return ()+            | otherwise = do+                x <- readArrayData tp adef i+                writeArrayData tp aout i x+                init (i+1)++          -- project each element onto the destination array and update+          update src+            = case p src of+                (0,_)        -> return ()+                (1,((),dst)) -> do+                  let i = toIndex shr  sh  src+                      j = toIndex shr' sh' dst+                      x = ain i+                  --+                  y <- readArrayData tp aout j+                  writeArrayData tp aout j (f x y)+                _            -> internalError "unexpected tag"++      init 0+      iter shr sh update (>>) (return ())+      return (aout, undefined)+++backpermuteOp+    :: ShapeR sh'+    -> sh'+    -> (sh' -> sh)+    -> Delayed (Array sh e)+    -> WithReprs (Array sh' e)+backpermuteOp shr sh' p (Delayed (ArrayR _ tp) _ arr _)+  = fromFunction' (ArrayR shr tp) sh' (\ix -> arr $ p ix)+++stencilOp+    :: HasCallStack+    => StencilR sh a stencil+    -> TypeR b+    -> (stencil -> b)+    -> Boundary (Array sh a)+    -> Delayed  (Array sh a)+    -> WithReprs (Array sh b)+stencilOp stencil tp f bnd arr@(Delayed _ sh _ _)+  = fromFunction' (ArrayR shr tp) sh+  $ f . stencilAccess stencil (bounded shr bnd arr)+  where+    shr = stencilShapeR stencil+++stencil2Op+    :: HasCallStack+    => StencilR sh a stencil1+    -> StencilR sh b stencil2+    -> TypeR c+    -> (stencil1 -> stencil2 -> c)+    -> Boundary (Array sh a)+    -> Delayed  (Array sh a)+    -> Boundary (Array sh b)+    -> Delayed  (Array sh b)+    -> WithReprs (Array sh c)+stencil2Op s1 s2 tp stencil bnd1 arr1@(Delayed _ sh1 _ _) bnd2 arr2@(Delayed _ sh2 _ _)+  = fromFunction' (ArrayR shr tp) (intersect shr sh1 sh2) f+  where+    f ix  = stencil (stencilAccess s1 (bounded shr bnd1 arr1) ix)+                    (stencilAccess s2 (bounded shr bnd2 arr2) ix)+    shr = stencilShapeR s1++stencilAccess+    :: StencilR sh e stencil+    -> (sh -> e)+    -> sh+    -> stencil+stencilAccess stencil = goR (stencilShapeR stencil) stencil+  where+    -- Base cases, nothing interesting to do here since we know the lower+    -- dimension is Z.+    --+    goR :: ShapeR sh -> StencilR sh e stencil -> (sh -> e) -> sh -> stencil+    goR _ (StencilRunit3 _) rf ix =+      let+          (z, i) = ix+          rf' d  = rf (z, i+d)+      in+      ((( ()+      , rf' (-1))+      , rf'   0 )+      , rf'   1 )++    goR _ (StencilRunit5 _) rf ix =+      let (z, i) = ix+          rf' d  = rf (z, i+d)+      in+      ((((( ()+      , rf' (-2))+      , rf' (-1))+      , rf'   0 )+      , rf'   1 )+      , rf'   2 )++    goR _ (StencilRunit7 _) rf ix =+      let (z, i) = ix+          rf' d  = rf (z, i+d)+      in+      ((((((( ()+      , rf' (-3))+      , rf' (-2))+      , rf' (-1))+      , rf'   0 )+      , rf'   1 )+      , rf'   2 )+      , rf'   3 )++    goR _ (StencilRunit9 _) rf ix =+      let (z, i) = ix+          rf' d  = rf (z, i+d)+      in+      ((((((((( ()+      , rf' (-4))+      , rf' (-3))+      , rf' (-2))+      , rf' (-1))+      , rf'   0 )+      , rf'   1 )+      , rf'   2 )+      , rf'   3 )+      , rf'   4 )++    -- Recursive cases. Note that because the stencil pattern is defined with+    -- cons ordering, whereas shapes (and indices) are defined as a snoc-list,+    -- when we recurse on the stencil structure we must manipulate the+    -- _left-most_ index component.+    --+    goR (ShapeRsnoc shr) (StencilRtup3 s1 s2 s3) rf ix =+      let (i, ix') = uncons shr ix+          rf' d ds = rf (cons shr (i+d) ds)+      in+      ((( ()+      , goR shr s1 (rf' (-1)) ix')+      , goR shr s2 (rf'   0)  ix')+      , goR shr s3 (rf'   1)  ix')++    goR (ShapeRsnoc shr) (StencilRtup5 s1 s2 s3 s4 s5) rf ix =+      let (i, ix') = uncons shr ix+          rf' d ds = rf (cons shr (i+d) ds)+      in+      ((((( ()+      , goR shr s1 (rf' (-2)) ix')+      , goR shr s2 (rf' (-1)) ix')+      , goR shr s3 (rf'   0)  ix')+      , goR shr s4 (rf'   1)  ix')+      , goR shr s5 (rf'   2)  ix')++    goR (ShapeRsnoc shr) (StencilRtup7 s1 s2 s3 s4 s5 s6 s7) rf ix =+      let (i, ix') = uncons shr ix+          rf' d ds = rf (cons shr (i+d) ds)+      in+      ((((((( ()+      , goR shr s1 (rf' (-3)) ix')+      , goR shr s2 (rf' (-2)) ix')+      , goR shr s3 (rf' (-1)) ix')+      , goR shr s4 (rf'   0)  ix')+      , goR shr s5 (rf'   1)  ix')+      , goR shr s6 (rf'   2)  ix')+      , goR shr s7 (rf'   3)  ix')++    goR (ShapeRsnoc shr) (StencilRtup9 s1 s2 s3 s4 s5 s6 s7 s8 s9) rf ix =+      let (i, ix') = uncons shr ix+          rf' d ds = rf (cons shr (i+d) ds)+      in+      ((((((((( ()+      , goR shr s1 (rf' (-4)) ix')+      , goR shr s2 (rf' (-3)) ix')+      , goR shr s3 (rf' (-2)) ix')+      , goR shr s4 (rf' (-1)) ix')+      , goR shr s5 (rf'   0)  ix')+      , goR shr s6 (rf'   1)  ix')+      , goR shr s7 (rf'   2)  ix')+      , goR shr s8 (rf'   3)  ix')+      , goR shr s9 (rf'   4)  ix')++    -- Add a left-most component to an index+    --+    cons :: ShapeR sh -> Int -> sh -> (sh, Int)+    cons ShapeRz          ix ()       = ((), ix)+    cons (ShapeRsnoc shr) ix (sh, sz) = (cons shr ix sh, sz)++    -- Remove the left-most index of an index, and return the remainder+    --+    uncons :: ShapeR sh -> (sh, Int) -> (Int, sh)+    uncons ShapeRz          ((), v)  = (v, ())+    uncons (ShapeRsnoc shr) (v1, v2) = let (i, v1') = uncons shr v1+                                       in  (i, (v1', v2))+++bounded+    :: HasCallStack+    => ShapeR sh+    -> Boundary (Array sh e)+    -> Delayed (Array sh e)+    -> sh+    -> e+bounded shr bnd (Delayed _ sh f _) ix =+  if inside shr sh ix+    then f ix+    else+      case bnd of+        Function g -> g ix+        Constant v -> v+        _          -> f (bound shr sh ix)++  where+    -- Whether the index (second argument) is inside the bounds of the given+    -- shape (first argument).+    --+    inside :: ShapeR sh -> sh -> sh -> Bool+    inside ShapeRz          ()       ()       = True+    inside (ShapeRsnoc shr) (sh, sz) (ih, iz) = iz >= 0 && iz < sz && inside shr sh ih++    -- Return the index (second argument), updated to obey the given boundary+    -- conditions when outside the bounds of the given shape (first argument)+    --+    bound :: HasCallStack => ShapeR sh -> sh -> sh -> sh+    bound ShapeRz () () = ()+    bound (ShapeRsnoc shr) (sh, sz) (ih, iz) = (bound shr sh ih, ih')+      where+        ih'+          | iz < 0 = case bnd of+                          Clamp  -> 0+                          Mirror -> -iz+                          Wrap   -> sz + iz+                          _      -> internalError "unexpected boundary condition"+          | iz >= sz  = case bnd of+                          Clamp  -> sz - 1+                          Mirror -> sz - (iz - sz + 2)+                          Wrap   -> iz - sz+                          _      -> internalError "unexpected boundary condition"+          | otherwise = iz++-- 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))+++-- Stencil boundary conditions+-- ---------------------------++data Boundary t where+  Clamp    :: Boundary t+  Mirror   :: Boundary t+  Wrap     :: Boundary t+  Constant :: t -> Boundary (Array sh t)+  Function :: (sh -> e) -> Boundary (Array sh e)+++evalBoundary :: HasCallStack => AST.Boundary aenv t -> Val aenv -> Boundary t+evalBoundary bnd aenv =+  case bnd of+    AST.Clamp      -> Clamp+    AST.Mirror     -> Mirror+    AST.Wrap       -> Wrap+    AST.Constant v -> Constant v+    AST.Function f -> Function (evalFun f aenv)+++-- Scalar expression evaluation+-- ----------------------------++-- Evaluate a closed scalar expression+--+evalExp :: HasCallStack => Exp aenv t -> Val aenv -> t+evalExp e aenv = evalOpenExp e Empty aenv++-- Evaluate a closed scalar function+--+evalFun :: HasCallStack => Fun aenv t -> Val aenv -> t+evalFun f aenv = evalOpenFun f Empty aenv++-- Evaluate an open scalar function+--+evalOpenFun :: HasCallStack => OpenFun env aenv t -> Val env -> Val aenv -> t+evalOpenFun (Body e)    env aenv = evalOpenExp e env aenv+evalOpenFun (Lam lhs f) env aenv =+  \x -> evalOpenFun f (env `push` (lhs, x)) aenv+++-- Evaluate an open scalar expression+--+-- NB: The implementation of 'Index' and 'Shape' demonstrate clearly why+--     array expressions must be hoisted out of scalar expressions before code+--     execution. If these operations are in the body of a function that gets+--     mapped over an array, the array argument would be evaluated many times+--     leading to a large amount of wasteful recomputation.+--+evalOpenExp+    :: forall env aenv t. HasCallStack+    => OpenExp env aenv t+    -> Val env+    -> Val aenv+    -> t+evalOpenExp pexp env aenv =+  let+      evalE :: OpenExp env aenv t' -> t'+      evalE e = evalOpenExp e env aenv++      evalF :: OpenFun env aenv f' -> f'+      evalF f = evalOpenFun f env aenv++      evalA :: ArrayVar aenv a -> WithReprs a+      evalA (Var repr ix) = (TupRsingle repr, prj ix aenv)+  in+  case pexp of+    Let lhs exp1 exp2           -> let !v1  = evalE exp1+                                       env' = env `push` (lhs, v1)+                                   in  evalOpenExp exp2 env' aenv+    Evar (Var _ ix)             -> prj ix env+    Const _ c                   -> c+    Undef tp                    -> undefElt (TupRsingle tp)+    PrimConst c                 -> evalPrimConst c+    PrimApp f x                 -> evalPrim f (evalE x)+    Nil                         -> ()+    Pair e1 e2                  -> let !x1 = evalE e1+                                       !x2 = evalE e2+                                   in  (x1, x2)+    VecPack   vecR e            -> pack   vecR $! evalE e+    VecUnpack vecR e            -> unpack vecR $! evalE e+    IndexSlice slice slix sh    -> restrict slice (evalE slix)+                                                  (evalE sh)+      where+        restrict :: SliceIndex slix sl co sh -> slix -> sh -> sl+        restrict SliceNil              ()        ()         = ()+        restrict (SliceAll sliceIdx)   (slx, ()) (sl, sz)   =+          let sl' = restrict sliceIdx slx sl+          in  (sl', sz)+        restrict (SliceFixed sliceIdx) (slx, _i)  (sl, _sz) =+          restrict sliceIdx slx sl++    IndexFull slice slix sh     -> extend slice (evalE slix)+                                                (evalE sh)+      where+        extend :: SliceIndex slix sl co sh -> slix -> sl -> sh+        extend SliceNil              ()        ()       = ()+        extend (SliceAll sliceIdx)   (slx, ()) (sl, sz) =+          let sh' = extend sliceIdx slx sl+          in  (sh', sz)+        extend (SliceFixed sliceIdx) (slx, sz) sl       =+          let sh' = extend sliceIdx slx sl+          in  (sh', sz)++    ToIndex shr sh ix           -> toIndex shr (evalE sh) (evalE ix)+    FromIndex shr sh ix         -> fromIndex shr (evalE sh) (evalE ix)+    Case e rhs def              -> evalE (caseof (evalE e) rhs)+      where+        caseof :: TAG -> [(TAG, OpenExp env aenv t)] -> OpenExp env aenv t+        caseof tag = go+          where+            go ((t,c):cs)+              | tag == t  = c+              | otherwise = go cs+            go []+              | Just d <- def = d+              | otherwise     = internalError "unmatched case"++    Cond c t e+      | toBool (evalE c)        -> evalE t+      | otherwise               -> evalE e++    While cond body seed        -> go (evalE seed)+      where+        f       = evalF body+        p       = evalF cond+        go !x+          | toBool (p x) = go (f x)+          | otherwise    = x++    Index acc ix                -> let (TupRsingle repr, a) = evalA acc+                                   in (repr, a) ! evalE ix+    LinearIndex acc i           -> let (TupRsingle repr, a) = evalA acc+                                       ix   = fromIndex (arrayRshape repr) (shape a) (evalE i)+                                   in (repr, a) ! ix+    Shape acc                   -> shape $ snd $ evalA acc+    ShapeSize shr sh            -> size shr (evalE sh)+    Foreign _ _ f e             -> evalOpenFun f Empty Empty $ evalE e+    Coerce t1 t2 e              -> evalCoerceScalar t1 t2 (evalE e)+++-- Coercions+-- ---------++-- Coercion between two scalar types. We require that the size of the source and+-- destination values are equal (this is not checked at this point).+--+evalCoerceScalar :: ScalarType a -> ScalarType b -> a -> b+evalCoerceScalar SingleScalarType{}    SingleScalarType{} a = unsafeCoerce a+evalCoerceScalar VectorScalarType{}    VectorScalarType{} a = unsafeCoerce a  -- XXX: or just unpack/repack the (Vec ba#)+evalCoerceScalar (SingleScalarType ta) VectorScalarType{} a = vector ta a+  where+    vector :: SingleType a -> a -> Vec n b+    vector (NumSingleType t) = num t++    num :: NumType a -> a -> Vec n b+    num (IntegralNumType t) = integral t+    num (FloatingNumType t) = floating t++    integral :: IntegralType a -> a -> Vec n b+    integral TypeInt{}     = poke+    integral TypeInt8{}    = poke+    integral TypeInt16{}   = poke+    integral TypeInt32{}   = poke+    integral TypeInt64{}   = poke+    integral TypeWord{}    = poke+    integral TypeWord8{}   = poke+    integral TypeWord16{}  = poke+    integral TypeWord32{}  = poke+    integral TypeWord64{}  = poke++    floating :: FloatingType a -> a -> Vec n b+    floating TypeHalf{}    = poke+    floating TypeFloat{}   = poke+    floating TypeDouble{}  = poke++    {-# INLINE poke #-}+    poke :: forall a b n. Prim a => a -> Vec n b+    poke x = runST $ do+      mba <- newByteArray (sizeOf (undefined::a))+      writeByteArray mba 0 x+      ByteArray ba# <- unsafeFreezeByteArray mba+      return $ Vec ba#++evalCoerceScalar VectorScalarType{} (SingleScalarType tb) a = scalar tb a+  where+    scalar :: SingleType b -> Vec n a -> b+    scalar (NumSingleType t) = num t++    num :: NumType b -> Vec n a -> b+    num (IntegralNumType t) = integral t+    num (FloatingNumType t) = floating t++    integral :: IntegralType b -> Vec n a -> b+    integral TypeInt{}     = peek+    integral TypeInt8{}    = peek+    integral TypeInt16{}   = peek+    integral TypeInt32{}   = peek+    integral TypeInt64{}   = peek+    integral TypeWord{}    = peek+    integral TypeWord8{}   = peek+    integral TypeWord16{}  = peek+    integral TypeWord32{}  = peek+    integral TypeWord64{}  = peek++    floating :: FloatingType b -> Vec n a -> b+    floating TypeHalf{}    = peek+    floating TypeFloat{}   = peek+    floating TypeDouble{}  = peek++    {-# INLINE peek #-}+    peek :: Prim a => Vec n b -> a+    peek (Vec ba#) = indexByteArray (ByteArray ba#) 0+++-- Scalar primitives+-- -----------------++evalPrimConst :: PrimConst a -> a+evalPrimConst (PrimMinBound ty) = evalMinBound ty+evalPrimConst (PrimMaxBound ty) = evalMaxBound ty+evalPrimConst (PrimPi       ty) = evalPi ty++evalPrim :: PrimFun (a -> r) -> (a -> r)+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 (PrimIsInfinite         ty) = evalIsInfinite 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 (PrimFromIntegral ta tb)    = evalFromIntegral ta tb+evalPrim (PrimToFloating ta tb)      = evalToFloating ta tb+++-- Implementation of scalar primitives+-- -----------------------------------++toBool :: PrimBool -> Bool+toBool 0 = False+toBool _ = True++fromBool :: Bool -> PrimBool+fromBool False = 0+fromBool True  = 1++evalLAnd :: (PrimBool, PrimBool) -> PrimBool+evalLAnd (x, y) = fromBool (toBool x && toBool y)++evalLOr  :: (PrimBool, PrimBool) -> PrimBool+evalLOr (x, y) = fromBool (toBool x || toBool y)++evalLNot :: PrimBool -> PrimBool+evalLNot = fromBool . not . toBool++evalFromIntegral :: IntegralType a -> NumType b -> a -> b+evalFromIntegral ta (IntegralNumType tb)+  | IntegralDict <- integralDict ta+  , IntegralDict <- integralDict tb+  = fromIntegral++evalFromIntegral ta (FloatingNumType tb)+  | IntegralDict <- integralDict ta+  , 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+--++-- Constant methods of Bounded+--++evalMinBound :: BoundedType a -> a+evalMinBound (IntegralBoundedType ty)+  | IntegralDict <- integralDict ty+  = minBound++evalMaxBound :: BoundedType a -> a+evalMaxBound (IntegralBoundedType ty)+  | IntegralDict <- integralDict ty+  = maxBound++-- Constant method of floating+--++evalPi :: FloatingType a -> a+evalPi ty | FloatingDict <- floatingDict ty = pi++evalSin :: FloatingType a -> (a -> a)+evalSin ty | FloatingDict <- floatingDict ty = sin++evalCos :: FloatingType a -> (a -> a)+evalCos ty | FloatingDict <- floatingDict ty = cos++evalTan :: FloatingType a -> (a -> a)+evalTan ty | FloatingDict <- floatingDict ty = tan++evalAsin :: FloatingType a -> (a -> a)+evalAsin ty | FloatingDict <- floatingDict ty = asin++evalAcos :: FloatingType a -> (a -> a)+evalAcos ty | FloatingDict <- floatingDict ty = acos++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++evalAcosh :: FloatingType a -> (a -> a)+evalAcosh ty | FloatingDict <- floatingDict ty = acosh++evalAtanh :: FloatingType a -> (a -> a)+evalAtanh ty | FloatingDict <- floatingDict ty = atanh++evalExpFloating :: FloatingType a -> (a -> a)+evalExpFloating ty | FloatingDict <- floatingDict ty = exp++evalSqrt :: FloatingType a -> (a -> a)+evalSqrt ty | FloatingDict <- floatingDict ty = sqrt++evalLog :: FloatingType a -> (a -> a)+evalLog ty | FloatingDict <- floatingDict ty = log++evalFPow :: FloatingType a -> ((a, a) -> a)+evalFPow ty | FloatingDict <- floatingDict ty = uncurry (**)++evalLogBase :: FloatingType a -> ((a, a) -> a)+evalLogBase ty | FloatingDict <- floatingDict ty = uncurry logBase++evalTruncate :: FloatingType a -> IntegralType b -> (a -> b)+evalTruncate ta tb+  | FloatingDict <- floatingDict ta+  , IntegralDict <- integralDict tb+  = truncate++evalRound :: FloatingType a -> IntegralType b -> (a -> b)+evalRound ta tb+  | FloatingDict <- floatingDict ta+  , IntegralDict <- integralDict tb+  = round++evalFloor :: FloatingType a -> IntegralType b -> (a -> b)+evalFloor ta tb+  | FloatingDict <- floatingDict ta+  , IntegralDict <- integralDict tb+  = floor++evalCeiling :: FloatingType a -> IntegralType b -> (a -> b)+evalCeiling ta tb+  | FloatingDict <- floatingDict ta+  , IntegralDict <- integralDict tb+  = ceiling++evalAtan2 :: FloatingType a -> ((a, a) -> a)+evalAtan2 ty | FloatingDict <- floatingDict ty = uncurry atan2++evalIsNaN :: FloatingType a -> (a -> PrimBool)+evalIsNaN ty | FloatingDict <- floatingDict ty = fromBool . isNaN++evalIsInfinite :: FloatingType a -> (a -> PrimBool)+evalIsInfinite ty | FloatingDict <- floatingDict ty = fromBool . isInfinite+++-- Methods of Num+--++evalAdd :: NumType a -> ((a, a) -> a)+evalAdd (IntegralNumType ty) | IntegralDict <- integralDict ty = uncurry (+)+evalAdd (FloatingNumType ty) | FloatingDict <- floatingDict ty = uncurry (+)++evalSub :: NumType a -> ((a, a) -> a)+evalSub (IntegralNumType ty) | IntegralDict <- integralDict ty = uncurry (-)+evalSub (FloatingNumType ty) | FloatingDict <- floatingDict ty = uncurry (-)++evalMul :: NumType a -> ((a, a) -> a)+evalMul (IntegralNumType ty) | IntegralDict <- integralDict ty = uncurry (*)+evalMul (FloatingNumType ty) | FloatingDict <- floatingDict ty = uncurry (*)++evalNeg :: NumType a -> (a -> a)+evalNeg (IntegralNumType ty) | IntegralDict <- integralDict ty = negate+evalNeg (FloatingNumType ty) | FloatingDict <- floatingDict ty = negate++evalAbs :: NumType a -> (a -> a)+evalAbs (IntegralNumType ty) | IntegralDict <- integralDict ty = abs+evalAbs (FloatingNumType ty) | FloatingDict <- floatingDict ty = abs++evalSig :: NumType a -> (a -> a)+evalSig (IntegralNumType ty) | IntegralDict <- integralDict ty = signum+evalSig (FloatingNumType ty) | FloatingDict <- floatingDict ty = signum++evalQuot :: IntegralType a -> ((a, a) -> a)+evalQuot ty | IntegralDict <- integralDict ty = uncurry quot++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 (.&.)++evalBOr :: IntegralType a -> ((a, a) -> a)+evalBOr ty | IntegralDict <- integralDict ty = uncurry (.|.)++evalBXor :: IntegralType a -> ((a, a) -> a)+evalBXor ty | IntegralDict <- integralDict ty = uncurry xor++evalBNot :: IntegralType a -> (a -> a)+evalBNot ty | IntegralDict <- integralDict ty = complement++evalBShiftL :: IntegralType a -> ((a, Int) -> a)+evalBShiftL ty | IntegralDict <- integralDict ty = uncurry shiftL++evalBShiftR :: IntegralType a -> ((a, Int) -> a)+evalBShiftR ty | IntegralDict <- integralDict ty = uncurry shiftR++evalBRotateL :: IntegralType a -> ((a, Int) -> a)+evalBRotateL ty | IntegralDict <- integralDict ty = uncurry rotateL++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)+evalCountLeadingZeros ty | IntegralDict <- integralDict ty = countLeadingZeros++evalCountTrailingZeros :: IntegralType a -> (a -> Int)+evalCountTrailingZeros ty | IntegralDict <- integralDict ty = countTrailingZeros++evalFDiv :: FloatingType a -> ((a, a) -> a)+evalFDiv ty | FloatingDict <- floatingDict ty = uncurry (/)++evalRecip :: FloatingType a -> (a -> a)+evalRecip ty | FloatingDict <- floatingDict ty = recip+++evalLt :: SingleType a -> ((a, a) -> PrimBool)+evalLt (NumSingleType (IntegralNumType ty)) | IntegralDict <- integralDict ty = fromBool . uncurry (<)+evalLt (NumSingleType (FloatingNumType ty)) | FloatingDict <- floatingDict ty = fromBool . uncurry (<)++evalGt :: SingleType a -> ((a, a) -> PrimBool)+evalGt (NumSingleType (IntegralNumType ty)) | IntegralDict <- integralDict ty = fromBool . uncurry (>)+evalGt (NumSingleType (FloatingNumType ty)) | FloatingDict <- floatingDict ty = fromBool . uncurry (>)++evalLtEq :: SingleType a -> ((a, a) -> PrimBool)+evalLtEq (NumSingleType (IntegralNumType ty)) | IntegralDict <- integralDict ty = fromBool . uncurry (<=)+evalLtEq (NumSingleType (FloatingNumType ty)) | FloatingDict <- floatingDict ty = fromBool . uncurry (<=)++evalGtEq :: SingleType a -> ((a, a) -> PrimBool)+evalGtEq (NumSingleType (IntegralNumType ty)) | IntegralDict <- integralDict ty = fromBool . uncurry (>=)+evalGtEq (NumSingleType (FloatingNumType ty)) | FloatingDict <- floatingDict ty = fromBool . uncurry (>=)++evalEq :: SingleType a -> ((a, a) -> PrimBool)+evalEq (NumSingleType (IntegralNumType ty)) | IntegralDict <- integralDict ty = fromBool . uncurry (==)+evalEq (NumSingleType (FloatingNumType ty)) | FloatingDict <- floatingDict ty = fromBool . uncurry (==)++evalNEq :: SingleType a -> ((a, a) -> PrimBool)+evalNEq (NumSingleType (IntegralNumType ty)) | IntegralDict <- integralDict ty = fromBool . uncurry (/=)+evalNEq (NumSingleType (FloatingNumType ty)) | FloatingDict <- floatingDict ty = fromBool . uncurry (/=)++evalMax :: SingleType a -> ((a, a) -> a)+evalMax (NumSingleType (IntegralNumType ty)) | IntegralDict <- integralDict ty = uncurry max+evalMax (NumSingleType (FloatingNumType ty)) | FloatingDict <- floatingDict ty = uncurry max++evalMin :: SingleType a -> ((a, a) -> a)+evalMin (NumSingleType (IntegralNumType ty)) | IntegralDict <- integralDict ty = uncurry min+evalMin (NumSingleType (FloatingNumType ty)) | FloatingDict <- floatingDict 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++-- 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 = evalExp exp aenv++    evalF :: DelayedFun aenv f -> f+    evalF fun = evalFun 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 (evalExp extentD aenv)+                                      (evalFun indexD aenv)+                                      (evalFun linearIndexD aenv)  produce :: Arrays a => ExecP senv a -> Val' senv -> (Chunk a, Maybe (ExecP senv a)) produce p senv =
src/Data/Array/Accelerate/Language.hs view
@@ -1,17 +1,18 @@+{-# LANGUAGE AllowAmbiguousTypes #-} {-# LANGUAGE ConstraintKinds     #-} {-# LANGUAGE FlexibleContexts    #-}+{-# LANGUAGE GADTs               #-} {-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TypeApplications    #-} {-# 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+-- Copyright   : [2008..2020] The Accelerate Team -- License     : BSD3 ----- Maintainer  : Trevor L. McDonell <tmcdonell@cse.unsw.edu.au>+-- Maintainer  : Trevor L. McDonell <trevor.mcdonell@gmail.com> -- Stability   : experimental -- Portability : non-portable (GHC extensions) --@@ -25,12 +26,6 @@  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, @@ -56,7 +51,7 @@   -- foldSeq, foldSeqFlatten,    -- * Reductions-  fold, fold1, foldSeg, fold1Seg,+  fold, fold1, foldSeg', fold1Seg',    -- * Scan functions   scanl, scanl', scanl1, scanr, scanr', scanr1,@@ -102,16 +97,20 @@   -- * Conversions   ord, chr, boolToInt, bitcast, -  -- * Constants-  ignore- ) where --- friends-import Data.Array.Accelerate.Array.Sugar                            hiding ( (!), (!!), ignore, shape, reshape, size, toIndex, fromIndex, intersect, union )-import Data.Array.Accelerate.Smart+import Data.Array.Accelerate.AST                                    ( PrimFun(..) )+import Data.Array.Accelerate.Pattern+import Data.Array.Accelerate.Representation.Array                   ( ArrayR(..) )+import Data.Array.Accelerate.Representation.Shape                   ( ShapeR(..) )+import Data.Array.Accelerate.Representation.Type+import Data.Array.Accelerate.Smart                                  hiding ( arraysR )+import Data.Array.Accelerate.Sugar.Array                            ( Arrays(..), Array, Scalar, Segments, arrayR )+import Data.Array.Accelerate.Sugar.Elt+import Data.Array.Accelerate.Sugar.Foreign+import Data.Array.Accelerate.Sugar.Shape                            ( Shape(..), Slice(..), (:.) ) import Data.Array.Accelerate.Type-import qualified Data.Array.Accelerate.Array.Sugar                  as Sugar+import qualified Data.Array.Accelerate.Representation.Array         as R  import Data.Array.Accelerate.Classes.Eq import Data.Array.Accelerate.Classes.Fractional@@ -119,15 +118,16 @@ import Data.Array.Accelerate.Classes.Num import Data.Array.Accelerate.Classes.Ord --- standard libraries-import Prelude                                                      ( ($), (.) )+import Prelude                                                      ( ($), (.), Maybe(..), Char ) + -- $setup -- >>> :seti -XFlexibleContexts -- >>> :seti -XScopedTypeVariables -- >>> :seti -XTypeOperators -- >>> :seti -XViewPatterns -- >>> import Data.Array.Accelerate+-- >>> import Data.Array.Accelerate.Data.Maybe -- >>> import Data.Array.Accelerate.Interpreter -- >>> :{ --   let runExp :: Elt e => Exp e -> e@@ -162,14 +162,19 @@ -- >>> let mat' = use mat         :: Acc (Matrix Int) -- >>> let tup  = use (vec, mat)  :: Acc (Vector Int, Matrix Int) ---use :: Arrays arrays => arrays -> Acc arrays-use = Acc . Use+use :: forall arrays. Arrays arrays => arrays -> Acc arrays+use = Acc . use' (arraysR @arrays) . fromArr+  where+    use' :: R.ArraysR a -> a -> SmartAcc a+    use' TupRunit                   ()       = SmartAcc $ Anil+    use' (TupRsingle repr@ArrayR{}) a        = SmartAcc $ Use repr a+    use' (TupRpair r1 r2)           (a1, a2) = SmartAcc $ use' r1 a1 `Apair` use' r2 a2  -- | 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+unit :: forall e. Elt e => Exp e -> Acc (Scalar e)+unit (Exp e) = Acc $ SmartAcc $ Unit (eltR @e) e  -- | Replicate an array across one or more dimensions as specified by the -- /generalised/ array index provided as the first argument.@@ -253,18 +258,19 @@ --     0, 1, 2, 3, 4, 5, 6, 7, 8, 9] -- replicate-    :: (Slice slix, Elt e)+    :: forall slix e.+       (Slice slix, Elt e)     => Exp slix     -> Acc (Array (SliceShape slix) e)     -> Acc (Array (FullShape  slix) e)-replicate = Acc $$ Replicate+replicate = Acc $$ applyAcc (Replicate $ sliceIndex @slix)  -- | 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: ----- >>> run $ generate (index1 3) (\_ -> 1.2) :: Vector Float+-- >>> run $ generate (I1 3) (\_ -> 1.2) :: Vector Float -- Vector (Z :. 3) [1.2,1.2,1.2] -- -- Or equivalently:@@ -274,7 +280,7 @@ -- -- The following will create a vector with the elements @[1..10]@: ----- >>> run $ generate (index1 10) (\ix -> unindex1 ix + 1) :: Vector Int+-- >>> run $ generate (I1 10) (\(I1 i) -> i + 1) :: Vector Int -- Vector (Z :. 10) [1,2,3,4,5,6,7,8,9,10] -- -- [/NOTE:/]@@ -289,11 +295,12 @@ -- @.\/Data\/Array\/Accelerate\/Trafo\/Sharing.hs:447 (convertSharingExp): inconsistent valuation \@ shared \'Exp\' tree ...@. -- generate-    :: (Shape sh, Elt a)+    :: forall sh a.+       (Shape sh, Elt a)     => Exp sh     -> (Exp sh -> Exp a)     -> Acc (Array sh a)-generate = Acc $$ Generate+generate = Acc $$ applyAcc (Generate $ arrayR @sh @a)  -- Shape manipulation -- ------------------@@ -308,11 +315,12 @@ -- an index transformation in the fused code. -- reshape-    :: (Shape sh, Shape sh', Elt e)+    :: forall sh sh' e.+       (Shape sh, Shape sh', Elt e)     => Exp sh     -> Acc (Array sh' e)     -> Acc (Array sh e)-reshape = Acc $$ Reshape+reshape = Acc $$ applyAcc (Reshape $ shapeR @sh)  -- Extraction of sub-arrays -- ------------------------@@ -382,11 +390,12 @@ --     30, 31, 32, 33, 34, --     50, 51, 52, 53, 54] ---slice :: (Slice slix, Elt e)+slice :: forall slix e.+         (Slice slix, Elt e)       => Acc (Array (FullShape slix) e)       -> Exp slix       -> Acc (Array (SliceShape slix) e)-slice = Acc $$ Slice+slice = Acc $$ applyAcc (Slice $ sliceIndex @slix)  -- Map-like functions -- ------------------@@ -402,11 +411,12 @@ -- >>> run $ map (+1) (use xs) -- Vector (Z :. 10) [1,2,3,4,5,6,7,8,9,10] ---map :: (Shape sh, Elt a, Elt b)+map :: forall sh a b.+       (Shape sh, Elt a, Elt b)     => (Exp a -> Exp b)     -> Acc (Array sh a)     -> Acc (Array sh b)-map = Acc $$ Map+map = Acc $$ applyAcc (Map (eltR @a) (eltR @b))  -- | Apply the given binary function element-wise to the two arrays. The extent -- of the resulting array is the intersection of the extents of the two source@@ -434,12 +444,13 @@ --     16, 18, 20, 22, 24, --     31, 33, 35, 37, 39] ---zipWith :: (Shape sh, Elt a, Elt b, Elt c)+zipWith :: forall sh a b c.+           (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+zipWith = Acc $$$ applyAcc (ZipWith (eltR @a) (eltR @b) (eltR @c))  -- Reductions -- ----------@@ -478,24 +489,23 @@ --           => 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)+--         = map (\(T4 x _ _ _) -> 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+--             let T4 mssx misx mcsx tsx = x+--                 T4 mssy misy mcsy tsy = y --             in---             lift ( mssx `max` (mssy `max` (mcsx+misy))---                  , misx `max` (tsx+misy)---                  , mcsy `max` (mcsx+tsy)---                  , tsx+tsy---                  )+--             T4 (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)+--                  in T4 y y y x -- :} -- -- >>> let vec = fromList (Z:.10) [-2,1,-3,4,-1,2,1,-5,4,0] :: Vector Int@@ -505,12 +515,13 @@ -- 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)+fold :: forall sh a.+        (Shape sh, Elt a)      => (Exp a -> Exp a -> Exp a)      -> Exp a      -> Acc (Array (sh:.Int) a)      -> Acc (Array sh a)-fold = Acc $$$ Fold+fold f (Exp x) = Acc . applyAcc (Fold (eltR @a) (unExpBinaryFunction f) (Just x))  -- | Variant of 'fold' that requires the innermost dimension of the array to be -- non-empty and doesn't need an default value.@@ -522,58 +533,51 @@ -- The first argument needs to be an /associative/ function to enable an -- efficient parallel implementation, but does not need to be commutative. ---fold1 :: (Shape sh, Elt a)+fold1 :: forall sh a.+         (Shape sh, Elt a)       => (Exp a -> Exp a -> Exp a)       -> Acc (Array (sh:.Int) a)       -> Acc (Array sh a)-fold1 = Acc $$ Fold1+fold1 f = Acc . applyAcc (Fold (eltR @a) (unExpBinaryFunction f) Nothing) --- | 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).+-- | Segmented reduction along the innermost dimension of an array. The+-- segment descriptor specifies the starting index (offset) along the+-- innermost dimension to the beginning of each logical sub-array. ----- >>> let seg = fromList (Z:.4) [1,4,0,3] :: Segments Int--- >>> seg--- Vector (Z :. 4) [1,4,0,3]+-- The value in the output array at index i is the reduction of values+-- between the indices of the segment descriptor at index i and (i+1). ----- >>> let mat = fromList (Z:.5:.10) [0..] :: Matrix 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]+-- We have that: ----- >>> run $ 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 f z xs seg  ==  foldSeg' f z xs (scanl (+) 0 seg) ---foldSeg-    :: (Shape sh, Elt a, Elt i, IsIntegral i)+-- @since 1.3.0.0+--+foldSeg'+    :: forall sh a i.+       (Shape sh, Elt a, Elt i, IsIntegral i, i ~ EltR 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+foldSeg' f (Exp x) = Acc $$ applyAcc (FoldSeg (integralType @i) (eltR @a) (unExpBinaryFunction f) (Just x)) --- | 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.+-- | 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 offset to the beginning of each of the logical+-- sub-arrays. ---fold1Seg-    :: (Shape sh, Elt a, Elt i, IsIntegral i)+-- @since 1.3.0.0+--+fold1Seg'+    :: forall sh a i.+       (Shape sh, Elt a, Elt i, IsIntegral i, i ~ EltR i)     => (Exp a -> Exp a -> Exp a)     -> Acc (Array (sh:.Int) a)     -> Acc (Segments i)     -> Acc (Array (sh:.Int) a)-fold1Seg = Acc $$$ Fold1Seg+fold1Seg' f = Acc $$ applyAcc (FoldSeg (integralType @i) (eltR @a) (unExpBinaryFunction f) Nothing)  -- Scan functions -- --------------@@ -595,12 +599,13 @@ --     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)+scanl :: forall sh a.+         (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+scanl f (Exp x) (Acc a) = Acc $ SmartAcc $ Scan LeftToRight (eltR @a) (unExpBinaryFunction f) (Just x) a  -- | Variant of 'scanl', where the last element (final reduction result) along -- each dimension is returned separately. Denotationally we have:@@ -628,12 +633,13 @@ -- >>> sums -- Vector (Z :. 4) [45,145,245,345] ---scanl' :: (Shape sh, Elt a)+scanl' :: forall sh a.+          (Shape sh, Elt a)        => (Exp a -> Exp a -> Exp a)        -> Exp a        -> Acc (Array (sh:.Int) a)        -> Acc (Array (sh:.Int) a, Array sh a)-scanl' = Acc $$$ Scanl'+scanl' = Acc . mkPairToTuple $$$ applyAcc (Scan' LeftToRight $ eltR @a)  -- | Data.List style left-to-right scan along the innermost dimension without an -- initial value (aka inclusive scan). The innermost dimension of the array must@@ -647,37 +653,41 @@ --     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)+scanl1 :: forall sh a.+          (Shape sh, Elt a)        => (Exp a -> Exp a -> Exp a)        -> Acc (Array (sh:.Int) a)        -> Acc (Array (sh:.Int) a)-scanl1 = Acc $$ Scanl1+scanl1 f (Acc a) = Acc $ SmartAcc $ Scan LeftToRight (eltR @a) (unExpBinaryFunction f) Nothing a  -- | Right-to-left variant of 'scanl'. ---scanr :: (Shape sh, Elt a)+scanr :: forall sh a.+         (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+scanr f (Exp x) (Acc a) = Acc $ SmartAcc $ Scan RightToLeft (eltR @a) (unExpBinaryFunction f) (Just x) a  -- | Right-to-left variant of 'scanl''. ---scanr' :: (Shape sh, Elt a)+scanr' :: forall sh a.+          (Shape sh, Elt a)        => (Exp a -> Exp a -> Exp a)        -> Exp a        -> Acc (Array (sh:.Int) a)        -> Acc (Array (sh:.Int) a, Array sh a)-scanr' = Acc $$$ Scanr'+scanr' = Acc . mkPairToTuple $$$ applyAcc (Scan' RightToLeft $ eltR @a)  -- | Right-to-left variant of 'scanl1'. ---scanr1 :: (Shape sh, Elt a)+scanr1 :: forall sh a.+          (Shape sh, Elt a)        => (Exp a -> Exp a -> Exp a)        -> Acc (Array (sh:.Int) a)        -> Acc (Array (sh:.Int) a)-scanr1 = Acc $$ Scanr1+scanr1 f (Acc a) = Acc $ SmartAcc $ Scan RightToLeft (eltR @a) (unExpBinaryFunction f) Nothing a  -- Permutations -- ------------@@ -689,8 +699,8 @@ -- 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 index 'ignore' by the permutation function are+-- The combination function must be /associative/ and /commutative/.+-- Elements for which the permutation function returns 'Nothing' are -- dropped. -- -- The combination function is given the new value being permuted as its first@@ -705,7 +715,7 @@ --         let zeros = fill (constant (Z:.10)) 0 --             ones  = fill (shape xs)         1 --         in---         permute (+) zeros (\ix -> index1 (xs!ix)) ones+--         permute (+) zeros (\ix -> Just_ (I1 (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] :: Vector Int@@ -719,10 +729,10 @@ -- >>> :{ --   let identity :: Num a => Exp Int -> Acc (Matrix a) --       identity n =---         let zeros = fill (index2 n n) 0---             ones  = fill (index1 n)   1+--         let zeros = fill (I2 n n) 0+--             ones  = fill (I1 n)   1 --         in---         permute const zeros (\(unindex1 -> i) -> index2 i i) ones+--         permute const zeros (\(I1 i) -> Just_ (I2 i i)) ones -- :} -- -- >>> run $ identity 5 :: Matrix Int@@ -747,7 +757,7 @@ --   3. The array of source values can fuse into the permutation operation. -- --   4. If the array of default values is only used once, it will be updated---      in-place.+--      in-place. This behaviour can be disabled this with @-fno-inplace@. -- -- Regarding the defaults array: --@@ -756,14 +766,32 @@ -- array created by 'Data.Array.Accelerate.Prelude.fill'ing with the value -- 'Data.Array.Accelerate.Unsafe.undef' will give you a new uninitialised array. --+-- Regarding the combination function:+--+-- The function 'const' can be used to replace elements of the defaults+-- array with the new values. If the permutation function maps multiple+-- values to the same location in the results array (the function is not+-- injective) then this operation is non-deterministic.+--+-- Since Accelerate uses an unzipped struct-of-array representation, where+-- the individual components of product types (for example, pairs) are+-- stored in separate arrays, storing values of product type requires+-- multiple store instructions.+--+-- Accelerate prior to version 1.3.0.0 performs this operation atomically,+-- to ensure that the stored values are always consistent (each component+-- of the product type is written by the same thread). Later versions relax+-- this restriction, but this behaviour can be disabled with+-- @-fno-fast-permute-const@.+-- permute-    :: (Shape sh, Shape sh', Elt a)+    :: forall sh sh' a. (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+    -> (Exp sh -> Exp (Maybe sh'))      -- ^ index permutation function     -> Acc (Array sh  a)                -- ^ array of source values to be permuted     -> Acc (Array sh' a)-permute = Acc $$$$ Permute+permute = Acc $$$$ applyAcc (Permute $ arrayR @sh @a)  -- | Generalised backward permutation operation (array gather). --@@ -809,13 +837,12 @@ --     9, 19, 29, 39, 49] -- backpermute-    :: (Shape sh, Shape sh', Elt a)+    :: forall sh sh' a. (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-+backpermute = Acc $$$ applyAcc (Backpermute $ shapeR @sh')  -- Stencil operations -- ------------------@@ -898,27 +925,67 @@ -- > blur = stencil (convolve5x1 gaussian) clamp -- >      . stencil (convolve1x5 gaussian) clamp --+-- [/Note:/]+--+-- Since accelerate-1.3.0.0, we allow the source array to fuse into the stencil+-- operation. However, since a stencil computation (typically) requires multiple+-- values from the source array, this means that the work of the fused operation+-- will be duplicated for each element in the stencil pattern.+--+-- For example, suppose we write:+--+-- > blur . map f+--+-- The operation `f` will be fused into each element of the first Gaussian blur+-- kernel, resulting in a stencil equivalent to:+--+-- > f_and_convolve1x5 :: Num a => (Exp a -> Exp b) -> [Exp b] -> Stencil1x5 a -> Exp b+-- > f_and_convolve1x5 f kernel ((_,a,_), (_,b,_), (_,c,_), (_,d,_), (_,e,_))+-- >   = Prelude.sum $ Prelude.zipWith (*) kernel [f a, f b, f c, f d, f e]+--+-- This duplication is often beneficial, however you may choose to instead force+-- the array to be evaluated first, preventing fusion, using the+-- `Data.Array.Accelerate.Prelude.compute` operation. Benchmarking should reveal+-- which approach is best for your application.+-- stencil-    :: (Stencil sh a stencil, Elt b)+    :: forall sh stencil a b.+       (Stencil sh a stencil, Elt b)     => (stencil -> Exp b)                     -- ^ stencil function     -> Boundary (Array sh a)                  -- ^ boundary condition     -> Acc (Array sh a)                       -- ^ source array     -> Acc (Array sh b)                       -- ^ destination array-stencil f (Boundary b) a = Acc $ Stencil f b a+stencil f (Boundary b) (Acc a)+  = Acc $ SmartAcc $ Stencil+      (stencilR @sh @a @stencil)+      (eltR @b)+      (unExp . f . stencilPrj @sh @a @stencil)+      b+      a  -- | 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)+    :: forall sh stencil1 stencil2 a b c.+       (Stencil sh a stencil1, Stencil sh b stencil2, Elt c)     => (stencil1 -> stencil2 -> Exp c)        -- ^ binary stencil function     -> Boundary (Array sh a)                  -- ^ boundary condition #1     -> Acc (Array sh a)                       -- ^ source array #1     -> Boundary (Array sh b)                  -- ^ boundary condition #2     -> Acc (Array sh b)                       -- ^ source array #2     -> Acc (Array sh c)                       -- ^ destination array-stencil2 f (Boundary b1) a1 (Boundary b2) a2 = Acc $ Stencil2 f b1 a1 b2 a2+stencil2 f (Boundary b1) (Acc a1) (Boundary b2) (Acc a2)+  = Acc $ SmartAcc $ Stencil2+      (stencilR @sh @a @stencil1)+      (stencilR @sh @b @stencil2)+      (eltR @c)+      (\x y -> unExp $ f (stencilPrj @sh @a @stencil1 x) (stencilPrj @sh @b @stencil2 y))+      b1+      a1+      b2+      a2  -- | Boundary condition where elements of the stencil which would be -- out-of-bounds are instead clamped to the edges of the array.@@ -992,10 +1059,13 @@ -- >     Z :. height :. width = unlift (shape xs) -- function-    :: (Shape sh, Elt e)+    :: forall sh e. (Shape sh, Elt e)     => (Exp sh -> Exp e)     -> Boundary (Array sh e)-function = Boundary . Function+function f = Boundary $ Function (f')+  where+    f' :: SmartExp (EltR sh) -> SmartExp (EltR e)+    f' = unExp . f . Exp   {--@@ -1121,12 +1191,12 @@ -- 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)+    :: forall as bs asm. (Arrays as, Arrays bs, Foreign asm)+    => asm (ArraysR as -> ArraysR bs)     -> (Acc as -> Acc bs)     -> Acc as     -> Acc bs-foreignAcc = Acc $$$ Aforeign+foreignAcc asm f (Acc as) = Acc $ SmartAcc $ Aforeign (arraysR @bs) asm (unAccFunction f) as  -- | Call a foreign scalar expression. --@@ -1139,12 +1209,12 @@ -- purely in Accelerate. -- foreignExp-    :: (Elt x, Elt y, Foreign asm)-    => asm (x -> y)+    :: forall x y asm. (Elt x, Elt y, Foreign asm)+    => asm (EltR x -> EltR y)     -> (Exp x -> Exp y)     -> Exp x     -> Exp y-foreignExp = Exp $$$ Foreign+foreignExp asm f (Exp x) = mkExp $ Foreign (eltR @y) asm (unExpFunction f) x   -- Composition of array computations@@ -1163,8 +1233,8 @@ -- function. -- infixl 1 >->-(>->) :: (Arrays a, Arrays b, Arrays c) => (Acc a -> Acc b) -> (Acc b -> Acc c) -> (Acc a -> Acc c)-(>->) = Acc $$$ Pipe+(>->) :: forall a b c. (Arrays a, Arrays b, Arrays c) => (Acc a -> Acc b) -> (Acc b -> Acc c) -> (Acc a -> Acc c)+(>->) = Acc $$$ applyAcc $ Pipe (arraysR @a) (arraysR @b) (arraysR @c)   -- Flow control constructs@@ -1180,65 +1250,66 @@       -> Acc a                  -- ^ then-array       -> Acc a                  -- ^ else-array       -> Acc a-acond = Acc $$$ Acond+acond (Exp p) = Acc $$ applyAcc $ Acond (mkCoerce' p)  -- | 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+awhile :: forall a. 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+awhile f = Acc $$ applyAcc $ Awhile (arraysR @a) (unAccFunction g)+  where+    -- FIXME: This should be a no-op!+    g :: Acc a -> Acc (Scalar PrimBool)+    g = map mkCoerce . f   -- Shapes and indices -- ------------------ --- | Get the innermost dimension of a shape.------ The innermost dimension (right-most component of the shape) is the index of--- the array which varies most rapidly, and corresponds to elements of the array--- which are adjacent in memory.------ Another way to think of this is, for example when writing nested loops over--- an array in C, this index corresponds to the index iterated over by the--- innermost nested loop.----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+    :: forall sh. Shape sh     => Exp sh                     -- ^ extent of the array     -> Exp sh                     -- ^ index to remap     -> Exp Int-toIndex = Exp $$ ToIndex+toIndex (Exp sh) (Exp ix) = mkExp $ ToIndex (shapeR @sh) sh ix  -- | Inverse of 'toIndex' ---fromIndex :: Shape sh => Exp sh -> Exp Int -> Exp sh-fromIndex = Exp $$ FromIndex+fromIndex :: forall sh. Shape sh => Exp sh -> Exp Int -> Exp sh+fromIndex (Exp sh) (Exp e) = mkExp $ FromIndex (shapeR @sh) sh e  -- | Intersection of two shapes ---intersect :: Shape sh => Exp sh -> Exp sh -> Exp sh-intersect = Exp $$ Intersect+intersect :: forall sh. Shape sh => Exp sh -> Exp sh -> Exp sh+intersect (Exp shx) (Exp shy) = Exp $ intersect' (shapeR @sh) shx shy+  where+    intersect' :: ShapeR t -> SmartExp t -> SmartExp t -> SmartExp t+    intersect' ShapeRz _ _ = SmartExp Nil+    intersect' (ShapeRsnoc shR) (unPair -> (xs, x)) (unPair -> (ys, y))+      = SmartExp+      $ intersect' shR xs ys `Pair`+        SmartExp (PrimApp (PrimMin singleType) $ SmartExp $ Pair x y) + -- | Union of two shapes ---union :: Shape sh => Exp sh -> Exp sh -> Exp sh-union = Exp $$ Union+union :: forall sh. Shape sh => Exp sh -> Exp sh -> Exp sh+union (Exp shx) (Exp shy) = Exp $ union' (shapeR @sh) shx shy+  where+    union' :: ShapeR t -> SmartExp t -> SmartExp t -> SmartExp t+    union' ShapeRz _ _ = SmartExp Nil+    union' (ShapeRsnoc shR) (unPair -> (xs, x)) (unPair -> (ys, y))+      = SmartExp+      $ union' shR xs ys `Pair`+        SmartExp (PrimApp (PrimMax singleType) $ SmartExp $ Pair x y)   -- Flow-control@@ -1254,17 +1325,20 @@      -> Exp t                   -- ^ then-expression      -> Exp t                   -- ^ else-expression      -> Exp t-cond = Exp $$$ Cond+cond (Exp c) (Exp x) (Exp y) = mkExp $ Cond (mkCoerce' c) x y  -- | While construct. Continue to apply the given function, starting with the -- initial value, until the test function evaluates to 'False'. ---while :: Elt e+while :: forall e. 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+while c f (Exp e) =+  mkExp $ While @(EltR e) (eltR @e)+            (mkCoerce' . unExp . c . Exp)+            (unExp . f . Exp) e   -- Array operations with a scalar result@@ -1286,8 +1360,8 @@ -- 12 -- infixl 9 !-(!) :: (Shape sh, Elt e) => Acc (Array sh e) -> Exp sh -> Exp e-(!) = Exp $$ Index+(!) :: forall sh e. (Shape sh, Elt e) => Acc (Array sh e) -> Exp sh -> Exp e+Acc a ! Exp ix = mkExp $ Index (eltR @e) a ix  -- | Extract the value from an array at the specified linear index. -- Multidimensional arrays in Accelerate are stored in row-major order with@@ -1306,13 +1380,13 @@ -- 12 -- infixl 9 !!-(!!) :: (Shape sh, Elt e) => Acc (Array sh e) -> Exp Int -> Exp e-(!!) = Exp $$ LinearIndex+(!!) :: forall sh e. (Shape sh, Elt e) => Acc (Array sh e) -> Exp Int -> Exp e+Acc a !! Exp ix = mkExp $ LinearIndex (eltR @e) a ix  -- | Extract the shape (extent) of an array. ---shape :: (Shape sh, Elt e) => Acc (Array sh e) -> Exp sh-shape = Exp . Shape+shape :: forall sh e. (Shape sh, Elt e) => Acc (Array sh e) -> Exp sh+shape = mkExp . Shape (shapeR @sh) . unAcc  -- | The number of elements in the array --@@ -1321,8 +1395,8 @@  -- | 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+shapeSize :: forall sh. Shape sh => Exp sh -> Exp Int+shapeSize (Exp sh) = mkExp $ ShapeSize (shapeR @sh) sh   -- Numeric functions@@ -1359,10 +1433,9 @@   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))+      let T2 r _ = while (\(T2 _ b) -> b /= 0)+                         (\(T2 a b) -> T2 b (a `rem` b))+                         (T2 u v)       in r  @@ -1382,21 +1455,19 @@   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))+      let T2 x' y' = while (\(T2 _ v) -> even v)+                           (\(T2 u v) -> T2 (u * u) (v `quot` 2))+                           (T2 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))+      let T3 x' _ z' = while (\(T3 _ v _) -> v /= 1)+                             (\(T3 u v w) ->+                               cond (even v) (T3 (u*u) (v     `quot` 2) w)+                                             (T3 (u*u) ((v-1) `quot` 2) (w*u)))+                             (T3 x y z)       in       x' * z' @@ -1416,34 +1487,25 @@ -- |Convert a character to an 'Int'. -- ord :: Exp Char -> Exp Int-ord = mkOrd+ord = mkFromIntegral  -- |Convert an 'Int' into a character. -- chr :: Exp Int -> Exp Char-chr = mkChr+chr = mkFromIntegral  -- |Convert a Boolean value to an 'Int', where 'False' turns into '0' and 'True' -- into '1'. -- boolToInt :: Exp Bool -> Exp Int-boolToInt = mkBoolToInt+boolToInt = mkFromIntegral . mkCoerce @_ @Word8  -- |Reinterpret a value as another type. The two representations must have the -- same bit size. -- bitcast-    :: (Elt a, Elt b, IsScalar (EltRepr a), IsScalar (EltRepr b), BitSizeEq (EltRepr a) (EltRepr b))+    :: (Elt a, Elt b, IsScalar (EltR a), IsScalar (EltR b), BitSizeEq (EltR a) (EltR b))     => Exp a     -> Exp b bitcast = mkBitcast----- Constants--- ------------- | Magic index identifying elements that are ignored in a forward permutation.----ignore :: Shape sh => Exp sh-ignore = constant Sugar.ignore 
src/Data/Array/Accelerate/Lifetime.hs view
@@ -1,14 +1,13 @@-{-# 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+-- Copyright   : [2015..2020] The Accelerate Team -- License     : BSD3 ----- Maintainer  : Robert Clifton-Everest <robertce@cse.unsw.edu.au>+-- Maintainer  : Trevor L. McDonell <trevor.mcdonell@gmail.com> -- Stability   : experimental -- Portability : non-portable (GHC extensions) --@@ -121,11 +120,7 @@ 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+    go (IO f) =  -- GHC-8.x       IO $ \s -> case mkWeak# r# v f s of                    (# s', w# #) -> (# s', Weak w# #) 
src/Data/Array/Accelerate/Lift.hs view
@@ -1,22 +1,23 @@ {-# LANGUAGE CPP                   #-}+{-# LANGUAGE ConstraintKinds       #-} {-# LANGUAGE FlexibleContexts      #-} {-# LANGUAGE FlexibleInstances     #-} {-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE RankNTypes            #-}+{-# LANGUAGE ScopedTypeVariables   #-}+{-# LANGUAGE TemplateHaskell       #-}+{-# LANGUAGE TypeApplications      #-} {-# LANGUAGE TypeFamilies          #-} {-# LANGUAGE TypeOperators         #-}-#if __GLASGOW_HASKELL__ <= 708-{-# LANGUAGE OverlappingInstances  #-}-{-# OPTIONS_GHC -fno-warn-unrecognised-pragmas #-}-#endif #if __GLASGOW_HASKELL__ >= 806 {-# LANGUAGE UndecidableInstances  #-} #endif -- | -- Module      : Data.Array.Accelerate.Lift--- Copyright   : [2016..2017] Manuel M T Chakravarty, Gabriele Keller, Trevor L. McDonell+-- Copyright   : [2016..2020] The Accelerate Team -- License     : BSD3 ----- Maintainer  : Trevor L. McDonell <tmcdonell@cse.unsw.edu.au>+-- Maintainer  : Trevor L. McDonell <trevor.mcdonell@gmail.com> -- Stability   : experimental -- Portability : non-portable (GHC extensions) --@@ -33,12 +34,19 @@  ) where -import Data.Array.Accelerate.Array.Sugar+import Data.Array.Accelerate.AST.Idx+import Data.Array.Accelerate.Pattern import Data.Array.Accelerate.Smart+import Data.Array.Accelerate.Sugar.Array+import Data.Array.Accelerate.Sugar.Elt+import Data.Array.Accelerate.Sugar.Shape import Data.Array.Accelerate.Type +import Language.Haskell.TH                                          hiding ( Exp, tupP, tupE )+import Language.Haskell.TH.Extra --- |Lift a unary function into 'Exp'.++-- | Lift a unary function into 'Exp'. -- lift1 :: (Unlift Exp a, Lift Exp b)       => (a -> b)@@ -46,7 +54,7 @@       -> Exp (Plain b) lift1 f = lift . f . unlift --- |Lift a binary function into 'Exp'.+-- | Lift a binary function into 'Exp'. -- lift2 :: (Unlift Exp a, Unlift Exp b, Lift Exp c)       => (a -> b -> c)@@ -55,7 +63,7 @@       -> Exp (Plain c) lift2 f x y = lift $ f (unlift x) (unlift y) --- |Lift a ternary function into 'Exp'.+-- | Lift a ternary function into 'Exp'. -- lift3 :: (Unlift Exp a, Unlift Exp b, Unlift Exp c, Lift Exp d)       => (a -> b -> c -> d)@@ -65,24 +73,24 @@       -> 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.+-- | 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.+-- | 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.+-- | 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@.@@ -92,6 +100,7 @@   --   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@@ -110,7 +119,8 @@   unlift :: c (Plain e) -> e  --- identity instances+-- Identity instances+-- ------------------  instance Lift Exp (Exp e) where   type Plain (Exp e) = e@@ -134,617 +144,216 @@ --   unlift = id  --- instances for indices--instance Lift Exp () where-  type Plain () = ()-  lift _ = Exp $ Tuple NilTup--instance Unlift Exp () where-  unlift _ = ()+-- Instances for indices+-- ---------------------  instance Lift Exp Z where   type Plain Z = Z-  lift _ = Exp $ IndexNil+  lift _ = Z_  instance Unlift Exp Z where   unlift _ = Z -instance (Slice (Plain ix), Lift Exp ix) => Lift Exp (ix :. Int) where+instance (Elt (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)+  lift (ix :. i) = lift ix ::. lift i -instance (Slice (Plain ix), Lift Exp ix) => Lift Exp (ix :. All) where+instance (Elt (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)+  lift (ix :. i) = lift ix ::. constant i -instance (Elt e, Slice (Plain ix), Lift Exp ix) => Lift Exp (ix :. Exp e) where+instance (Elt e, Elt (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+  lift (ix :. i) = 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, Elt (Plain ix), Unlift Exp ix) => Unlift Exp (ix :. Exp e) where+  unlift (ix ::. i) = unlift ix :. i -instance {-# OVERLAPPABLE #-} (Elt e, Slice ix) => Unlift Exp (Exp ix :. Exp e) where-  unlift e = (Exp $ IndexTail e) :. Exp (IndexHead e)+instance {-# OVERLAPPABLE #-} (Elt e, Elt ix) => Unlift Exp (Exp ix :. Exp e) where+  unlift (ix ::. i) = ix :. i -instance Shape sh => Lift Exp (Any sh) where- type Plain (Any sh) = Any sh- lift Any = Exp $ IndexAny+instance (Shape sh, Elt (Any sh)) => Lift Exp (Any sh) where+  type Plain (Any sh) = Any sh+  lift Any = constant Any --- instances for numeric types+-- Instances for numeric types+-- --------------------------- +{-# INLINE expConst #-}+expConst :: forall e. Elt e => IsScalar (EltR e) => e -> Exp e+expConst = Exp . SmartExp . Const (scalarType @(EltR e)) . fromElt+ instance Lift Exp Int where   type Plain Int = Int-  lift = Exp . Const+  lift = expConst  instance Lift Exp Int8 where   type Plain Int8 = Int8-  lift = Exp . Const+  lift = expConst  instance Lift Exp Int16 where   type Plain Int16 = Int16-  lift = Exp . Const+  lift = expConst  instance Lift Exp Int32 where   type Plain Int32 = Int32-  lift = Exp . Const+  lift = expConst  instance Lift Exp Int64 where   type Plain Int64 = Int64-  lift = Exp . Const+  lift = expConst  instance Lift Exp Word where   type Plain Word = Word-  lift = Exp . Const+  lift = expConst  instance Lift Exp Word8 where   type Plain Word8 = Word8-  lift = Exp . Const+  lift = expConst  instance Lift Exp Word16 where   type Plain Word16 = Word16-  lift = Exp . Const+  lift = expConst  instance Lift Exp Word32 where   type Plain Word32 = Word32-  lift = Exp . Const+  lift = expConst  instance Lift Exp Word64 where   type Plain Word64 = Word64-  lift = Exp . Const+  lift = expConst  instance Lift Exp CShort where   type Plain CShort = CShort-  lift = Exp . Const+  lift = expConst  instance Lift Exp CUShort where   type Plain CUShort = CUShort-  lift = Exp . Const+  lift = expConst  instance Lift Exp CInt where   type Plain CInt = CInt-  lift = Exp . Const+  lift = expConst  instance Lift Exp CUInt where   type Plain CUInt = CUInt-  lift = Exp . Const+  lift = expConst  instance Lift Exp CLong where   type Plain CLong = CLong-  lift = Exp . Const+  lift = expConst  instance Lift Exp CULong where   type Plain CULong = CULong-  lift = Exp . Const+  lift = expConst  instance Lift Exp CLLong where   type Plain CLLong = CLLong-  lift = Exp . Const+  lift = expConst  instance Lift Exp CULLong where   type Plain CULLong = CULLong-  lift = Exp . Const+  lift = expConst +instance Lift Exp Half where+  type Plain Half = Half+  lift = expConst+ instance Lift Exp Float where   type Plain Float = Float-  lift = Exp . Const+  lift = expConst  instance Lift Exp Double where   type Plain Double = Double-  lift = Exp . Const+  lift = expConst  instance Lift Exp CFloat where   type Plain CFloat = CFloat-  lift = Exp . Const+  lift = expConst  instance Lift Exp CDouble where   type Plain CDouble = CDouble-  lift = Exp . Const+  lift = expConst  instance Lift Exp Bool where   type Plain Bool = Bool-  lift = Exp . Const+  lift True  = Exp . SmartExp $ SmartExp (Const scalarType 1) `Pair` SmartExp Nil+  lift False = Exp . SmartExp $ SmartExp (Const scalarType 0) `Pair` SmartExp Nil  instance Lift Exp Char where   type Plain Char = Char-  lift = Exp . Const+  lift = expConst  instance Lift Exp CChar where   type Plain CChar = CChar-  lift = Exp . Const+  lift = expConst  instance Lift Exp CSChar where   type Plain CSChar = CSChar-  lift = Exp . Const+  lift = expConst  instance Lift Exp CUChar where   type Plain CUChar = CUChar-  lift = Exp . Const+  lift = expConst  -- 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+-- -------------------- +instance Lift Exp () where+  type Plain () = ()+  lift _ = Exp (SmartExp Nil) +instance Unlift Exp () where+  unlift _ = () --- Instances for Arrays class+instance Lift Acc () where+  type Plain () = ()+  lift _ = Acc (SmartAcc Anil) ---instance Lift Acc () where---  type Plain () = ()---  lift _ = Acc (Atuple NilAtup)+instance Unlift Acc () where+  unlift _ = ()  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)+  lift (Array arr) = Acc $ SmartAcc $ Use (arrayR @sh @e) arr -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)+-- Lift and Unlift instances for tuples+--+runQ $ do+    let+        mkInstances :: Name -> TypeQ -> ExpQ -> ExpQ -> ExpQ -> ExpQ -> Int -> Q [Dec]+        mkInstances con cst smart prj nil pair n = do+          let+              xs      = [ mkName ('x' : show i) | i <- [0 .. n-1] ]+              ts      = map varT xs+              res1    = tupT ts+              res2    = tupT (map (conT con `appT`) ts)+              plain   = tupT (map (\t -> [t| Plain $t |]) ts)+              ctx1    = tupT (map (\t -> [t| Lift $(conT con) $t |]) ts)+              ctx2    = tupT (map (\t -> [t| $cst (Plain $t) |]) ts)+              ctx3    = tupT (map (appT cst) ts)+              --+              get x 0 = [| $(conE con) ($smart ($prj PairIdxRight $x)) |]+              get x i = get [| $smart ($prj PairIdxLeft $x) |] (i-1)+          --+          _x <- newName "_x"+          [d| instance ($ctx1, $ctx2) => Lift $(conT con) $res1 where+                type Plain $res1 = $plain+                lift $(tupP (map varP xs)) =+                  $(conE con)+                  $(foldl (\vs v -> do _v <- newName "_v"+                                       [| let $(conP con [varP _v]) = lift $(varE v)+                                           in $smart ($pair $vs $(varE _v)) |]) [| $smart $nil |] xs) -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 $ctx3 => Unlift $(conT con) $res2 where+                unlift $(conP con [varP _x]) =+                  $(tupE (map (get (varE _x)) [(n-1), (n-2) .. 0]))+            |] -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)---}+        mkAccInstances = mkInstances (mkName "Acc") [t| Arrays |] [| SmartAcc |] [| Aprj |] [| Anil |] [| Apair |]+        mkExpInstances = mkInstances (mkName "Exp") [t| Elt    |] [| SmartExp |] [| Prj  |] [| Nil  |] [| Pair  |]+    --+    as <- mapM mkAccInstances [2..16]+    es <- mapM mkExpInstances [2..16]+    return $ concat (as ++ es) 
+ src/Data/Array/Accelerate/Orphans.hs view
@@ -0,0 +1,49 @@+{-# LANGUAGE DeriveGeneric              #-}+{-# LANGUAGE GeneralizedNewtypeDeriving #-}+{-# LANGUAGE StandaloneDeriving         #-}+{-# LANGUAGE TypeInType                 #-}+{-# LANGUAGE UnboxedTuples              #-}+{-# OPTIONS_GHC -fno-warn-orphans #-}+-- |+-- Module      : Data.Array.Accelerate.Orphans+-- Copyright   : [2008..2020] The Accelerate Team+-- License     : BSD3+--+-- Maintainer  : Trevor L. McDonell <trevor.mcdonell@gmail.com>+-- Stability   : experimental+-- Portability : non-portable (GHC extensions)+--++module Data.Array.Accelerate.Orphans ()+  where++import Data.Orphans ()    -- orphan instances for 8-tuples and beyond+import Data.Primitive.Types+import Data.Ratio+import Foreign.C.Types+import GHC.Generics+import GHC.Real+import Numeric.Half+++-- base+--+deriving instance (Show a, Show b, Show c, Show d, Show e, Show f, Show g, Show h, Show i, Show j, Show k, Show l, Show m, Show n, Show o, Show p)+  => Show (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p)++deriving instance Generic (a, b, c, d, e, f, g, h)+deriving instance Generic (a, b, c, d, e, f, g, h, i)+deriving instance Generic (a, b, c, d, e, f, g, h, i, j)+deriving instance Generic (a, b, c, d, e, f, g, h, i, j, k)+deriving instance Generic (a, b, c, d, e, f, g, h, i, j, k, l)+deriving instance Generic (a, b, c, d, e, f, g, h, i, j, k, l, m)+deriving instance Generic (a, b, c, d, e, f, g, h, i, j, k, l, m, n)+deriving instance Generic (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o)+deriving instance Generic (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p)++deriving instance Generic (Ratio a)++-- primitive+--+deriving instance Prim Half+
+ src/Data/Array/Accelerate/Pattern.hs view
@@ -0,0 +1,286 @@+{-# LANGUAGE ConstraintKinds       #-}+{-# LANGUAGE DataKinds             #-}+{-# LANGUAGE FlexibleContexts      #-}+{-# LANGUAGE FlexibleInstances     #-}+{-# LANGUAGE LambdaCase            #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE ParallelListComp      #-}+{-# LANGUAGE PatternSynonyms       #-}+{-# LANGUAGE ScopedTypeVariables   #-}+{-# LANGUAGE TemplateHaskell       #-}+{-# LANGUAGE TypeApplications      #-}+{-# LANGUAGE TypeFamilies          #-}+{-# LANGUAGE TypeOperators         #-}+{-# LANGUAGE UndecidableInstances  #-}+{-# LANGUAGE ViewPatterns          #-}+-- |+-- Module      : Data.Array.Accelerate.Pattern+-- Copyright   : [2018..2020] The Accelerate Team+-- License     : BSD3+--+-- Maintainer  : Trevor L. McDonell <trevor.mcdonell@gmail.com>+-- Stability   : experimental+-- Portability : non-portable (GHC extensions)+--++module Data.Array.Accelerate.Pattern (++  pattern Pattern,+  pattern T2,  pattern T3,  pattern T4,  pattern T5,  pattern T6,+  pattern T7,  pattern T8,  pattern T9,  pattern T10, pattern T11,+  pattern T12, pattern T13, pattern T14, pattern T15, pattern T16,++  pattern Z_, pattern Ix, pattern (::.),+  pattern I0, pattern I1, pattern I2, pattern I3, pattern I4,+  pattern I5, pattern I6, pattern I7, pattern I8, pattern I9,++  pattern V2, pattern V3, pattern V4, pattern V8, pattern V16,++) where++import Data.Array.Accelerate.AST.Idx+import Data.Array.Accelerate.Representation.Tag+import Data.Array.Accelerate.Representation.Vec+import Data.Array.Accelerate.Smart+import Data.Array.Accelerate.Sugar.Array+import Data.Array.Accelerate.Sugar.Elt+import Data.Array.Accelerate.Sugar.Shape+import Data.Array.Accelerate.Sugar.Vec+import Data.Array.Accelerate.Type+import Data.Primitive.Vec++import Language.Haskell.TH                                          hiding ( Exp, Match, tupP, tupE )+import Language.Haskell.TH.Extra+++-- | A pattern synonym for working with (product) data types. You can declare+-- your own pattern synonyms based off of this.+--+pattern Pattern :: forall b a context. IsPattern context a b => b -> context a+pattern Pattern vars <- (destruct @context -> vars)+  where Pattern = construct @context++class IsPattern con a b where+  construct :: b -> con a+  destruct  :: con a -> b+++pattern Vector :: forall b a context. IsVector context a b => b -> context a+pattern Vector vars <- (vunpack @context -> vars)+  where Vector = vpack @context++class IsVector context a b where+  vpack   :: b -> context a+  vunpack :: context a -> b++-- | Pattern synonyms for indices, which may be more convenient to use than+-- 'Data.Array.Accelerate.Lift.lift' and+-- 'Data.Array.Accelerate.Lift.unlift'.+--+pattern Z_ :: Exp DIM0+pattern Z_ = Pattern Z+{-# COMPLETE Z_ #-}++infixl 3 ::.+pattern (::.) :: (Elt a, Elt b) => Exp a -> Exp b -> Exp (a :. b)+pattern a ::. b = Pattern (a :. b)+{-# COMPLETE (::.) #-}++infixl 3 `Ix`+pattern Ix :: (Elt a, Elt b) => Exp a -> Exp b -> Exp (a :. b)+pattern a `Ix` b = a ::. b+{-# COMPLETE Ix #-}++-- IsPattern instances for Shape nil and cons+--+instance IsPattern Exp Z Z where+  construct _ = constant Z+  destruct _  = Z++instance (Elt a, Elt b) => IsPattern Exp (a :. b) (Exp a :. Exp b) where+  construct (Exp a :. Exp b) = Exp $ SmartExp $ Pair a b+  destruct (Exp t)           = Exp (SmartExp $ Prj PairIdxLeft t) :. Exp (SmartExp $ Prj PairIdxRight t)+++-- IsPattern instances for up to 16-tuples (Acc and Exp). TH takes care of+-- the (unremarkable) boilerplate for us.+--+runQ $ do+    let+        -- Generate instance declarations for IsPattern of the form:+        -- instance (Arrays x, ArraysR x ~ (((), ArraysR a), ArraysR b), Arrays a, Arrays b,) => IsPattern Acc x (Acc a, Acc b)+        mkAccPattern :: Int -> Q [Dec]+        mkAccPattern n = do+          a <- newName "a"+          let+              -- Type variables for the elements+              xs       = [ mkName ('x' : show i) | i <- [0 .. n-1] ]+              -- Last argument to `IsPattern`, eg (Acc a, Acc b) in the example+              b        = tupT (map (\t -> [t| Acc $(varT t)|]) xs)+              -- Representation as snoc-list of pairs, eg (((), ArraysR a), ArraysR b)+              snoc     = foldl (\sn t -> [t| ($sn, ArraysR $(varT t)) |]) [t| () |] xs+              -- Constraints for the type class, consisting of Arrays constraints on all type variables,+              -- and an equality constraint on the representation type of `a` and the snoc representation `snoc`.+              context  = tupT+                       $ [t| Arrays $(varT a) |]+                       : [t| ArraysR $(varT a) ~ $snoc |]+                       : map (\t -> [t| Arrays $(varT t)|]) xs+              --+              get x 0 = [| Acc (SmartAcc (Aprj PairIdxRight $x)) |]+              get x i = get  [| SmartAcc (Aprj PairIdxLeft $x) |] (i-1)+          --+          _x <- newName "_x"+          [d| instance $context => IsPattern Acc $(varT a) $b where+                construct $(tupP (map (\x -> [p| Acc $(varP x)|]) xs)) =+                  Acc $(foldl (\vs v -> [| SmartAcc ($vs `Apair` $(varE v)) |]) [| SmartAcc Anil |] xs)+                destruct (Acc $(varP _x)) =+                  $(tupE (map (get (varE _x)) [(n-1), (n-2) .. 0]))+            |]++        -- Generate instance declarations for IsPattern of the form:+        -- instance (Elt x, EltR x ~ (((), EltR a), EltR b), Elt a, Elt b,) => IsPattern Exp x (Exp a, Exp b)+        mkExpPattern :: Int -> Q [Dec]+        mkExpPattern n = do+          a <- newName "a"+          let+              -- Type variables for the elements+              xs       = [ mkName ('x' : show i) | i <- [0 .. n-1] ]+              -- Variables for sub-pattern matches+              ms       = [ mkName ('m' : show i) | i <- [0 .. n-1] ]+              tags     = foldl (\ts t -> [p| $ts `TagRpair` $(varP t) |]) [p| TagRunit |] ms+              -- Last argument to `IsPattern`, eg (Exp, a, Exp b) in the example+              b        = tupT (map (\t -> [t| Exp $(varT t)|]) xs)+              -- Representation as snoc-list of pairs, eg (((), EltR a), EltR b)+              snoc     = foldl (\sn t -> [t| ($sn, EltR $(varT t)) |]) [t| () |] xs+              -- Constraints for the type class, consisting of Elt constraints on all type variables,+              -- and an equality constraint on the representation type of `a` and the snoc representation `snoc`.+              context  = tupT+                       $ [t| Elt $(varT a) |]+                       : [t| EltR $(varT a) ~ $snoc |]+                       : map (\t -> [t| Elt $(varT t)|]) xs+              --+              get x 0 =     [| SmartExp (Prj PairIdxRight $x) |]+              get x i = get [| SmartExp (Prj PairIdxLeft $x)  |] (i-1)+          --+          _x <- newName "_x"+          _y <- newName "_y"+          [d| instance $context => IsPattern Exp $(varT a) $b where+                construct $(tupP (map (\x -> [p| Exp $(varP x)|]) xs)) =+                  let _unmatch :: SmartExp a -> SmartExp a+                      _unmatch (SmartExp (Match _ $(varP _y))) = $(varE _y)+                      _unmatch x = x+                  in+                  Exp $(foldl (\vs v -> [| SmartExp ($vs `Pair` _unmatch $(varE v)) |]) [| SmartExp Nil |] xs)+                destruct (Exp $(varP _x)) =+                  case $(varE _x) of+                    SmartExp (Match $tags $(varP _y))+                      -> $(tupE [[| Exp (SmartExp (Match $(varE m) $(get (varE _x) i))) |] | m <- ms | i <- [(n-1), (n-2) .. 0]])+                    _ -> $(tupE [[| Exp $(get (varE _x) i) |] | i <- [(n-1), (n-2) .. 0]])+            |]++        -- Generate instance declarations for IsVector of the form:+        -- instance (Elt v, EltR v ~ Vec 2 a, Elt a) => IsVector Exp v (Exp a, Exp a)+        mkVecPattern :: Int -> Q [Dec]+        mkVecPattern n = do+          a <- newName "a"+          v <- newName "v"+          let+              -- Last argument to `IsVector`, eg (Exp, a, Exp a) in the example+              tup      = tupT (replicate n ([t| Exp $(varT a)|]))+              -- Representation as a vector, eg (Vec 2 a)+              vec      = [t| Vec $(litT (numTyLit (fromIntegral n))) $(varT a) |]+              -- Constraints for the type class, consisting of Elt constraints on all type variables,+              -- and an equality constraint on the representation type of `a` and the vector representation `vec`.+              context  = [t| (Elt $(varT v), VecElt $(varT a), EltR $(varT v) ~ $vec) |]+              --+              vecR     = foldr appE [| VecRnil (singleType @ $(varT a)) |] (replicate n [| VecRsucc |])+              tR       = tupT (replicate n (varT a))+          --+          [d| instance $context => IsVector Exp $(varT v) $tup where+                vpack x = case construct x :: Exp $tR of+                            Exp x' -> Exp (SmartExp (VecPack $vecR x'))+                vunpack (Exp x) = destruct (Exp (SmartExp (VecUnpack $vecR x)) :: Exp $tR)+            |]+    --+    es <- mapM mkExpPattern [0..16]+    as <- mapM mkAccPattern [0..16]+    vs <- mapM mkVecPattern [2,3,4,8,16]+    return $ concat (es ++ as ++ vs)+++-- | Specialised pattern synonyms for tuples, which may be more convenient to+-- use than 'Data.Array.Accelerate.Lift.lift' and+-- 'Data.Array.Accelerate.Lift.unlift'. For example, to construct a pair:+--+-- > let a = 4        :: Exp Int+-- > let b = 2        :: Exp Float+-- > let c = T2 a b   -- :: Exp (Int, Float); equivalent to 'lift (a,b)'+--+-- Similarly they can be used to destruct values:+--+-- > let T2 x y = c   -- x :: Exp Int, y :: Exp Float; equivalent to 'let (x,y) = unlift c'+--+-- These pattern synonyms can be used for both 'Exp' and 'Acc' terms.+--+-- Similarly, we have patterns for constructing and destructing indices of+-- a given dimensionality:+--+-- > let ix = Ix 2 3    -- :: Exp DIM2+-- > let I2 y x = ix    -- y :: Exp Int, x :: Exp Int+--+runQ $ do+    let+        mkT :: Int -> Q [Dec]+        mkT n =+          let xs    = [ mkName ('x' : show i) | i <- [0 .. n-1] ]+              ts    = map varT xs+              name  = mkName ('T':show n)+              con   = varT (mkName "con")+              ty1   = tupT ts+              ty2   = tupT (map (con `appT`) ts)+              sig   = foldr (\t r -> [t| $con $t -> $r |]) (appT con ty1) ts+          in+          sequence+            [ patSynSigD name [t| IsPattern $con $ty1 $ty2 => $sig |]+            , patSynD    name (prefixPatSyn xs) implBidir [p| Pattern $(tupP (map varP xs)) |]+            , pragCompleteD [name] (Just ''Acc)+            , pragCompleteD [name] (Just ''Exp)+            ]++        mkI :: Int -> Q [Dec]+        mkI n =+          let xs      = [ mkName ('x' : show i) | i <- [0 .. n-1] ]+              ts      = map varT xs+              name    = mkName ('I':show n)+              ix      = mkName "Ix"+              cst     = tupT (map (\t -> [t| Elt $t |]) ts)+              dim     = foldl (\h t -> [t| $h :. $t |]) [t| Z |] ts+              sig     = foldr (\t r -> [t| Exp $t -> $r |]) [t| Exp $dim |] ts+          in+          sequence+            [ patSynSigD name [t| $cst => $sig |]+            , patSynD    name (prefixPatSyn xs) implBidir (foldl (\ps p -> infixP ps ix (varP p)) [p| Z_ |] xs)+            , pragCompleteD [name] Nothing+            ]++        mkV :: Int -> Q [Dec]+        mkV n =+          let xs    = [ mkName ('x' : show i) | i <- [0 .. n-1] ]+              ts    = map varT xs+              name  = mkName ('V':show n)+              con   = varT (mkName "con")+              ty1   = varT (mkName "vec")+              ty2   = tupT (map (con `appT`) ts)+              sig   = foldr (\t r -> [t| $con $t -> $r |]) (appT con ty1) ts+          in+          sequence+            [ patSynSigD name [t| IsVector $con $ty1 $ty2 => $sig |]+            , patSynD    name (prefixPatSyn xs) implBidir [p| Vector $(tupP (map varP xs)) |]+            , pragCompleteD [name] (Just ''Exp)+            ]+    --+    ts <- mapM mkT [2..16]+    is <- mapM mkI [0..9]+    vs <- mapM mkV [2,3,4,8,16]+    return $ concat (ts ++ is ++ vs)+
+ src/Data/Array/Accelerate/Pattern/Bool.hs view
@@ -0,0 +1,26 @@+{-# LANGUAGE GADTs               #-}+{-# LANGUAGE PatternSynonyms     #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TemplateHaskell     #-}+{-# LANGUAGE TypeApplications    #-}+{-# LANGUAGE ViewPatterns        #-}+-- |+-- Module      : Data.Array.Accelerate.Pattern.Bool+-- Copyright   : [2018..2020] The Accelerate Team+-- License     : BSD3+--+-- Maintainer  : Trevor L. McDonell <trevor.mcdonell@gmail.com>+-- Stability   : experimental+-- Portability : non-portable (GHC extensions)+--++module Data.Array.Accelerate.Pattern.Bool (++  Bool, pattern True_, pattern False_,++) where++import Data.Array.Accelerate.Pattern.TH++mkPattern ''Bool+
+ src/Data/Array/Accelerate/Pattern/Either.hs view
@@ -0,0 +1,26 @@+{-# LANGUAGE GADTs               #-}+{-# LANGUAGE PatternSynonyms     #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TemplateHaskell     #-}+{-# LANGUAGE TypeApplications    #-}+{-# LANGUAGE ViewPatterns        #-}+-- |+-- Module      : Data.Array.Accelerate.Pattern.Either+-- Copyright   : [2018..2020] The Accelerate Team+-- License     : BSD3+--+-- Maintainer  : Trevor L. McDonell <trevor.mcdonell@gmail.com>+-- Stability   : experimental+-- Portability : non-portable (GHC extensions)+--++module Data.Array.Accelerate.Pattern.Either (++  Either, pattern Left_, pattern Right_,++) where++import Data.Array.Accelerate.Pattern.TH++mkPattern ''Either+
+ src/Data/Array/Accelerate/Pattern/Maybe.hs view
@@ -0,0 +1,26 @@+{-# LANGUAGE GADTs               #-}+{-# LANGUAGE PatternSynonyms     #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TemplateHaskell     #-}+{-# LANGUAGE TypeApplications    #-}+{-# LANGUAGE ViewPatterns        #-}+-- |+-- Module      : Data.Array.Accelerate.Pattern.Maybe+-- Copyright   : [2018..2020] The Accelerate Team+-- License     : BSD3+--+-- Maintainer  : Trevor L. McDonell <trevor.mcdonell@gmail.com>+-- Stability   : experimental+-- Portability : non-portable (GHC extensions)+--++module Data.Array.Accelerate.Pattern.Maybe (++  Maybe, pattern Nothing_, pattern Just_,++) where++import Data.Array.Accelerate.Pattern.TH++mkPattern ''Maybe+
+ src/Data/Array/Accelerate/Pattern/Ordering.hs view
@@ -0,0 +1,26 @@+{-# LANGUAGE GADTs               #-}+{-# LANGUAGE PatternSynonyms     #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TemplateHaskell     #-}+{-# LANGUAGE TypeApplications    #-}+{-# LANGUAGE ViewPatterns        #-}+-- |+-- Module      : Data.Array.Accelerate.Pattern.Ordering+-- Copyright   : [2018..2020] The Accelerate Team+-- License     : BSD3+--+-- Maintainer  : Trevor L. McDonell <trevor.mcdonell@gmail.com>+-- Stability   : experimental+-- Portability : non-portable (GHC extensions)+--++module Data.Array.Accelerate.Pattern.Ordering (++  Ordering, pattern LT_, pattern EQ_, pattern GT_,++) where++import Data.Array.Accelerate.Pattern.TH++mkPattern ''Ordering+
+ src/Data/Array/Accelerate/Pattern/TH.hs view
@@ -0,0 +1,456 @@+{-# LANGUAGE TemplateHaskell  #-}+{-# LANGUAGE TypeApplications #-}+-- |+-- Module      : Data.Array.Accelerate.Pattern.TH+-- Copyright   : [2018..2020] The Accelerate Team+-- License     : BSD3+--+-- Maintainer  : Trevor L. McDonell <trevor.mcdonell@gmail.com>+-- Stability   : experimental+-- Portability : non-portable (GHC extensions)+--++module Data.Array.Accelerate.Pattern.TH (++  mkPattern,+  mkPatterns,++) where++import Data.Array.Accelerate.AST.Idx+import Data.Array.Accelerate.Pattern+import Data.Array.Accelerate.Representation.Tag+import Data.Array.Accelerate.Smart+import Data.Array.Accelerate.Sugar.Elt+import Data.Array.Accelerate.Type++import Control.Monad+import Data.Bits+import Data.Char+import Data.List                                                    ( (\\), foldl' )+import Language.Haskell.TH                                          hiding ( Exp, Match, match, tupP, tupE )+import Language.Haskell.TH.Extra+import Numeric+import Text.Printf+import qualified Language.Haskell.TH                                as TH++import GHC.Stack+++-- | As 'mkPattern', but for a list of types+--+mkPatterns :: [Name] -> DecsQ+mkPatterns nms = concat <$> mapM mkPattern nms++-- | Generate pattern synonyms for the given simple (Haskell'98) sum or+-- product data type.+--+-- Constructor and record selectors are renamed to add a trailing+-- underscore if it does not exist, or to remove it if it does. For infix+-- constructors, the name is prepended with a colon ':'. For example:+--+-- > data Point = Point { xcoord_ :: Float, ycoord_ :: Float }+-- >   deriving (Generic, Elt)+--+-- Will create the pattern synonym:+--+-- > Point_ :: Exp Float -> Exp Float -> Exp Point+--+-- together with the selector functions+--+-- > xcoord :: Exp Point -> Exp Float+-- > ycoord :: Exp Point -> Exp Float+--+mkPattern :: Name -> DecsQ+mkPattern nm = do+  info <- reify nm+  case info of+    TyConI dec -> mkDec dec+    _          -> fail "mkPatterns: expected the name of a newtype or datatype"++mkDec :: Dec -> DecsQ+mkDec dec =+  case dec of+    DataD    _ nm tv _ cs _ -> mkDataD nm tv cs+    NewtypeD _ nm tv _ c  _ -> mkNewtypeD nm tv c+    _                       -> fail "mkPatterns: expected the name of a newtype or datatype"++mkNewtypeD :: Name -> [TyVarBndr] -> Con -> DecsQ+mkNewtypeD tn tvs c = mkDataD tn tvs [c]++mkDataD :: Name -> [TyVarBndr] -> [Con] -> DecsQ+mkDataD tn tvs cs = do+  (pats, decs) <- unzip <$> go cs+  comp         <- pragCompleteD pats Nothing+  return $ comp : concat decs+  where+    -- For single-constructor types we create the pattern synonym for the+    -- type directly in terms of Pattern+    go []  = fail "mkPatterns: empty data declarations not supported"+    go [c] = return <$> mkConP tn tvs c+    go _   = go' [] (map fieldTys cs) ctags cs++    -- For sum-types, when creating the pattern for an individual+    -- constructor we need to know about the types of the fields all other+    -- constructors as well+    go' prev (this:next) (tag:tags) (con:cons) = do+      r  <- mkConS tn tvs prev next tag con+      rs <- go' (this:prev) next tags cons+      return (r : rs)+    go' _ [] [] [] = return []+    go' _ _  _  _  = fail "mkPatterns: unexpected error"++    fieldTys (NormalC _ fs) = map snd fs+    fieldTys (RecC _ fs)    = map (\(_,_,t) -> t) fs+    fieldTys (InfixC a _ b) = [snd a, snd b]+    fieldTys _              = fail "mkPatterns: only constructors for \"vanilla\" syntax are supported"++    -- TODO: The GTags class demonstrates a way to generate the tags for+    -- a given constructor, rather than backwards-engineering the structure+    -- as we've done here. We should use that instead!+    --+    ctags =+      let n = length cs+          m = n `quot` 2+          l = take m     (iterate (True:) [False])+          r = take (n-m) (iterate (True:) [True])+          --+          bitsToTag = foldl' f 0+            where+              f i False =         i `shiftL` 1+              f i True  = setBit (i `shiftL` 1) 0+      in+      map bitsToTag (l ++ r)+++mkConP :: Name -> [TyVarBndr] -> Con -> Q (Name, [Dec])+mkConP tn' tvs' con' = do+  checkExts [ PatternSynonyms ]+  case con' of+    NormalC cn fs -> mkNormalC tn' cn (map tyVarBndrName tvs') (map snd fs)+    RecC cn fs    -> mkRecC tn' cn (map tyVarBndrName tvs') (map (rename . fst3) fs) (map thd3 fs)+    InfixC a cn b -> mkInfixC tn' cn (map tyVarBndrName tvs') [snd a, snd b]+    _             -> fail "mkPatterns: only constructors for \"vanilla\" syntax are supported"+  where+    mkNormalC :: Name -> Name -> [Name] -> [Type] -> Q (Name, [Dec])+    mkNormalC tn cn tvs fs = do+      xs <- replicateM (length fs) (newName "_x")+      r  <- sequence [ patSynSigD pat sig+                     , patSynD    pat+                         (prefixPatSyn xs)+                         implBidir+                         [p| Pattern $(tupP (map varP xs)) |]+                     ]+      return (pat, r)+      where+        pat = rename cn+        sig = forallT+                (map plainTV tvs)+                (cxt (map (\t -> [t| Elt $(varT t) |]) tvs))+                (foldr (\t ts -> [t| $t -> $ts |])+                       [t| Exp $(foldl' appT (conT tn) (map varT tvs)) |]+                       (map (\t -> [t| Exp $(return t) |]) fs))++    mkRecC :: Name -> Name -> [Name] -> [Name] -> [Type] -> Q (Name, [Dec])+    mkRecC tn cn tvs xs fs = do+      r  <- sequence [ patSynSigD pat sig+                     , patSynD    pat+                         (recordPatSyn xs)+                         implBidir+                         [p| Pattern $(tupP (map varP xs)) |]+                     ]+      return (pat, r)+      where+        pat = rename cn+        sig = forallT+                (map plainTV tvs)+                (cxt (map (\t -> [t| Elt $(varT t) |]) tvs))+                (foldr (\t ts -> [t| $t -> $ts |])+                       [t| Exp $(foldl' appT (conT tn) (map varT tvs)) |]+                       (map (\t -> [t| Exp $(return t) |]) fs))++    mkInfixC :: Name -> Name -> [Name] -> [Type] -> Q (Name, [Dec])+    mkInfixC tn cn tvs fs = do+      mf <- reifyFixity cn+      _a <- newName "_a"+      _b <- newName "_b"+      r  <- sequence [ patSynSigD pat sig+                     , patSynD    pat+                         (infixPatSyn _a _b)+                         implBidir+                         [p| Pattern $(tupP [varP _a, varP _b]) |]+                     ]+      r' <- case mf of+              Nothing -> return r+              Just f  -> return (InfixD f pat : r)+      return (pat, r')+      where+        pat = mkName (':' : nameBase cn)+        sig = forallT+                (map plainTV tvs)+                (cxt (map (\t -> [t| Elt $(varT t) |]) tvs))+                (foldr (\t ts -> [t| $t -> $ts |])+                       [t| Exp $(foldl' appT (conT tn) (map varT tvs)) |]+                       (map (\t -> [t| Exp $(return t) |]) fs))++mkConS :: Name -> [TyVarBndr] -> [[Type]] -> [[Type]] -> Word8 -> Con -> Q (Name, [Dec])+mkConS tn' tvs' prev' next' tag' con' = do+  checkExts [GADTs, PatternSynonyms, ScopedTypeVariables, TypeApplications, ViewPatterns]+  case con' of+    NormalC cn fs -> mkNormalC tn' cn tag' (map tyVarBndrName tvs') prev' (map snd fs) next'+    RecC cn fs    -> mkRecC tn' cn tag' (map tyVarBndrName tvs') (map (rename . fst3) fs) prev' (map thd3 fs) next'+    InfixC a cn b -> mkInfixC tn' cn tag' (map tyVarBndrName tvs') prev' [snd a, snd b] next'+    _             -> fail "mkPatterns: only constructors for \"vanilla\" syntax are supported"+  where+    mkNormalC :: Name -> Name -> Word8 -> [Name] -> [[Type]] -> [Type] -> [[Type]] -> Q (Name, [Dec])+    mkNormalC tn cn tag tvs ps fs ns = do+      let pat = rename cn+      (fun_build, dec_build) <- mkBuild tn (nameBase cn) tvs tag ps fs ns+      (fun_match, dec_match) <- mkMatch tn (nameBase pat) (nameBase cn) tvs tag ps fs ns+      dec_pat                <- mkNormalC_pattern tn pat tvs fs fun_build fun_match+      return $ (pat, concat [dec_pat, dec_build, dec_match])++    mkRecC :: Name -> Name -> Word8 -> [Name] -> [Name] -> [[Type]] -> [Type] -> [[Type]] -> Q (Name, [Dec])+    mkRecC tn cn tag tvs xs ps fs ns = do+      let pat = rename cn+      (fun_build, dec_build) <- mkBuild tn (nameBase cn) tvs tag ps fs ns+      (fun_match, dec_match) <- mkMatch tn (nameBase pat) (nameBase cn) tvs tag ps fs ns+      dec_pat                <- mkRecC_pattern tn pat tvs xs fs fun_build fun_match+      return $ (pat, concat [dec_pat, dec_build, dec_match])++    mkInfixC :: Name -> Name -> Word8 -> [Name] -> [[Type]] -> [Type] -> [[Type]] -> Q (Name, [Dec])+    mkInfixC tn cn tag tvs ps fs ns = do+      let pat = mkName (':' : nameBase cn)+      (fun_build, dec_build) <- mkBuild tn (zencode (nameBase cn)) tvs tag ps fs ns+      (fun_match, dec_match) <- mkMatch tn ("(" ++ nameBase pat ++ ")") (zencode (nameBase cn)) tvs tag ps fs ns+      dec_pat                <- mkInfixC_pattern tn cn pat tvs fs fun_build fun_match+      return $ (pat, concat [dec_pat, dec_build, dec_match])++    mkNormalC_pattern :: Name -> Name -> [Name] -> [Type] -> Name -> Name -> Q [Dec]+    mkNormalC_pattern tn pat tvs fs build match = do+      xs <- replicateM (length fs) (newName "_x")+      r  <- sequence [ patSynSigD pat sig+                     , patSynD    pat+                         (prefixPatSyn xs)+                         (explBidir [clause [] (normalB (varE build)) []])+                         (parensP $ viewP (varE match) [p| Just $(tupP (map varP xs)) |])+                     ]+      return r+      where+        sig = forallT+                (map plainTV tvs)+                (cxt ([t| HasCallStack |] : map (\t -> [t| Elt $(varT t) |]) tvs))+                (foldr (\t ts -> [t| $t -> $ts |])+                       [t| Exp $(foldl' appT (conT tn) (map varT tvs)) |]+                       (map (\t -> [t| Exp $(return t) |]) fs))++    mkRecC_pattern :: Name -> Name -> [Name] -> [Name] -> [Type] -> Name -> Name -> Q [Dec]+    mkRecC_pattern tn pat tvs xs fs build match = do+      r  <- sequence [ patSynSigD pat sig+                     , patSynD    pat+                         (recordPatSyn xs)+                         (explBidir [clause [] (normalB (varE build)) []])+                         (parensP $ viewP (varE match) [p| Just $(tupP (map varP xs)) |])+                     ]+      return r+      where+        sig = forallT+                (map plainTV tvs)+                (cxt ([t| HasCallStack |] : map (\t -> [t| Elt $(varT t) |]) tvs))+                (foldr (\t ts -> [t| $t -> $ts |])+                       [t| Exp $(foldl' appT (conT tn) (map varT tvs)) |]+                       (map (\t -> [t| Exp $(return t) |]) fs))++    mkInfixC_pattern :: Name -> Name -> Name -> [Name] -> [Type] -> Name -> Name -> Q [Dec]+    mkInfixC_pattern tn cn pat tvs fs build match = do+      mf <- reifyFixity cn+      _a <- newName "_a"+      _b <- newName "_b"+      r  <- sequence [ patSynSigD pat sig+                     , patSynD    pat+                         (infixPatSyn _a _b)+                         (explBidir [clause [] (normalB (varE build)) []])+                         (parensP $ viewP (varE match) [p| Just $(tupP [varP _a, varP _b]) |])+                     ]+      r' <- case mf of+              Nothing -> return r+              Just f  -> return (InfixD f pat : r)+      return r'+      where+        sig = forallT+                (map plainTV tvs)+                (cxt ([t| HasCallStack |] : map (\t -> [t| Elt $(varT t) |]) tvs))+                (foldr (\t ts -> [t| $t -> $ts |])+                       [t| Exp $(foldl' appT (conT tn) (map varT tvs)) |]+                       (map (\t -> [t| Exp $(return t) |]) fs))++    mkBuild :: Name -> String -> [Name] -> Word8 -> [[Type]] -> [Type] -> [[Type]] -> Q (Name, [Dec])+    mkBuild tn cn tvs tag fs0 fs fs1 = do+      fun <- newName ("_build" ++ cn)+      xs  <- replicateM (length fs) (newName "_x")+      let+        vs    = foldl' (\es e -> [| SmartExp ($es `Pair` $e) |]) [| SmartExp Nil |]+              $  map (\t -> [| unExp (undef @ $(return t)) |] ) (concat (reverse fs0))+              ++ map varE xs+              ++ map (\t -> [| unExp (undef @ $(return t)) |] ) (concat fs1)++        tagged = [| Exp $ SmartExp $ Pair (SmartExp (Const (SingleScalarType (NumSingleType (IntegralNumType TypeWord8))) $(litE (IntegerL (toInteger tag))))) $vs |]+        body   = clause (map (\x -> [p| (Exp $(varP x)) |]) xs) (normalB tagged) []++      r <- sequence [ sigD fun sig+                    , funD fun [body]+                    ]+      return (fun, r)+      where+        sig = forallT+                (map plainTV tvs)+                (cxt (map (\t -> [t| Elt $(varT t) |]) tvs))+                (foldr (\t ts -> [t| $t -> $ts |])+                       [t| Exp $(foldl' appT (conT tn) (map varT tvs)) |]+                       (map (\t -> [t| Exp $(return t) |]) fs))+++    mkMatch :: Name -> String -> String -> [Name] -> Word8 -> [[Type]] -> [Type] -> [[Type]] -> Q (Name, [Dec])+    mkMatch tn pn cn tvs tag fs0 fs fs1 = do+      fun     <- newName ("_match" ++ cn)+      e       <- newName "_e"+      x       <- newName "_x"+      (ps,es) <- extract vs [| Prj PairIdxRight $(varE x) |] [] []+      unbind  <- isExtEnabled RebindableSyntax+      let+        eqE   = if unbind then letE [funD (mkName "==") [clause [] (normalB (varE '(==))) []]] else id+        lhs   = [p| (Exp $(varP e)) |]+        body  = normalB $ eqE $ caseE (varE e)+          [ TH.match (conP 'SmartExp [(conP 'Match [matchP ps, varP x])]) (normalB [| Just $(tupE es)  |]) []+          , TH.match (conP 'SmartExp [(recP 'Match [])])                  (normalB [| Nothing          |]) []+          , TH.match wildP                                                (normalB [| error $error_msg |]) []+          ]++      r <- sequence [ sigD fun sig+                    , funD fun [clause [lhs] body []]+                    ]+      return (fun, r)+      where+        sig = forallT+                (map plainTV tvs)+                (cxt ([t| HasCallStack |] : map (\t -> [t| Elt $(varT t) |]) tvs))+                [t| Exp $(foldl' appT (conT tn) (map varT tvs)) -> Maybe $(tupT (map (\t -> [t| Exp $(return t) |]) fs)) |]++        matchP us = [p| TagRtag $(litP (IntegerL (toInteger tag))) $pat |]+          where+            pat = [p| $(foldl (\ps p -> [p| TagRpair $ps $p |]) [p| TagRunit |] us) |]++        extract []     _ ps es = return (ps, es)+        extract (u:us) x ps es = do+          _u <- newName "_u"+          let x' = [| Prj PairIdxLeft (SmartExp $x) |]+          if not u+             then extract us x' (wildP:ps)  es+             else extract us x' (varP _u:ps) ([| Exp (SmartExp (Match $(varE _u) (SmartExp (Prj PairIdxRight (SmartExp $x))))) |] : es)++        vs = reverse+           $ [ False | _ <- concat fs0 ] ++ [ True | _ <- fs ] ++ [ False | _ <- concat fs1 ]++        error_msg =+          let pv = unwords+                 $ take (length fs + 1)+                 $ concatMap (map reverse)+                 $ iterate (concatMap (\xs -> [ x:xs | x <- ['a'..'z'] ])) [""]+           in stringE $ unlines+             [ "Embedded pattern synonym used outside 'match' context."+             , ""+             , "To use case statements in the embedded language the case statement must"+             , "be applied as an n-ary function to the 'match' operator. For single"+             , "argument case statements this can be done inline using LambdaCase, for"+             , "example:"+             , ""+             , "> x & match \\case"+             , printf ">   %s%s -> ..." pn pv+             , printf ">   _%s -> ..." (replicate (length pn + length pv - 1) ' ')+             ]++fst3 :: (a,b,c) -> a+fst3 (a,_,_) = a++thd3 :: (a,b,c) -> c+thd3 (_,_,c) = c++rename :: Name -> Name+rename nm =+  let+      split acc []     = (reverse acc, '\0')  -- shouldn't happen+      split acc [l]    = (reverse acc, l)+      split acc (l:ls) = split (l:acc) ls+      --+      nm'              = nameBase nm+      (base, suffix)   = split [] nm'+   in+   case suffix of+     '_' -> mkName base+     _   -> mkName (nm' ++ "_")++checkExts :: [Extension] -> Q ()+checkExts req = do+  enabled <- extsEnabled+  let missing = req \\ enabled+  unless (null missing) . fail . unlines+    $ printf "You must enable the following language extensions to generate pattern synonyms:"+    : map (printf "    {-# LANGUAGE %s #-}" . show) missing++-- A simplified version of that stolen from GHC/Utils/Encoding.hs+--+type EncodedString = String++zencode :: String -> EncodedString+zencode []       = []+zencode (h:rest) = encode_digit h ++ go rest+  where+    go []     = []+    go (c:cs) = encode_ch c ++ go cs++unencoded_char :: Char -> Bool+unencoded_char 'z' = False+unencoded_char 'Z' = False+unencoded_char c   = isAlphaNum c++encode_digit :: Char -> EncodedString+encode_digit c | isDigit c = encode_as_unicode_char c+               | otherwise = encode_ch c++encode_ch :: Char -> EncodedString+encode_ch c | unencoded_char c = [c]     -- Common case first+encode_ch '('  = "ZL"+encode_ch ')'  = "ZR"+encode_ch '['  = "ZM"+encode_ch ']'  = "ZN"+encode_ch ':'  = "ZC"+encode_ch 'Z'  = "ZZ"+encode_ch 'z'  = "zz"+encode_ch '&'  = "za"+encode_ch '|'  = "zb"+encode_ch '^'  = "zc"+encode_ch '$'  = "zd"+encode_ch '='  = "ze"+encode_ch '>'  = "zg"+encode_ch '#'  = "zh"+encode_ch '.'  = "zi"+encode_ch '<'  = "zl"+encode_ch '-'  = "zm"+encode_ch '!'  = "zn"+encode_ch '+'  = "zp"+encode_ch '\'' = "zq"+encode_ch '\\' = "zr"+encode_ch '/'  = "zs"+encode_ch '*'  = "zt"+encode_ch '_'  = "zu"+encode_ch '%'  = "zv"+encode_ch c    = encode_as_unicode_char c++encode_as_unicode_char :: Char -> EncodedString+encode_as_unicode_char c+  = 'z'+  : if isDigit (head hex_str) then hex_str+                              else '0':hex_str+  where+    hex_str = showHex (ord c) "U"+
src/Data/Array/Accelerate/Prelude.hs view
@@ -1,21 +1,24 @@+{-# LANGUAGE AllowAmbiguousTypes   #-} {-# LANGUAGE CPP                   #-} {-# LANGUAGE ConstraintKinds       #-} {-# LANGUAGE FlexibleContexts      #-} {-# LANGUAGE FlexibleInstances     #-}+{-# LANGUAGE GADTs                 #-} {-# LANGUAGE MultiParamTypeClasses #-} {-# LANGUAGE PatternGuards         #-} {-# LANGUAGE RankNTypes            #-} {-# LANGUAGE RebindableSyntax      #-} {-# LANGUAGE ScopedTypeVariables   #-}+{-# LANGUAGE TypeApplications      #-} {-# LANGUAGE TypeFamilies          #-} {-# LANGUAGE TypeOperators         #-}+{-# OPTIONS_GHC -fno-warn-incomplete-patterns #-}   -- pattern synonyms -- | -- Module      : Data.Array.Accelerate.Prelude--- Copyright   : [2009..2017] Manuel M T Chakravarty, Gabriele Keller, Trevor L. McDonell---               [2010..2011] Ben Lever+-- Copyright   : [2009..2020] The Accelerate Team -- License     : BSD3 ----- Maintainer  : Trevor L. McDonell <tmcdonell@cse.unsw.edu.au>+-- Maintainer  : Trevor L. McDonell <trevor.mcdonell@gmail.com> -- Stability   : experimental -- Portability : non-portable (GHC extensions) --@@ -39,6 +42,7 @@    -- * Reductions   foldAll, fold1All,+  foldSeg, fold1Seg,    -- ** Specialised folds   all, any, and, or, sum, product, minimum, maximum,@@ -61,7 +65,7 @@    -- * Working with predicates   -- ** Filtering-  filter,+  filter, compact,    -- ** Scatter / Gather   scatter, scatterIf,@@ -85,7 +89,7 @@   (?|),    -- ** Expression-level-  (?), caseof,+  (?), match,    -- * Scalar iteration   iterate,@@ -106,27 +110,23 @@   -- * Array operations with a scalar result   the, null, length, +  -- * Irregular data-parallelism+  expand,+   -- * Sequence operations   -- fromSeq, fromSeqElems, fromSeqShapes, toSeqInner, toSeqOuter2, toSeqOuter3, generateSeq,  ) where --- avoid clashes with Prelude functions----import Control.Lens                                                 ( Lens', (&), (^.), (.~), (+~), (-~), lens, over )-import Data.Typeable                                                ( gcast )-import GHC.Base                                                     ( Constraint )-import Prelude                                                      ( (.), ($), Maybe(..), const, id, flip, undefined )-#if __GLASGOW_HASKELL__ == 800-import Prelude                                                      ( fail )-#endif---- friends import Data.Array.Accelerate.Analysis.Match-import Data.Array.Accelerate.Array.Sugar                            hiding ( (!), (!!), ignore, shape, reshape, size, intersect, toIndex, fromIndex ) import Data.Array.Accelerate.Language import Data.Array.Accelerate.Lift+import Data.Array.Accelerate.Pattern+import Data.Array.Accelerate.Pattern.Maybe import Data.Array.Accelerate.Smart+import Data.Array.Accelerate.Sugar.Array                            ( Arrays, Array, Scalar, Vector, Segments,  fromList )+import Data.Array.Accelerate.Sugar.Elt+import Data.Array.Accelerate.Sugar.Shape                            ( Shape, Slice, Z(..), (:.)(..), All(..), DIM1, DIM2, empty ) import Data.Array.Accelerate.Type  import Data.Array.Accelerate.Classes.Eq@@ -137,7 +137,14 @@  import Data.Array.Accelerate.Data.Bits +import Control.Lens                                                 ( Lens', (&), (^.), (.~), (+~), (-~), lens, over )+import Prelude                                                      ( (.), ($), Maybe(..), const, id, flip )++import GHC.Base                                                     ( Constraint )++ -- $setup+-- >>> :seti -XFlexibleContexts -- >>> import Data.Array.Accelerate -- >>> import Data.Array.Accelerate.Interpreter -- >>> :{@@ -162,7 +169,7 @@ --     (Z :. 2 :. 0,8.0), (Z :. 2 :. 1,9.0), (Z :. 2 :. 2,10.0), (Z :. 2 :. 3,11.0)] -- indexed :: (Shape sh, Elt a) => Acc (Array sh a) -> Acc (Array sh (sh, a))-indexed xs = zip (generate (shape xs) id) xs+indexed = imap T2  -- | Apply a function to every element of an array and its index --@@ -172,7 +179,18 @@      -> Acc (Array sh b) imap f xs = zipWith f (generate (shape xs) id) xs +-- | Used to define the zipWith functions on more than two arrays+--+zipWithInduction+    :: (Shape sh, Elt a, Elt b)+    => ((Exp (a,b) -> rest) -> Acc (Array sh (a,b)) -> result) -- The zipWith function operating on one fewer array+    -> (Exp a -> Exp b -> rest)+    -> Acc (Array sh a)+    -> Acc (Array sh b)+    -> result+zipWithInduction prev f as bs = prev (\(T2 a b) -> f a b) (zip as bs) + -- | Zip three arrays with the given function, analogous to 'zipWith'. -- zipWith3@@ -182,9 +200,7 @@     -> 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))+zipWith3 = zipWithInduction zipWith  -- | Zip four arrays with the given function, analogous to 'zipWith'. --@@ -196,10 +212,7 @@     -> 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))+zipWith4 = zipWithInduction zipWith3  -- | Zip five arrays with the given function, analogous to 'zipWith'. --@@ -212,10 +225,7 @@     -> 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))+zipWith5 = zipWithInduction zipWith4  -- | Zip six arrays with the given function, analogous to 'zipWith'. --@@ -229,11 +239,7 @@     -> 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))+zipWith6 = zipWithInduction zipWith5  -- | Zip seven arrays with the given function, analogous to 'zipWith'. --@@ -248,11 +254,7 @@     -> 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))+zipWith7 = zipWithInduction zipWith6  -- | Zip eight arrays with the given function, analogous to 'zipWith'. --@@ -268,12 +270,7 @@     -> 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))+zipWith8 = zipWithInduction zipWith7  -- | Zip nine arrays with the given function, analogous to 'zipWith'. --@@ -290,14 +287,21 @@     -> 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))+zipWith9 = zipWithInduction zipWith8  +-- | Used to define the izipWith functions on two or more arrays+--+izipWithInduction+    :: (Shape sh, Elt a, Elt b)+    => ((Exp sh -> Exp (a,b) -> rest) -> Acc (Array sh (a,b)) -> result) -- The zipWith function operating on one fewer array+    -> (Exp sh -> Exp a -> Exp b -> rest)+    -> Acc (Array sh a)+    -> Acc (Array sh b)+    -> result+izipWithInduction prev f as bs = prev (\ix (T2 a b) -> f ix a b) (zip as bs)++ -- | Zip two arrays with a function that also takes the element index -- izipWith@@ -306,9 +310,7 @@     -> 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))+izipWith = izipWithInduction imap  -- | Zip three arrays with a function that also takes the element index, -- analogous to 'izipWith'.@@ -320,9 +322,7 @@     -> 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))+izipWith3 = izipWithInduction izipWith  -- | Zip four arrays with the given function that also takes the element index, -- analogous to 'zipWith'.@@ -335,10 +335,7 @@     -> 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))+izipWith4 = izipWithInduction izipWith3  -- | Zip five arrays with the given function that also takes the element index, -- analogous to 'zipWith'.@@ -352,10 +349,7 @@     -> 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))+izipWith5 = izipWithInduction izipWith4  -- | Zip six arrays with the given function that also takes the element index, -- analogous to 'zipWith'.@@ -370,11 +364,7 @@     -> 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))+izipWith6 = izipWithInduction izipWith5  -- | Zip seven arrays with the given function that also takes the element -- index, analogous to 'zipWith'.@@ -390,11 +380,7 @@     -> 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))+izipWith7 = izipWithInduction izipWith6  -- | Zip eight arrays with the given function that also takes the element -- index, analogous to 'zipWith'.@@ -411,12 +397,7 @@     -> 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))+izipWith8 = izipWithInduction izipWith7  -- | Zip nine arrays with the given function that also takes the element index, -- analogous to 'zipWith'.@@ -434,12 +415,7 @@     -> 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))+izipWith9 = izipWithInduction izipWith8   -- | Combine the elements of two arrays pairwise. The shape of the result is the@@ -459,7 +435,7 @@     => Acc (Array sh a)     -> Acc (Array sh b)     -> Acc (Array sh (a, b))-zip = zipWith (curry lift)+zip = zipWith T2  -- | Take three arrays and return an array of triples, analogous to zip. --@@ -468,7 +444,7 @@      -> Acc (Array sh b)      -> Acc (Array sh c)      -> Acc (Array sh (a, b, c))-zip3 = zipWith3 (\a b c -> lift (a,b,c))+zip3 = zipWith3 T3  -- | Take four arrays and return an array of quadruples, analogous to zip. --@@ -478,7 +454,7 @@      -> 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))+zip4 = zipWith4 T4  -- | Take five arrays and return an array of five-tuples, analogous to zip. --@@ -489,7 +465,7 @@      -> 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))+zip5 = zipWith5 T5  -- | Take six arrays and return an array of six-tuples, analogous to zip. --@@ -501,7 +477,7 @@      -> 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))+zip6 = zipWith6 T6  -- | Take seven arrays and return an array of seven-tuples, analogous to zip. --@@ -514,7 +490,7 @@      -> 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))+zip7 = zipWith7 T7  -- | Take seven arrays and return an array of seven-tuples, analogous to zip. --@@ -528,7 +504,7 @@      -> 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))+zip8 = zipWith8 T8  -- | Take seven arrays and return an array of seven-tuples, analogous to zip. --@@ -543,7 +519,7 @@      -> 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))+zip9 = zipWith9 T9   -- | The converse of 'zip', but the shape of the two results is identical to the@@ -563,9 +539,9 @@        -> (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+    get1 (T3 a _ _) = a+    get2 (T3 _ b _) = b+    get3 (T3 _ _ c) = c   -- | Take an array of quadruples and return four arrays, analogous to 'unzip'.@@ -575,10 +551,10 @@        -> (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+    get1 (T4 a _ _ _) = a+    get2 (T4 _ b _ _) = b+    get3 (T4 _ _ c _) = c+    get4 (T4 _ _ _ d) = d  -- | Take an array of 5-tuples and return five arrays, analogous to 'unzip'. --@@ -587,11 +563,11 @@        -> (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+    get1 (T5 a _ _ _ _) = a+    get2 (T5 _ b _ _ _) = b+    get3 (T5 _ _ c _ _) = c+    get4 (T5 _ _ _ d _) = d+    get5 (T5 _ _ _ _ e) = e  -- | Take an array of 6-tuples and return six arrays, analogous to 'unzip'. --@@ -601,12 +577,12 @@           , 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+    get1 (T6 a _ _ _ _ _) = a+    get2 (T6 _ b _ _ _ _) = b+    get3 (T6 _ _ c _ _ _) = c+    get4 (T6 _ _ _ d _ _) = d+    get5 (T6 _ _ _ _ e _) = e+    get6 (T6 _ _ _ _ _ f) = f  -- | Take an array of 7-tuples and return seven arrays, analogous to 'unzip'. --@@ -619,13 +595,13 @@             , 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+    get1 (T7 a _ _ _ _ _ _) = a+    get2 (T7 _ b _ _ _ _ _) = b+    get3 (T7 _ _ c _ _ _ _) = c+    get4 (T7 _ _ _ d _ _ _) = d+    get5 (T7 _ _ _ _ e _ _) = e+    get6 (T7 _ _ _ _ _ f _) = f+    get7 (T7 _ _ _ _ _ _ g) = g  -- | Take an array of 8-tuples and return eight arrays, analogous to 'unzip'. --@@ -638,16 +614,16 @@             , 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+    get1 (T8 a _ _ _ _ _ _ _) = a+    get2 (T8 _ b _ _ _ _ _ _) = b+    get3 (T8 _ _ c _ _ _ _ _) = c+    get4 (T8 _ _ _ d _ _ _ _) = d+    get5 (T8 _ _ _ _ e _ _ _) = e+    get6 (T8 _ _ _ _ _ f _ _) = f+    get7 (T8 _ _ _ _ _ _ g _) = g+    get8 (T8 _ _ _ _ _ _ _ h) = h --- | Take an array of 8-tuples and return eight arrays, analogous to 'unzip'.+-- | Take an array of 9-tuples and return nine 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))@@ -658,15 +634,15 @@             , 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+    get1 (T9 a _ _ _ _ _ _ _ _) = a+    get2 (T9 _ b _ _ _ _ _ _ _) = b+    get3 (T9 _ _ c _ _ _ _ _ _) = c+    get4 (T9 _ _ _ d _ _ _ _ _) = d+    get5 (T9 _ _ _ _ e _ _ _ _) = e+    get6 (T9 _ _ _ _ _ f _ _ _) = f+    get7 (T9 _ _ _ _ _ _ g _ _) = g+    get8 (T9 _ _ _ _ _ _ _ h _) = h+    get9 (T9 _ _ _ _ _ _ _ _ i) = i   -- Reductions@@ -704,6 +680,83 @@ fold1All f arr = fold1 f (flatten arr)  +-- | 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] :: Segments Int+-- >>> seg+-- Vector (Z :. 4) [1,4,0,3]+--+-- >>> let mat = fromList (Z:.5:.10) [0..] :: Matrix 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]+--+-- >>> run $ 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+    :: forall sh e i. (Shape sh, Elt e, Elt i, i ~ EltR i, IsIntegral i)+    => (Exp e -> Exp e -> Exp e)+    -> Exp e+    -> Acc (Array (sh:.Int) e)+    -> Acc (Segments i)+    -> Acc (Array (sh:.Int) e)+foldSeg f z arr seg = foldSeg' f z arr (scanl plus zero seg)+  where+    (plus, zero) =+      case integralType @i of+        TypeInt{}    -> ((+), 0)+        TypeInt8{}   -> ((+), 0)+        TypeInt16{}  -> ((+), 0)+        TypeInt32{}  -> ((+), 0)+        TypeInt64{}  -> ((+), 0)+        TypeWord{}   -> ((+), 0)+        TypeWord8{}  -> ((+), 0)+        TypeWord16{} -> ((+), 0)+        TypeWord32{} -> ((+), 0)+        TypeWord64{} -> ((+), 0)+++-- | Variant of 'foldSeg' that requires /all/ segments of the reduced array+-- to be non-empty, and does not need a default value. The segment+-- descriptor species the length of each of the logical sub-arrays.+--+fold1Seg+    :: forall sh e i. (Shape sh, Elt e, Elt i, i ~ EltR i, IsIntegral i)+    => (Exp e -> Exp e -> Exp e)+    -> Acc (Array (sh:.Int) e)+    -> Acc (Segments i)+    -> Acc (Array (sh:.Int) e)+fold1Seg f arr seg = fold1Seg' f arr (scanl plus zero seg)+  where+    plus :: Exp i -> Exp i -> Exp i+    zero :: Exp i+    (plus, zero) =+      case integralType @(EltR i) of+        TypeInt{}    -> ((+), 0)+        TypeInt8{}   -> ((+), 0)+        TypeInt16{}  -> ((+), 0)+        TypeInt32{}  -> ((+), 0)+        TypeInt64{}  -> ((+), 0)+        TypeWord{}   -> ((+), 0)+        TypeWord8{}  -> ((+), 0)+        TypeWord16{} -> ((+), 0)+        TypeWord32{} -> ((+), 0)+        TypeWord64{} -> ((+), 0)++ -- Specialised reductions -- ---------------------- --@@ -753,14 +806,14 @@ and :: Shape sh     => Acc (Array (sh:.Int) Bool)     -> Acc (Array sh Bool)-and = fold (&&) (constant True)+and = fold (&&) True_  -- | Check if any element along the innermost dimension is 'True'. -- or :: Shape sh    => Acc (Array (sh:.Int) Bool)    -> Acc (Array sh Bool)-or = fold (||) (constant False)+or = fold (||) False_  -- | Compute the sum of elements along the innermost dimension of the array. To -- find the sum of the entire array, 'flatten' it first.@@ -931,33 +984,31 @@     -> Acc (Array (sh:.Int) e) scanlSeg f z arr seg =   if null arr || null flags-    then fill (lift (sh:.sz + length seg)) z+    then fill (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.+    -- This is done by 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)+    sh ::. sz = shape arr+    seg'      = map (+1) seg+    arr'      = permute const+                        (fill (sh ::. sz + length seg) z)+                        (\(sx ::. i) -> Just_ (sx ::. i + fromIntegral (inc ! I1 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+    flags     = mkHeadFlags seg+    inc       = scanl1 (+) flags   -- | Segmented version of 'scanl'' along the innermost dimension of an array. The@@ -1006,8 +1057,8 @@     -> 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)+    then T2 arr  (fill (indexTail (shape arr) ::. length seg) z)+    else T2 body sums   where     -- Segmented scan' is implemented by deconstructing a segmented exclusive     -- scan, to separate the final value and scan body.@@ -1026,9 +1077,8 @@     seg'        = map (+1) seg     tails       = zipWith (+) seg $ prescanl (+) 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)))+                    (indexTail (shape arr') ::. length seg)+                    (\(sz ::. i) -> sz ::. fromIntegral (tails ! I1 i))                     arr'      -- Slice out the body of each segment.@@ -1041,15 +1091,14 @@     --     offset      = scanl1 (+) seg     inc         = scanl1 (+)-                $ permute (+) (fill (index1 $ size arr + 1) 0)-                              (\ix -> index1' $ offset ! ix)+                $ permute (+) (fill (I1 $ size arr + 1) 0)+                              (\ix -> Just_ (index1' (offset ! ix)))                               (fill (shape seg) (1 :: Exp i)) -    len         = offset ! index1 (length offset - 1)+    len         = offset ! I1 (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)))+                    (indexTail (shape arr) ::. fromIntegral len)+                    (\(sz ::. i) -> sz ::. i + fromIntegral (inc ! I1 i))                     arr'  @@ -1093,7 +1142,7 @@     -> Acc (Array (sh:.Int) e) scanl1Seg f arr seg   = map snd-  . scanl1 (segmented f)+  . scanl1 (segmentedL f)   $ zip (replicate (lift (indexTail (shape arr) :. All)) (mkHeadFlags seg)) arr  -- |Segmented version of 'prescanl'.@@ -1156,10 +1205,10 @@     -> Acc (Array (sh:.Int) e) scanrSeg f z arr seg =   if null arr || null flags-    then fill (lift (sh :. sz + length seg)) z+    then fill (sh ::. sz + length seg) z     else scanr1Seg f arr' seg'   where-    sh :. sz    = unlift (shape arr) :: Exp sh :. Exp Int+    sh ::. sz    = shape arr      -- Using technique described for 'scanlSeg', where we intersperse the array     -- with the seed element at the start of each segment, and then perform an@@ -1170,9 +1219,8 @@      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))+                          (fill (sh ::. sz + length seg) z)+                          (\(sx ::. i) -> Just_ (sx ::. i + fromIntegral (inc !! i) - 1))                           (drop (sz - length flags) arr)  @@ -1216,8 +1264,8 @@     -> 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)+    then T2 arr  (fill (indexTail (shape arr) ::. length seg) z)+    else T2 body sums   where     -- Using technique described for scanl'Seg     --@@ -1227,18 +1275,16 @@     seg'        = map (+1) seg     heads       = prescanl (+) 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)))+                    (indexTail (shape arr') ::. length seg)+                    (\(sz ::.i) -> sz ::. fromIntegral (heads ! I1 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)))+                    (indexTail (shape arr) ::. indexHead (shape flags))+                    (\(sz ::. i) -> sz ::. i + fromIntegral (inc ! I1 i))                     arr'  @@ -1273,7 +1319,7 @@     -> Acc (Array (sh:.Int) e) scanr1Seg f arr seg   = map snd-  . scanr1 (flip (segmented f))+  . scanr1 (segmentedR f)   $ zip (replicate (lift (indexTail (shape arr) :. All)) (mkTailFlags seg)) arr  @@ -1307,7 +1353,7 @@ -- Segmented scan helpers -- ---------------------- --- |Compute head flags vector from segment vector for left-scans.+-- | 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@@ -1320,14 +1366,14 @@     -> Acc (Segments i) mkHeadFlags seg   = init-  $ permute (+) zeros (\ix -> index1' (offset ! ix)) ones+  $ permute (+) zeros (\ix -> Just_ (index1' (offset ! ix))) ones   where-    (offset, len)       = unlift (scanl' (+) 0 seg)-    zeros               = fill (index1' $ the len + 1) 0-    ones                = fill (index1  $ size offset) 1+    T2 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.+-- | 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)@@ -1335,29 +1381,31 @@     -> Acc (Segments i) mkTailFlags seg   = init-  $ permute (+) zeros (\ix -> index1' (the len - 1 - offset ! ix)) ones+  $ permute (+) zeros (\ix -> Just_ (index1' (the len - 1 - offset ! ix))) ones   where-    (offset, len)       = unlift (scanr' (+) 0 seg)-    zeros               = fill (index1' $ the len + 1) 0-    ones                = fill (index1  $ size offset) 1+    T2 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.+-- | 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+segmentedL     :: (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))+    -> (Exp (i, e) -> Exp (i, e) -> Exp (i, e))+segmentedL f (T2 aF aV) (T2 bF bV) =+  T2 (aF .|. bF)+     (bF /= 0 ? (bV, f aV bV)) --- |Index construction and destruction generalised to integral types.+segmentedR+    :: (Elt e, Num i, Bits i)+    => (Exp e -> Exp e -> Exp e)+    -> (Exp (i, e) -> Exp (i, e) -> Exp (i, e))+segmentedR f y x = segmentedL (flip f) x y++-- | 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,@@ -1380,10 +1428,10 @@ -- flatten :: forall sh e. (Shape sh, Elt e) => Acc (Array sh e) -> Acc (Vector e) flatten a-  | Just Refl <- matchShapeType (undefined::sh) (undefined::DIM1)+  | Just Refl <- matchShapeType @sh @DIM1   = a flatten a-  = reshape (index1 (size a)) a+  = reshape (I1 (size a)) a   -- Enumeration and filling@@ -1434,7 +1482,7 @@     -> Acc (Array sh e) enumFromStepN sh x y   = reshape sh-  $ generate (index1 $ shapeSize sh)+  $ generate (I1 (shapeSize sh))              (\ix -> (fromIntegral (unindex1 ix :: Exp Int) * y) + x)  -- Concatenation@@ -1475,7 +1523,7 @@ --     40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 12, 13, 14] -- infixr 5 ++-(++) :: forall sh e. (Slice sh, Shape sh, Elt e)+(++) :: (Shape sh, Elt e)      => Acc (Array (sh :. Int) e)      -> Acc (Array (sh :. Int) e)      -> Acc (Array (sh :. Int) e)@@ -1585,46 +1633,55 @@ -- >>> run $ 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)+filter :: (Shape sh, Elt e)        => (Exp e -> Exp Bool)        -> Acc (Array (sh:.Int) e)        -> Acc (Vector e, Array sh Int)-filter p arr+filter p arr = compact (map p arr) arr+{-# NOINLINE filter #-}+{-# RULES+  "ACC filter/filter" forall f g arr.+    filter f (afst (filter g arr)) = filter (\x -> g x && f x) arr+ #-}+++-- | As 'filter', but with separate arrays for the data elements and the+-- flags indicating which elements of that array should be kept.+--+compact :: forall sh e. (Shape sh, Elt e)+        => Acc (Array (sh:.Int) Bool)+        -> Acc (Array (sh:.Int) e)+        -> Acc (Vector e, Array sh Int)+compact keep arr   -- Optimise 1-dimensional arrays, where we can avoid additional computations   -- for the offset indices.-  | Just Refl <- matchShapeType (undefined::sh) (undefined::Z)+  | Just Refl <- matchShapeType @sh @Z   = let-        keep            = map p arr-        (target, len)   = unlift $ scanl' (+) 0 (map boolToInt keep)-        prj ix          = keep!ix ? ( index1 (target!ix), ignore )-        dummy           = fill (index1 (the len)) undef+        T2 target len   = scanl' (+) 0 (map boolToInt keep)+        prj ix          = if keep!ix+                             then Just_ (I1 (target!ix))+                             else Nothing_+        dummy           = fill (I1 (the len)) undef         result          = permute const dummy prj arr     in     if null arr-      then lift (emptyArray, fill (constant Z) 0)-      else lift (result, len)+      then T2 emptyArray (fill Z_ 0)+      else T2 result len -filter p arr+compact keep arr   = let         sz              = indexTail (shape arr)-        keep            = map p arr-        (target, len)   = unlift $ scanl' (+) 0 (map boolToInt keep)-        (offset, valid) = unlift $ scanl' (+) 0 (flatten len)+        T2 target len   = scanl' (+) 0 (map boolToInt keep)+        T2 offset valid = scanl' (+) 0 (flatten len)         prj ix          = if keep!ix-                            then index1 $ offset!index1 (toIndex sz (indexTail ix)) + target!ix-                            else ignore-        dummy           = fill (index1 (the valid)) undef+                            then Just_ (I1 (offset !! (toIndex sz (indexTail ix)) + target!ix))+                            else Nothing_+        dummy           = fill (I1 (the valid)) undef         result          = permute const dummy prj arr     in     if null arr-      then lift (emptyArray, fill sz 0)-      else lift (result, len)--{-# NOINLINE filter #-}-{-# RULES-  "ACC filter/filter" forall f g arr.-    filter f (afst (filter g arr)) = filter (\x -> g x && f x) arr- #-}+      then T2 emptyArray (fill sz 0)+      else T2 result len   -- Gather operations@@ -1699,8 +1756,8 @@     -> 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+    pf ix   = Just_ (I1 (to ! ix))+    input'  = backpermute (shape to `intersect` shape input) id input   -- | Conditionally overwrite elements of the destination by scattering values of@@ -1726,8 +1783,10 @@     -> Acc (Vector b) 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+    input'  = backpermute (shape to `intersect` shape input) id input+    pf ix   = if pred (maskV ! ix)+                 then Just_ (I1 (to ! ix))+                 else Nothing_   -- Permutations@@ -1867,7 +1926,7 @@ --     30, 31, 32, 33, 34, --     40, 41, 42, 43, 44] ---take :: forall sh e. (Slice sh, Shape sh, Elt e)+take :: (Shape sh, Elt e)      => Exp Int      -> Acc (Array (sh :. Int) e)      -> Acc (Array (sh :. Int) e)@@ -1894,7 +1953,7 @@ --     37, 38, 39, --     47, 48, 49] ---drop :: forall sh e. (Slice sh, Shape sh, Elt e)+drop :: (Shape sh, Elt e)      => Exp Int      -> Acc (Array (sh :. Int) e)      -> Acc (Array (sh :. Int) e)@@ -1920,7 +1979,7 @@ --     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)+init :: (Shape sh, Elt e)      => Acc (Array (sh :. Int) e)      -> Acc (Array (sh :. Int) e) init = initOn _1@@ -1946,7 +2005,7 @@ --     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)+tail :: (Shape sh, Elt e)      => Acc (Array (sh :. Int) e)      -> Acc (Array (sh :. Int) e) tail = tailOn _1@@ -1957,7 +2016,7 @@ -- -- > slit i n = take n . drop i ---slit :: forall sh e. (Slice sh, Shape sh, Elt e)+slit :: (Shape sh, Elt e)      => Exp Int                     -- ^ starting index      -> Exp Int                     -- ^ length      -> Acc (Array (sh :. Int) e)@@ -2137,17 +2196,6 @@ (?) :: 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. --@@ -2164,22 +2212,112 @@   ifThenElse = acond  +-- | The 'match' operation is the core operation which enables embedded+-- pattern matching. It is applied to an n-ary scalar function, and+-- generates the necessary case-statements in the embedded code for each+-- argument. For example, given the function:+--+-- > example1 :: Exp (Maybe Bool) -> Exp Int+-- > example1 Nothing_ = 0+-- > example1 (Just_ False_) = 1+-- > example1 (Just_ True_) = 2+--+-- In order to use this function it must be applied to the 'match'+-- operator:+--+-- > match example1+--+-- Using the infix-flip operator ('Data.Function.&'), we can also write+-- case statements inline. For example, instead of this:+--+-- > example2 x = case f x of+-- >   Nothing_ -> ...      -- error: embedded pattern synonym...+-- >   Just_ y  -> ...      -- ...used outside of 'match' context+--+-- This can be written instead as:+--+-- > example3 x = f x & match \case+-- >   Nothing_ -> ...+-- >   Just_ y  -> ...+--+-- And utilising the @LambdaCase@ and @BlockArguments@ syntactic extensions.+--+-- The Template Haskell splice 'Data.Array.Accelerate.mkPattern' (or+-- 'Data.Array.Accelerate.mkPatterns') can be used to generate the pattern+-- synonyms for a given Haskell'98 sum or product data type. For example:+--+-- > data Option a = None | Some a+-- >   deriving (Generic, Elt)+-- >+-- > mkPattern ''Option+--+-- Which can then be used such as:+--+-- > isNone :: Elt a => Exp (Option a) -> Exp Bool+-- > isNone = match \case+-- >   None_   -> True_+-- >   Some_{} -> False_+--+-- @since 1.4.0.0+--+match :: Matching f => f -> f+match f = mkFun (mkMatch f) id++data Args f where+  (:->)  :: Exp a -> Args b -> Args (Exp a -> b)+  Result :: Args (Exp a)++class Matching a where+  type ResultT a+  mkMatch :: a -> Args a -> Exp (ResultT a)+  mkFun   :: (Args f -> Exp (ResultT a))+          -> (Args a -> Args f)+          -> a++instance Elt a => Matching (Exp a) where+  type ResultT (Exp a) = a++  mkFun f k = f (k Result)+  mkMatch (Exp e) Result =+    case e of+      SmartExp (Match _ x) -> Exp x+      _                    -> Exp e++instance (Elt e, Matching r) => Matching (Exp e -> r) where+  type ResultT (Exp e -> r) = ResultT r++  mkFun f k x = mkFun f (\xs -> k (x :-> xs))+  mkMatch f (x@(Exp p) :-> xs) =+    case p of+      -- This first case is used when we have nested calls to 'match'+      SmartExp Match{} -> mkMatch (f x) xs++      -- If there is only a single alternative, we can elide the case+      -- statement at this point. This can occur when pattern matching on+      -- product types.+      _ -> case rhs of+             [(_,r)] -> Exp r+             _       -> Exp (SmartExp (Case p rhs))+    where+      rhs = [ (tag, unExp (mkMatch (f x') xs))+            | tag <- tagsR @e+            , let x' = Exp (SmartExp (Match tag p)) ]++ -- Scalar iteration -- ----------------  -- | Repeatedly apply a function a fixed number of times -- iterate-    :: forall a. Elt 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 (0, z))+  = let step (T2 i acc) = T2 (i+1) (f acc)+     in snd $ while (\v -> fst v < n) step (T2 0 z)   -- Scalar bulk operations@@ -2188,18 +2326,16 @@ -- | 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)+sfoldl :: (Shape 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 (0, z))+  = let n               = indexHead (shape xs)+        step (T2 i acc) = T2 (i+1) (acc `f` (xs ! (ix ::. i)))+     in snd $ while (\v -> fst v < n) step (T2 0 z)   -- Tuples@@ -2207,22 +2343,22 @@  -- |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+fst :: (Elt a, Elt b) => Exp (a, b) -> Exp a+fst (T2 a _) = a  -- |Extract the first component of an array pair. {-# NOINLINE[1] afst #-}-afst :: forall a b. (Arrays a, Arrays b) => Acc (a, b) -> Acc a-afst a = let (x, _::Acc b) = unlift a in x+afst :: (Arrays a, Arrays b) => Acc (a, b) -> Acc a+afst (T2 a _) = a  -- |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+snd :: (Elt a, Elt b) => Exp (a, b) -> Exp b+snd (T2 _ b) = b  -- | 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+asnd :: (Arrays a, Arrays b) => Acc (a, b) -> Acc b+asnd (T2 _ b) = b  -- |Converts an uncurried function to a curried function. --@@ -2256,7 +2392,7 @@ -- | Creates a rank-2 index from two Exp Int`s -- index2-    :: (Elt i, Slice (Z :. i))+    :: Elt i     => Exp i     -> Exp i     -> Exp (Z :. i :. i)@@ -2265,30 +2401,27 @@ -- | Destructs a rank-2 index to an Exp tuple of two Int`s. -- unindex2-    :: forall i. (Elt i, Slice (Z :. i))+    :: Elt 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)+unindex2 (Z_ ::. i ::. j) = T2 i j  -- | Create a rank-3 index from three Exp Int`s -- index3-    :: (Elt i, Slice (Z :. i), Slice (Z :. i :. i))+    :: Elt i     => Exp i     -> Exp i     -> Exp i     -> Exp (Z :. i :. i :. i)-index3 k j i = lift (Z :. k :. j :. i)+index3 k j i = 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))+    :: Elt 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)+unindex3 (Z_ ::. k ::. j ::. i) = T3 k j i   -- Array operations with a scalar result@@ -2312,9 +2445,108 @@ length = unindex1 . shape  +-- Operations to facilitate irregular data parallelism+-- ---------------------------------------------------++-- | A recipe for generating flattened implementations of some kinds of+-- irregular nested parallelism. Given two functions that:+--+--   (1) for each source element, determine how many target+--       elements it expands into; and+--+--   (2) computes a particular target element based on a source element and+--       the target element index associated with the source+--+-- The following example implements the Sieve of Eratosthenes,+-- a contraction style algorithm which first computes all primes less than+-- /sqrt n/, then uses this intermediate result to sieve away all numbers+-- in the range /[sqrt n .. n]/. The 'expand' function is used to calculate+-- and flatten the sieves. For each prime /p/ and upper limit /c2/,+-- function /sz/ computes the number of contributions in the sieve. Then,+-- for each prime /p/ and sieve index /i/, the function /get/ computes the+-- sieve contribution. The final step produces all the new primes in the+-- interval /[c1 .. c2]/.+--+-- >>> :{+--   primes :: Exp Int -> Acc (Vector Int)+--   primes n = afst loop+--     where+--       c0    = unit 2+--       a0    = use $ fromList (Z:.0) []+--       limit = truncate (sqrt (fromIntegral (n+1) :: Exp Float))+--       loop  = awhile+--                 (\(T2 _   c) -> map (< n+1) c)+--                 (\(T2 old c) ->+--                   let c1 = the c+--                       c2 = c1 < limit ? ( c1*c1, n+1 )+--                       --+--                       sieves =+--                         let sz p    = (c2 - p) `quot` p+--                             get p i = (2+i)*p+--                         in+--                         map (subtract c1) (expand sz get old)+--                       --+--                       new =+--                         let m     = c2-c1+--                             put i = let s = sieves ! i+--                                      in s >= 0 && s < m ? (Just_ (I1 s), Nothing_)+--                         in+--                         afst+--                           $ filter (> 0)+--                           $ permute const (enumFromN (I1 m) c1) put+--                           $ fill (shape sieves) 0+--                    in+--                    T2 (old ++ new) (unit c2))+--                 (T2 a0 c0)+-- :}+--+-- >>> run $ primes 100+-- Vector (Z :. 25) [2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97]+--+-- Inspired by the paper /Data-Parallel Flattening by Expansion/ by Martin+-- Elsman, Troels Henddriksen, and Niels Gustav Westphal Serup, ARRAY'19.+--+-- @since 1.4.0.0+--+expand :: (Elt a, Elt b)+       => (Exp a -> Exp Int)+       -> (Exp a -> Exp Int -> Exp b)+       -> Acc (Vector a)+       -> Acc (Vector b)+expand f g xs =+  let+      szs           = map f xs+      T2 offset len = scanl' (+) 0 szs+      m             = the len+  in+  if length xs == 0 || m == 0+     then use $ fromList (Z:.0) []+     else+      let+          n          = m + 1+          put ix     = Just_ (I1 (offset ! ix))++          head_flags :: Acc (Vector Int)+          head_flags = permute const (fill (I1 n) 0) put (fill (shape szs) 1)++          idxs       = map (subtract 1)+                     $ map snd+                     $ scanl1 (segmentedL (+))+                     $ zip head_flags+                     $ fill (I1 m) 1++          iotas      = map snd+                     $ scanl1 (segmentedL const)+                     $ zip head_flags+                     $ permute const (fill (I1 n) undef) put+                     $ enumFromN (shape xs) 0+      in+      zipWith g (gather iotas xs) idxs++ {-- -- Sequence operations--- --------------------------------------+-- -------------------  -- | Reduce a sequence by appending all the shapes and all the elements in two -- separate vectors.@@ -2364,29 +2596,20 @@ emptyArray = fill (constant empty) undef  -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-- -- Lenses -- ------ -- -- Imported from `lens-accelerate` (which provides more general Field instances) ---_1 :: forall sh. (Shape sh, Slice sh) => Lens' (Exp (sh:.Int)) (Exp Int)+_1 :: forall sh. Elt sh => Lens' (Exp (sh:.Int)) (Exp Int) _1 = lens (\ix   -> let _  :. x = unlift ix :: Exp sh :. Exp Int in x)           (\ix x -> let sh :. _ = unlift ix :: Exp sh :. Exp Int in lift (sh :. x)) -_2 :: forall sh. (Shape sh, Slice sh) => Lens' (Exp (sh:.Int:.Int)) (Exp Int)+_2 :: forall sh. Elt sh => Lens' (Exp (sh:.Int:.Int)) (Exp Int) _2 = lens (\ix   -> let _  :. y :. _ = unlift ix :: Exp sh :. Exp Int :. Exp Int in y)           (\ix y -> let sh :. _ :. x = unlift ix :: Exp sh :. Exp Int :. Exp Int in lift (sh :. y :. x)) -_3 :: forall sh. (Shape sh, Slice sh) => Lens' (Exp (sh:.Int:.Int:.Int)) (Exp Int)+_3 :: forall sh. Elt sh => Lens' (Exp (sh:.Int:.Int:.Int)) (Exp Int) _3 = lens (\ix   -> let _  :. z :. _ :. _ = unlift ix :: Exp sh :. Exp Int :. Exp Int :. Exp Int in z)           (\ix z -> let sh :. _ :. y :. x = unlift ix :: Exp sh :. Exp Int :. Exp Int :. Exp Int in lift (sh :. z :. y :. x)) 
src/Data/Array/Accelerate/Pretty.hs view
@@ -1,109 +1,187 @@+{-# LANGUAGE CPP                  #-}+{-# LANGUAGE FlexibleContexts     #-} {-# LANGUAGE FlexibleInstances    #-} {-# LANGUAGE GADTs                #-}+{-# LANGUAGE OverloadedStrings    #-} {-# LANGUAGE ScopedTypeVariables  #-}-{-# LANGUAGE TypeSynonymInstances #-}+{-# LANGUAGE TemplateHaskell      #-}+{-# LANGUAGE UndecidableInstances #-} {-# OPTIONS_GHC -fno-warn-orphans #-} {-# OPTIONS_HADDOCK hide #-} -- | -- Module      : Data.Array.Accelerate.Pretty--- Copyright   : [2008..2017] Manuel M T Chakravarty, Gabriele Keller---               [2009..2017] Trevor L. McDonell+-- Copyright   : [2008..2020] The Accelerate Team -- License     : BSD3 ----- Maintainer  : Trevor L. McDonell <tmcdonell@cse.unsw.edu.au>+-- Maintainer  : Trevor L. McDonell <trevor.mcdonell@gmail.com> -- Stability   : experimental -- Portability : non-portable (GHC extensions) --  module Data.Array.Accelerate.Pretty ( -  -- * Pretty printing functions-  module Data.Array.Accelerate.Pretty.Print,-  module Data.Array.Accelerate.Pretty.Graphviz,+  -- ** Pretty printing+  PrettyAcc, ExtractAcc,+  prettyPreOpenAcc,+  prettyPreOpenAfun,+  prettyOpenExp,+  prettyOpenFun, -  -- * Instances of Show+  -- ** Graphviz+  Graph,+  PrettyGraph(..), Detail(..),+  graphDelayedAcc, graphDelayedAfun,  ) where --- libraries+import Data.Array.Accelerate.AST                                    hiding ( Acc, Exp )+import Data.Array.Accelerate.Error+import Data.Array.Accelerate.Pretty.Graphviz+import Data.Array.Accelerate.Pretty.Print                           hiding ( Keyword(..) )+import Data.Array.Accelerate.Smart                                  ( Acc, Exp )+import Data.Array.Accelerate.Sugar.Array+import Data.Array.Accelerate.Sugar.Elt+import Data.Array.Accelerate.Trafo+import Data.Array.Accelerate.Trafo.Delayed++import Data.Maybe+import Data.Text.Prettyprint.Doc+import Data.Text.Prettyprint.Doc.Render.String+import Data.Text.Prettyprint.Doc.Render.Terminal+import System.Environment import System.IO import System.IO.Unsafe-import Text.PrettyPrint.ANSI.Leijen+import qualified Data.Text.Lazy                                     as T import qualified System.Console.ANSI                                as Term import qualified System.Console.Terminal.Size                       as Term --- friends-import Data.Array.Accelerate.AST-import Data.Array.Accelerate.Trafo.Base-import Data.Array.Accelerate.Pretty.Print-import Data.Array.Accelerate.Pretty.Graphviz+#if ACCELERATE_DEBUG+import Control.DeepSeq+import Data.Array.Accelerate.Debug.Flags+import Data.Array.Accelerate.Debug.Stats+#endif  --- Show--- ----+instance Arrays arrs => Show (Acc arrs) where+  show = withSimplStats . show . convertAcc --- Explicitly enumerate Show instances for the Accelerate array AST types. If we--- instead use a generic instance of the form:+instance Afunction (Acc a -> f) => Show (Acc a -> f) where+  show = withSimplStats . show . convertAfun++instance Elt e => Show (Exp e) where+  show = withSimplStats . show . convertExp++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+++-- Note: [Show instances] --+-- Explicitly enumerate Show instances for the Accelerate array AST types.+-- If we instead use a generic instance of the form:+-- --   instance Kit acc => Show (acc aenv a) where -- -- This matches any type of kind (* -> * -> *), which can cause problems -- interacting with other packages. See Issue #108. --+ instance PrettyEnv aenv => Show (OpenAcc aenv a) where-  showsPrec _ = renderForTerminal . pretty+  show = renderForTerminal . prettyOpenAcc context0 (prettyEnv (pretty 'a')) +instance PrettyEnv aenv => Show (OpenAfun aenv f) where+  show = renderForTerminal . prettyPreOpenAfun prettyOpenAcc (prettyEnv (pretty 'a'))+ instance PrettyEnv aenv => Show (DelayedOpenAcc aenv a) where-  showsPrec _ = renderForTerminal . pretty+  show = renderForTerminal . prettyDelayedOpenAcc context0 (prettyEnv (pretty 'a')) --- These parameterised instances are fine because there is a concrete kind------ 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-  showsPrec _ = renderForTerminal . pretty+instance PrettyEnv aenv => Show (DelayedOpenAfun aenv f) where+  show = renderForTerminal . prettyPreOpenAfun prettyDelayedOpenAcc (prettyEnv (pretty 'a')) -instance (Kit acc, PrettyEnv env, PrettyEnv aenv) => Show (PreOpenFun acc env aenv f) where-  showsPrec _ = renderForTerminal . pretty+instance (PrettyEnv env, PrettyEnv aenv) => Show (OpenExp env aenv e) where+  show = renderForTerminal . prettyOpenExp context0 (prettyEnv (pretty 'x')) (prettyEnv (pretty 'a')) -instance (Kit acc, PrettyEnv env, PrettyEnv aenv) => Show (PreOpenExp acc env aenv t) where-  showsPrec _ = renderForTerminal . pretty+instance (PrettyEnv env, PrettyEnv aenv) => Show (OpenFun env aenv e) where+  show = renderForTerminal . prettyOpenFun (prettyEnv (pretty 'x')) (prettyEnv (pretty 'a')) --- instance Kit acc => Show (PreOpenSeq acc aenv senv t) where---   show s = renderForTerminal wide $ sep $ punctuate (text ";") $ prettySeq prettyAcc 0 0 noParens s -renderForTerminal :: Doc -> ShowS-renderForTerminal doc next =-  unsafePerformIO $ do-    term <- Term.size-    ansi <- Term.hSupportsANSI stdout-    let-        w             = maybe 120 Term.width term-        d | ansi      = doc-          | otherwise = plain doc-        f | w <= 100  = 0.7-          | w <= 120  = 0.6-          | otherwise = 0.5-    ---    return $ displayS (renderSmart f w d) next+-- Internals+-- --------- --- Pretty--- ------+renderForTerminal :: Adoc  -> String+renderForTerminal = render . layoutSmart terminalLayoutOptions+  where+    fancy = terminalSupportsANSI && terminalColourAllowed+    render+      | fancy     = T.unpack . renderLazy . reAnnotateS ansiKeyword+      | otherwise = renderString -instance PrettyEnv aenv => Pretty (OpenAcc aenv a) where-  pretty c = prettyAcc noParens prettyEnv c+{-# NOINLINE terminalColourAllowed #-}+terminalColourAllowed :: Bool+terminalColourAllowed = unsafePerformIO $ isNothing <$> lookupEnv "NO_COLOR" -instance PrettyEnv aenv => Pretty (DelayedOpenAcc aenv a) where-  pretty c = prettyAcc noParens prettyEnv c+{-# NOINLINE terminalSupportsANSI #-}+terminalSupportsANSI :: Bool+terminalSupportsANSI = unsafePerformIO $ Term.hSupportsANSI stdout -instance (Kit acc, PrettyEnv aenv) => Pretty (PreOpenAfun acc aenv f) where-  pretty f = prettyPreOpenAfun prettyAcc prettyEnv f+{-# NOINLINE terminalLayoutOptions #-}+terminalLayoutOptions :: LayoutOptions+terminalLayoutOptions+  = unsafePerformIO+  $ do term <- Term.size+       return $ case term of+                  Nothing -> defaultLayoutOptions+                  Just t  -> LayoutOptions { layoutPageWidth = AvailablePerLine (min w 120) f }+                    where+                      w = Term.width t+                      f | w <= 80   = 1+                        | w <= 100  = 0.9+                        | otherwise = 0.8 -instance (Kit acc, PrettyEnv env, PrettyEnv aenv) => Pretty (PreOpenFun acc env aenv f) where-  pretty f = prettyPreOpenFun prettyAcc prettyEnv prettyEnv f+prettyOpenAcc :: PrettyAcc OpenAcc+prettyOpenAcc context aenv (OpenAcc pacc) =+  prettyPreOpenAcc context prettyOpenAcc extractOpenAcc aenv pacc -instance (Kit acc, PrettyEnv env, PrettyEnv aenv) => Pretty (PreOpenExp acc env aenv t) where-  pretty e = prettyPreOpenExp prettyAcc noParens prettyEnv prettyEnv e+extractOpenAcc :: OpenAcc aenv a -> PreOpenAcc OpenAcc aenv a+extractOpenAcc (OpenAcc pacc) = pacc+++prettyDelayedOpenAcc :: HasCallStack => PrettyAcc DelayedOpenAcc+prettyDelayedOpenAcc context aenv (Manifest pacc)+  = prettyPreOpenAcc context prettyDelayedOpenAcc extractDelayedOpenAcc aenv pacc+prettyDelayedOpenAcc _       aenv (Delayed _ sh f _)+  = parens+  $ nest shiftwidth+  $ sep [ delayed "delayed"+        ,          prettyOpenExp app Empty aenv sh+        , parens $ prettyOpenFun     Empty aenv f+        ]++extractDelayedOpenAcc :: HasCallStack => DelayedOpenAcc aenv a -> PreOpenAcc DelayedOpenAcc aenv a+extractDelayedOpenAcc (Manifest pacc) = pacc+extractDelayedOpenAcc Delayed{}       = internalError "expected manifest array"+++-- Debugging+-- ---------++-- Attach simplifier statistics to the tail of the given string. Since the+-- statistics rely on fully evaluating the expression this is difficult to do+-- generally (without an additional deepseq), but easy enough for our show+-- instances.+--+-- For now, we just reset the statistics at the beginning of a conversion, and+-- leave it to a backend to choose an appropriate moment to dump the summary.+--+withSimplStats :: String -> String+#ifdef ACCELERATE_DEBUG+withSimplStats x = unsafePerformIO $ do+  when dump_simpl_stats $ x `deepseq` dumpSimplStats+  return x+#else+withSimplStats x = x+#endif 
src/Data/Array/Accelerate/Pretty/Graphviz.hs view
@@ -6,16 +6,16 @@ {-# LANGUAGE RankNTypes           #-} {-# LANGUAGE RecordWildCards      #-} {-# LANGUAGE ScopedTypeVariables  #-}-{-# LANGUAGE TemplateHaskell      #-} {-# LANGUAGE TupleSections        #-}+{-# LANGUAGE TypeApplications     #-} {-# LANGUAGE TypeSynonymInstances #-} {-# LANGUAGE ViewPatterns         #-} -- | -- Module      : Data.Array.Accelerate.Pretty.Graphviz--- Copyright   : [2015..2017] Manuel M T Chakravarty, Gabriele Keller, Trevor L. McDonell+-- Copyright   : [2015..2020] The Accelerate Team -- License     : BSD3 ----- Maintainer  : Trevor L. McDonell <tmcdonell@cse.unsw.edu.au>+-- Maintainer  : Trevor L. McDonell <trevor.mcdonell@gmail.com> -- Stability   : experimental -- Portability : non-portable (GHC extensions) --@@ -28,28 +28,34 @@  ) where --- standard libraries+import Data.Array.Accelerate.AST+import Data.Array.Accelerate.AST.Idx+import Data.Array.Accelerate.AST.LeftHandSide+import Data.Array.Accelerate.AST.Var+import Data.Array.Accelerate.Analysis.Match+import Data.Array.Accelerate.Error+import Data.Array.Accelerate.Pretty.Graphviz.Monad+import Data.Array.Accelerate.Pretty.Graphviz.Type+import Data.Array.Accelerate.Pretty.Print               hiding ( Keyword(..) )+import Data.Array.Accelerate.Representation.Array+import Data.Array.Accelerate.Representation.Stencil+import Data.Array.Accelerate.Representation.Type+import Data.Array.Accelerate.Sugar.Foreign+import Data.Array.Accelerate.Trafo.Delayed+import Data.Array.Accelerate.Trafo.Substitution+ import Control.Applicative                              hiding ( Const, empty ) import Control.Arrow                                    ( (&&&) ) import Control.Monad.State                              ( modify, gets, state ) import Data.HashSet                                     ( HashSet )-import Data.List+import Data.List                                        ( nub, partition ) import Data.Maybe+import Data.String+import Data.Text.Prettyprint.Doc import System.IO.Unsafe                                 ( unsafePerformIO )-import Text.PrettyPrint.ANSI.Leijen                     hiding ( (<$>), parens ) import Prelude                                          hiding ( exp )-import qualified Data.Sequence                          as Seq import qualified Data.HashSet                           as Set-import qualified Text.PrettyPrint.ANSI.Leijen           as PP---- friends-import Data.Array.Accelerate.AST                        ( PreOpenAcc(..), PreOpenAfun(..), PreOpenFun(..), PreOpenExp(..), PreBoundary(..), Idx(..) )-import Data.Array.Accelerate.Array.Sugar                ( Array, Shape, Elt, Tuple(..), Atuple(..), arrays, toElt, strForeign )-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+import qualified Data.Sequence                          as Seq   -- Configuration options@@ -76,14 +82,11 @@ -- avalToVal :: Aval aenv -> Val aenv avalToVal Aempty           = Empty-avalToVal (Apush aenv _ v) = Push (avalToVal aenv) (text v)+avalToVal (Apush aenv _ v) = Push (avalToVal aenv) (pretty 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@@ -106,7 +109,7 @@  -- Add [T|F] ports underneath the given tree. ---mkTF :: Tree (Maybe Port, Doc) -> Tree (Maybe Port, Doc)+mkTF :: Tree (Maybe Port, Adoc) -> Tree (Maybe Port, Adoc) mkTF this =   Forest [ this          , Forest [ Leaf (Just "T", "T")@@ -142,20 +145,20 @@ -- | Generate a dependency graph for the given computation -- {-# NOINLINE graphDelayedAcc #-}-graphDelayedAcc :: Detail -> DelayedAcc a -> Graph+graphDelayedAcc :: HasCallStack => 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 :: HasCallStack => 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"+      _                                  -> internalError "unexpected error"   -- Pretty-printing data-dependency graphs@@ -164,16 +167,17 @@ -- 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)]+data PDoc  = PDoc Adoc [Vertex]+data PNode = PNode NodeId (Tree (Maybe Port, Adoc)) [(Vertex, Maybe Port)]  graphDelayedOpenAcc-    :: Detail+    :: HasCallStack+    => Detail     -> Aval aenv     -> DelayedOpenAcc aenv a     -> Dot Graph graphDelayedOpenAcc detail aenv acc = do-  r <- prettyDelayedOpenAcc detail noParens aenv acc+  r <- prettyDelayedOpenAcc detail context0 aenv acc   i <- mkNodeId r   v <- mkNode r Nothing   _ <- mkNode (PNode i (Leaf (Nothing,"result")) [(Vertex v Nothing, Nothing)]) Nothing@@ -182,21 +186,21 @@ -- Generate a graph for the given term. -- prettyDelayedOpenAcc-    :: forall aenv arrs.-       Detail                               -- simplified output: only print operator name-    -> (Doc -> Doc)+    :: forall aenv arrs. HasCallStack+    => Detail                               -- simplified output: only print operator name+    -> Context     -> Aval aenv     -> DelayedOpenAcc aenv arrs     -> Dot PNode-prettyDelayedOpenAcc _      _    _    Delayed{}            = $internalError "prettyDelayedOpenAcc" "expected manifest array"-prettyDelayedOpenAcc detail wrap aenv atop@(Manifest pacc) =+prettyDelayedOpenAcc _      _   _    Delayed{}            = internalError "expected manifest array"+prettyDelayedOpenAcc detail ctx 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+    Alet lhs bnd body       -> do+      bnd'@(PNode ident _ _) <- prettyDelayedOpenAcc detail context0 aenv bnd+      (aenv1, a) <- prettyLetALeftHandSide ident aenv lhs+      _ <- mkNode bnd' (Just a)+      body' <- prettyDelayedOpenAcc detail context0 aenv1 body       return body'      Acond p t e             -> do@@ -209,63 +213,62 @@           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+    Apply _ afun acc         -> apply <$> prettyDelayedAfun    detail     aenv afun+                                      <*> prettyDelayedOpenAcc detail ctx aenv acc -    Awhile p f x            -> do+    Awhile p f x             -> do       ident <- mkNodeId atop-      x'    <- replant =<< prettyDelayedOpenAcc detail parens aenv x+      x'    <- replant =<< prettyDelayedOpenAcc detail app aenv x       p'    <- prettyDelayedAfun detail aenv p       f'    <- prettyDelayedAfun detail aenv f       --       let PNode _ (Leaf (Nothing,xb)) fvs = x'-          loop                            = wrap $ hang 2 (sep ["awhile", text p', text f', xb ])+          loop                            = nest 2 (sep ["awhile", pretty p', pretty 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 (prettyTupleIdx ix <+> nest 2 d))) deps+    a@(Apair a1 a2)          -> mkNodeId a >>= prettyDelayedApair detail aenv a1 a2 -    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 bndy, ppA xs ]-    Stencil2 sten bndy1 acc1 bndy2 acc2-                            -> "stencil2"    .$ [ ppF sten, ppB bndy1, ppA acc1, ppB bndy2, ppA acc2 ]-    Aforeign ff _afun xs    -> "aforeign"    .$ [ return (PDoc (text (strForeign ff)) []), {- ppAf afun, -} ppA xs ]+    Anil                     -> "()"             .$ []++    Use repr arr             -> "use"            .$ [ return $ PDoc (prettyArray repr arr) [] ]+    Unit _ e                 -> "unit"           .$ [ ppE e ]+    Generate _ sh f          -> "generate"       .$ [ ppE sh, ppF f ]+    Transform _ sh ix f xs   -> "transform"      .$ [ ppE sh, ppF ix, ppF f, ppA xs ]+    Reshape _ sh xs          -> "reshape"        .$ [ ppE sh, ppA xs ]+    Replicate _ty ix xs      -> "replicate"      .$ [ ppE ix, ppA xs ]+    Slice _ty xs ix          -> "slice"          .$ [ ppA xs, ppE ix ]+    Map _ f xs               -> "map"            .$ [ ppF f, ppA xs ]+    ZipWith _ f xs ys        -> "zipWith"        .$ [ ppF f, ppA xs, ppA ys ]+    Fold f (Just z) a        -> "fold"           .$ [ ppF f,  ppE z, ppA a ]+    Fold f Nothing  a        -> "fold1"          .$ [ ppF f,  ppA a ]+    FoldSeg _ f (Just z) a s -> "foldSeg"        .$ [ ppF f,  ppE z, ppA a, ppA s ]+    FoldSeg _ f Nothing  a s -> "fold1Seg"       .$ [ ppF f,  ppA a, ppA s ]+    Scan d f (Just z) a      -> ppD "scan" d ""  .$ [ ppF f,  ppE z, ppA a ]+    Scan d f Nothing  a      -> ppD "scan" d "1" .$ [ ppF f,  ppA a ]+    Scan' d f z a            -> ppD "scan" d "'" .$ [ ppF f,  ppE z, ppA a ]+    Permute f dfts p xs      -> "permute"        .$ [ ppF f, ppA dfts, ppF p, ppA xs ]+    Backpermute _ sh p xs    -> "backpermute"    .$ [ ppE sh, ppF p, ppA xs ]+    Stencil s _ sten bndy xs -> "stencil"        .$ [ ppF sten, ppB (stencilEltR s) bndy, ppA xs ]+    Stencil2 s1 s2 _ sten bndy1 acc1 bndy2 acc2+                            -> "stencil2"        .$ [ ppF sten, ppB (stencilEltR s1) bndy1, ppA acc1, ppB (stencilEltR s2) bndy2, ppA acc2 ]+    Aforeign _ ff _afun xs  -> "aforeign"        .$ [ return (PDoc (pretty (strForeign ff)) []), {- ppAf afun, -} ppA xs ]     -- Collect{}               -> error "Collect"    where-    (.$) :: String -> [Dot PDoc] -> Dot PNode+    (.$) :: Operator -> [Dot PDoc] -> Dot PNode     name .$ docs = pnode =<< fmt name docs -    fmt :: String -> [Dot PDoc] -> Dot PDoc+    fmt :: Operator -> [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 2 (sep [text name, if simple detail then empty else sep args]))-                    (concat fvs)+          doc  = if simple detail+                   then manifest name+                   else parensIf (needsParens ctx name)+                      $ nest shiftwidth+                      $ sep ( manifest name : args )+      return $ PDoc doc (concat fvs)      pnode :: PDoc -> Dot PNode     pnode (PDoc doc vs) = do@@ -275,80 +278,76 @@      -- Free variables     ---    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+    fvF :: Fun aenv t -> [Vertex]+    fvF = fvOpenFun Empty aenv -    fvE :: DelayedExp aenv t -> [Vertex]-    fvE = fvPreOpenExp fvA Empty aenv+    fvE :: Exp aenv t -> [Vertex]+    fvE = fvOpenExp Empty aenv      -- Pretty-printing     ---    avar :: Idx aenv t -> PDoc-    avar ix = let (ident, v) = aprj ix aenv-              in  PDoc (text v) [Vertex ident Nothing]+    avar :: ArrayVar aenv t -> PDoc+    avar (Var _ ix) = let (ident, v) = aprj ix aenv+                      in  PDoc (pretty v) [Vertex ident Nothing]      aenv' :: Val aenv     aenv' = avalToVal aenv -    ppA :: DelayedOpenAcc aenv a -> Dot PDoc+    ppA :: HasCallStack => 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+      acc'  <- prettyDelayedOpenAcc detail app 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 (pretty v) [Vertex ident Nothing]+    ppA (Delayed _ sh f _)+      | Shape a    <- sh                   -- identical shape+      , Just b     <- isIdentityIndexing f -- function is `\ix -> b ! ix`+      , Just Refl  <- matchVar a b         -- function thus is `\ix -> a ! ix`+      = ppA $ Manifest $ Avar a+    ppA (Delayed _ sh f _) = do+      PDoc d v <- "Delayed" `fmt` [ ppE sh, ppF f ]       return    $ PDoc (parens d) v -    ppB :: forall sh e. (Shape sh, Elt e)-        => PreBoundary DelayedOpenAcc aenv (Array sh e)+    ppB :: forall sh e. HasCallStack+        => TypeR e+        -> Boundary aenv (Array sh 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))) [])-    ppB (Function f) = ppF f+    ppB _  Clamp        = return (PDoc "clamp"  [])+    ppB _  Mirror       = return (PDoc "mirror" [])+    ppB _  Wrap         = return (PDoc "wrap"   [])+    ppB tp (Constant e) = return (PDoc (prettyConst tp e) [])+    ppB _  (Function f) = ppF f -    ppF :: DelayedFun aenv t -> Dot PDoc-    ppF = return . uncurry PDoc . (parens . prettyDelayedFun aenv' &&& fvF)+    ppF :: HasCallStack => Fun aenv t -> Dot PDoc+    ppF = return . uncurry PDoc . (parens . prettyFun aenv' &&& fvF) -    ppE :: DelayedExp aenv t -> Dot PDoc-    ppE = return . uncurry PDoc . (prettyDelayedExp parens aenv' &&& fvE)+    ppE :: HasCallStack => Exp aenv t -> Dot PDoc+    ppE = return . uncurry PDoc . (prettyExp aenv' &&& fvE) -    ppSh :: DelayedExp aenv sh -> Dot PDoc-    ppSh = return . uncurry PDoc . (parens . prettyDelayedExp noParens aenv' &&& fvE)+    ppD :: String -> Direction -> String -> Operator+    ppD f LeftToRight k = fromString (f <> "l" <> k)+    ppD f RightToLeft k = fromString (f <> "r" <> k) -    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+    lift :: HasCallStack => DelayedOpenAcc aenv a -> Dot Vertex+    lift Delayed{}                    = internalError "expected manifest array"+    lift (Manifest (Avar (Var _ ix))) = return $ Vertex (fst (aprj ix aenv)) Nothing+    lift acc                          = do+      acc'  <- prettyDelayedOpenAcc detail context0 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)+                 Leaf (p,d) -> Leaf (p, pretty f <+> d)+                 Forest ts  -> Forest (Leaf (Nothing,pretty f) : ts)       in       PNode ident x' vs -    parens :: Doc -> Doc-    parens = PP.parens . align - -- 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.@@ -361,14 +360,15 @@ -- otherwise the referenced node will be drawn inside of the subgraph. -- prettyDelayedAfun-    :: Detail+    :: HasCallStack+    => 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)+  let label         = "afun" <> fromString (show (n+1))       outer         = collect aenv       (lifted,ss')  =         flip partition ss $ \s ->@@ -383,38 +383,66 @@   where     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+    go aenv' (Alam lhs f) = do+      aenv'' <- prettyLambdaALeftHandSide aenv' lhs+      go aenv'' f      collect :: Aval aenv' -> HashSet NodeId     collect Aempty        = Set.empty     collect (Apush a i _) = Set.insert i (collect a) +prettyLetALeftHandSide+    :: forall repr aenv aenv'. HasCallStack+    => NodeId+    -> Aval aenv+    -> ALeftHandSide repr aenv aenv'+    -> Dot (Aval aenv', Label)+prettyLetALeftHandSide _     aenv (LeftHandSideWildcard repr) = return (aenv, doc)+  where+    doc = case repr of+      TupRunit -> "()"+      _        -> "_"+prettyLetALeftHandSide ident aenv (LeftHandSideSingle _) = do+  a <- mkLabel+  return (Apush aenv ident a, a)+prettyLetALeftHandSide ident aenv (LeftHandSidePair lhs1 lhs2) = do+  (aenv1, d1) <- prettyLetALeftHandSide ident aenv  lhs1+  (aenv2, d2) <- prettyLetALeftHandSide ident aenv1 lhs2+  return (aenv2, "(" <> d1 <> ", " <> d2 <> ")") +prettyLambdaALeftHandSide+    :: forall repr aenv aenv'. HasCallStack+    => Aval aenv+    -> ALeftHandSide repr aenv aenv'+    -> Dot (Aval aenv')+prettyLambdaALeftHandSide aenv (LeftHandSideWildcard _) = return aenv+prettyLambdaALeftHandSide aenv lhs@(LeftHandSideSingle _) = do+  a     <- mkLabel+  ident <- mkNodeId lhs+  _     <- mkNode (PNode ident (Leaf (Nothing, pretty a)) []) Nothing+  return $ Apush aenv ident a+prettyLambdaALeftHandSide aenv (LeftHandSidePair lhs1 lhs2) = do+  aenv1 <- prettyLambdaALeftHandSide aenv lhs1+  prettyLambdaALeftHandSide aenv1 lhs2+ -- Display array tuples. This is a little tricky... ---prettyDelayedAtuple-    :: forall aenv atup.-       Detail-    -> (Doc -> Doc)+prettyDelayedApair+    :: forall aenv a1 a2. HasCallStack+    => Detail     -> Aval aenv-    -> Atuple (DelayedOpenAcc aenv) atup+    -> DelayedOpenAcc aenv a1+    -> DelayedOpenAcc aenv a2+    -> NodeId     -> 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)+prettyDelayedApair detail aenv a1 a2 ident = do+  PNode id1 t1 v1 <- prettyElem a1+  PNode id2 t2 v2 <- prettyElem a2+  modify $ \s -> s { dotEdges = fmap (redirect ident [id1, id2]) (dotEdges s) }+  return $ PNode ident (forest [t1, t2]) (v1 ++ v2)   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'+    prettyElem :: DelayedOpenAcc aenv a -> Dot PNode+    prettyElem a = replant =<< prettyDelayedOpenAcc detail context0 aenv a      -- Redirect any edges that pointed into one of the nodes now part of this     -- tuple, to instead point to the container node.@@ -427,7 +455,7 @@     -- 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 :: [Tree (Maybe Port, Adoc)] -> Tree (Maybe Port, Adoc)     forest leaves = Leaf (Nothing, tupled [ align d | Leaf (Nothing,d) <- leaves ])  @@ -442,7 +470,7 @@       vacuous <- mkNodeId pnode       a       <- mkLabel       _       <- mkNode pnode (Just a)-      return   $ PNode vacuous (Leaf (Nothing, text a)) [(Vertex ident Nothing, Nothing)]+      return   $ PNode vacuous (Leaf (Nothing, pretty a)) [(Vertex ident Nothing, Nothing)]   -- Pretty printing scalar functions and expressions@@ -454,43 +482,6 @@ -- 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 -- ----------------- --@@ -499,61 +490,56 @@ -- nodes (vertices) into the current term. -- -type FVAcc acc = forall aenv a. Aval aenv -> acc aenv a -> [Vertex]+fvAvar :: Aval aenv -> ArrayVar aenv a -> [Vertex]+fvAvar env (Var _ ix) = [ Vertex (fst $ aprj ix env) Nothing ] -fvPreOpenFun-    :: forall acc env aenv fun.-       FVAcc acc-    -> Val env+fvOpenFun+    :: forall env aenv fun.+       Val env     -> Aval aenv-    -> PreOpenFun acc env aenv fun+    -> OpenFun 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+fvOpenFun env aenv (Body b)    = fvOpenExp env  aenv b+fvOpenFun env aenv (Lam lhs f) = fvOpenFun env' aenv f+      where+        (env', _) = prettyELhs True env lhs -fvPreOpenExp-    :: forall acc env aenv exp.-       FVAcc acc-    -> Val env+fvOpenExp+    :: forall env aenv exp.+       Val env     -> Aval aenv-    -> PreOpenExp acc env aenv exp+    -> OpenExp env aenv exp     -> [Vertex]-fvPreOpenExp fvA env aenv = fv+fvOpenExp 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+    fvF :: OpenFun env aenv f -> [Vertex]+    fvF = fvOpenFun 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 :: OpenExp env aenv e -> [Vertex]+    fv (Shape acc)              = if cfgIncludeShape then fvAvar aenv acc else []+    fv (Index acc i)            = concat [ fvAvar aenv acc, fv i ]+    fv (LinearIndex acc i)      = concat [ fvAvar 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 Undef                    = []+    fv (Let lhs e1 e2)          = concat [ fv e1, fvOpenExp env' aenv e2 ]+      where+        (env', _) = prettyELhs False env lhs+    fv Evar{}                   = []+    fv Undef{}                  = []     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 (Pair e1 e2)             = concat [ fv e1, fv e2]+    fv Nil                      = []+    fv (VecPack   _ e)          = fv e+    fv (VecUnpack _ e)          = fv e     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 (ToIndex _ sh ix)        = concat [ fv sh, fv ix ]+    fv (FromIndex _ sh ix)      = concat [ fv sh, fv ix ]+    fv (ShapeSize _ sh)         = fv sh     fv Foreign{}                = []+    fv (Case e rhs def)         = concat [ fv e, concat [ fv c | (_,c) <- rhs ], maybe [] fv def ]     fv (Cond p t e)             = concat [ fv p, fv t, fv e ]     fv (While p f x)            = concat [ fvF p, fvF f, fv x ]-    fv (Coerce e)               = fv e+    fv (Coerce _ _ e)           = fv e 
src/Data/Array/Accelerate/Pretty/Graphviz/Monad.hs view
@@ -1,10 +1,11 @@-{-# LANGUAGE RecordWildCards #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE RecordWildCards   #-} -- | -- Module      : Data.Array.Accelerate.Pretty.Graphviz.Monad--- Copyright   : [2015..2017] Manuel M T Chakravarty, Gabriele Keller, Trevor L. McDonell+-- Copyright   : [2015..2020] The Accelerate Team -- License     : BSD3 ----- Maintainer  : Trevor L. McDonell <tmcdonell@cse.unsw.edu.au>+-- Maintainer  : Trevor L. McDonell <trevor.mcdonell@gmail.com> -- Stability   : experimental -- Portability : non-portable (GHC extensions) --@@ -18,6 +19,7 @@ import System.Mem.StableName import Prelude import qualified Data.Sequence                          as Seq+import qualified Data.Text                              as Text  import Data.Array.Accelerate.Pretty.Graphviz.Type @@ -50,7 +52,7 @@ mkLabel :: Dot Label mkLabel = state $ \s ->   let n = fresh s-  in  ( 'a' : show n, s { fresh = n + 1 } )+  in  ( Text.pack ('a' : show n), s { fresh = n + 1 } )  mkNodeId :: a -> Dot NodeId mkNodeId node = do@@ -60,7 +62,7 @@ mkGraph :: Dot Graph mkGraph =   state $ \DotState{..} ->-    ( Graph [] (toList $ fmap N dotNodes Seq.>< fmap E dotEdges Seq.>< fmap G dotGraph)+    ( Graph mempty (toList $ fmap N dotNodes Seq.>< fmap E dotEdges Seq.>< fmap G dotGraph)     , emptyState { fresh = fresh }     ) 
src/Data/Array/Accelerate/Pretty/Graphviz/Type.hs view
@@ -1,11 +1,12 @@+{-# LANGUAGE OverloadedStrings  #-} {-# LANGUAGE StandaloneDeriving #-} {-# LANGUAGE ViewPatterns       #-} -- | -- Module      : Data.Array.Accelerate.Pretty.Graphviz.Type--- Copyright   : [2015..2017] Manuel M T Chakravarty, Gabriele Keller, Trevor L. McDonell+-- Copyright   : [2015..2020] The Accelerate Team -- License     : BSD3 ----- Maintainer  : Trevor L. McDonell <tmcdonell@cse.unsw.edu.au>+-- Maintainer  : Trevor L. McDonell <trevor.mcdonell@gmail.com> -- Stability   : experimental -- Portability : non-portable (GHC extensions) --@@ -15,12 +16,16 @@ module Data.Array.Accelerate.Pretty.Graphviz.Type   where -import Data.Maybe import Data.Hashable+import Data.Maybe+import Data.Text                                          ( Text )+import Data.Text.Prettyprint.Doc import Text.Printf-import Text.PrettyPrint.ANSI.Leijen+import qualified Data.Text                                as Text +import Data.Array.Accelerate.Pretty.Print                 ( Adoc, Keyword ) + -- Rose tree, with all information at the leaves. -- data Tree a = Leaf a@@ -36,17 +41,11 @@ data Graph      = Graph Label [Statement] data Statement  = N Node | E Edge | G Graph -data Node       = Node (Maybe Label) NodeId (Tree (Maybe Port, Doc))+data Node       = Node (Maybe Label) NodeId (Tree (Maybe Port, Adoc)) 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+type Label      = Text+type Port       = Text  data Vertex     = Vertex NodeId (Maybe Port) data Edge       = Edge {- from -} Vertex@@ -61,55 +60,54 @@ instance Show Graph where   show = show . ppGraph - -- Pretty print a (directed) graph to dot format ---ppGraph :: Graph -> Doc+ppGraph :: Graph -> Adoc ppGraph (Graph l ss) =-  vcat [ text "digraph" <+> text l <+> lbrace+  vcat [ "digraph" <+> pretty l <+> lbrace        , nest 4 $ vcat                 $ punctuate semi-                $ text "graph [compound=true]"-                : text "node  [shape=record,fontsize=10]"+                $ "graph [compound=true]"+                : "node  [shape=record,fontsize=10]"                 : map ppStatement ss        , rbrace        ] -ppSubgraph :: Graph -> Doc+ppSubgraph :: Graph -> Adoc ppSubgraph (Graph l ss) =-  vcat [ text "subgraph cluster_" <> text l <+> lbrace+  vcat [ "subgraph cluster_" <> pretty l <+> lbrace        , nest 4 $ vcat                 $ punctuate semi-                $ text "label" <> equals <> text l+                $ "label" <> equals <> pretty l                 : map ppStatement ss        , rbrace        ] -ppStatement :: Statement -> Doc+ppStatement :: Statement -> Adoc 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+ppEdge :: Edge -> Adoc+ppEdge (Edge from to) = ppVertex from <+> "->" <+> ppVertex to -ppVertex :: Vertex -> Doc-ppVertex (Vertex n p) = ppNodeId n <> maybe empty (colon<>) (fmap text p)+ppVertex :: Vertex -> Adoc+ppVertex (Vertex n p) = ppNodeId n <> maybe mempty (colon<>) (fmap pretty p) -ppNode :: Node -> Doc+ppNode :: Node -> Adoc ppNode (Node label nid body) =   hcat [ ppNodeId nid        , brackets        $ hcat        $ punctuate comma-       $ catMaybes [ fmap ((\x -> text "xlabel" <> equals <> x) . dquotes . text) label-                   , Just (       text "label"  <> equals <>      dquotes (ppNodeTree body))+       $ catMaybes [ fmap ((\x -> "xlabel" <> equals <> x) . dquotes . pretty) label+                   , Just (       "label"  <> equals <>      dquotes (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+ppNodeTree :: Tree (Maybe Port, Adoc) -> Adoc+ppNodeTree (Forest trees)      = braces $ hcat (punctuate (pretty '|') (map ppNodeTree trees))+ppNodeTree (Leaf (port, body)) = maybe mempty (\p -> pretty '<' <> p <> pretty '>') (fmap pretty 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,@@ -118,37 +116,39 @@     -- '\l'. Single lines of text remain centred, which provides better     -- formatting for short statements and port labels.     ---    pp :: Doc -> Doc-    pp = encode . renderSmart 0.7 120+    pp :: Adoc -> Adoc+    pp = encode . layoutSmart defaultLayoutOptions+    -- pp = encode . renderSmart 0.7 120 -    encode :: SimpleDoc -> Doc+    encode :: SimpleDocStream Keyword -> Adoc     encode doc =       let-          go SFail         = error "unexpected failure rendering SimpleDoc"-          go SEmpty        = (empty, False)-          go (SChar c x)   = let (x',m) = go x in (text (escape c) <> x', m)-          go (SText _ t x) = let (x',m) = go x in (text (concatMap escape t) <> x', m)-          go (SLine i x)   = let (x',_) = go x in (text "\\l" <> spaces i <> x', True)  -- [1] left justify-          go (SSGR _ x)    = go x+          go SFail          = error "unexpected failure rendering SimpleDoc"+          go SEmpty         = (mempty, False)+          go (SChar c x)    = let (x',m) = go x in (pretty (escape c) <> x', m)+          go (SText _ t x)  = let (x',m) = go x in (pretty (Text.concatMap escape t) <> x', m)+          go (SLine i x)    = let (x',_) = go x in ("\\l" <> spaces i <> x', True)  -- [1] left justify+          go (SAnnPush a x) = let (x',m) = go x in (annotate a x', m)+          go (SAnnPop x)    = let (x',m) = go x in (unAnnotate x', m)            (doc',multiline) = go doc       in       doc' <> if multiline-                then text "\\l"-                else empty+                then "\\l"+                else mempty -    spaces :: Int -> Doc-    spaces i | i <= 0    = empty-             | otherwise = text (concat (replicate i "\\ "))+    spaces :: Int -> Doc ann+    spaces i | i <= 0    = mempty+             | otherwise = pretty (Text.replicate i "\\ ") -    escape :: Char -> String+    escape :: Char -> Text     escape ' '  = "\\ "         -- don't collapse multiple spaces     escape '>'  = "\\>"     escape '<'  = "\\<"     escape '|'  = "\\|"     -- escape '\n' = "\\l"      -- handled at [1] instead-    escape c    = [c]+    escape c    = Text.singleton c -ppNodeId :: NodeId -> Doc-ppNodeId (NodeId nid) = text (printf "Node_%#0x" nid)+ppNodeId :: NodeId -> Adoc+ppNodeId (NodeId nid) = pretty (printf "Node_%#0x" nid :: String) 
src/Data/Array/Accelerate/Pretty/Print.hs view
@@ -1,631 +1,734 @@-{-# LANGUAGE CPP                 #-}-{-# LANGUAGE FlexibleInstances   #-}-{-# LANGUAGE GADTs               #-}-{-# LANGUAGE PatternGuards       #-}-{-# LANGUAGE RankNTypes          #-}-{-# LANGUAGE ScopedTypeVariables #-}-{-# LANGUAGE TypeOperators       #-}--- |--- Module      : Data.Array.Accelerate.Pretty.Print--- 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)-----module Data.Array.Accelerate.Pretty.Print (--  -- * Pretty printing-  -- ** 'OpenAcc'-  ---  prettyOpenAcc,-  prettyOpenAfun,-  prettyOpenExp,-  prettyOpenFun,--  -- ** 'PreOpenAcc'-  PrettyAcc,-  prettyPreOpenAcc,-  prettyPreOpenAfun,-  -- prettyPreOpenSeq,-  prettyPreExp, prettyPreOpenExp,-  prettyPreFun, prettyPreOpenFun,-  prettyPrim,-  prettyArrays,-  prettyTupleIdx,--  -- ** Utilities-  Val(..), PrettyEnv(..), prj, sizeEnv,-  noParens,--) where---- standard libraries-import Prelude                                          hiding ( (<$>), exp, seq )-import Data.List                                        ( isPrefixOf )-import Data.Typeable                                    ( typeOf, showsTypeRep )-import Text.PrettyPrint.ANSI.Leijen                     hiding ( parens, tupled )-import qualified Text.PrettyPrint.ANSI.Leijen           as PP---- friends-import Data.Array.Accelerate.AST                        hiding ( Val(..), prj )-import Data.Array.Accelerate.Array.Sugar-import Data.Array.Accelerate.Product-import Data.Array.Accelerate.Type----- Pretty printing--- ===============---- Pretty printing for the knot-tied 'OpenAcc'--- ----------------------------------------------- Pretty print an array expression----prettyOpenAcc :: PrettyAcc OpenAcc-prettyOpenAcc wrap aenv (OpenAcc acc) = prettyPreOpenAcc prettyOpenAcc wrap aenv acc--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-    -> (Doc -> Doc)                             -- apply to compound expressions-    -> Val aenv                                 -- environment of array variables-    -> PreOpenAcc acc aenv arrs-    -> Doc-prettyPreOpenAcc prettyAcc wrap aenv = pp-  where-    ppE :: PreExp acc aenv e -> Doc-    ppE = prettyPreExp prettyAcc parens aenv--    ppSh :: PreExp acc aenv sh -> Doc-    ppSh x = encase (prettyPreExp prettyAcc noParens aenv x)-      where-        encase = case x of-                   Var{}    -> id-                   IndexNil -> id-                   IndexAny -> id-                   Const{}  -> id-                   _        -> parens--    ppF :: PreFun acc aenv f -> Doc-    ppF = parens . prettyPreFun prettyAcc aenv--    ppA :: acc aenv a -> Doc-    ppA = prettyAcc parens aenv--    ppAF :: PreOpenAfun acc aenv f -> Doc-    ppAF = parens . prettyPreOpenAfun prettyAcc aenv--    ppB :: forall sh e. (Shape sh, Elt e)-        => PreBoundary acc aenv (Array sh e)-        -> Doc-    ppB Clamp        = text "clamp"-    ppB Mirror       = text "mirror"-    ppB Wrap         = text "wrap"-    ppB (Constant e) = parens $ text "constant" <+> text (show (toElt e :: e))-    ppB (Function f) = ppF f--    -- pretty print a named array operation with its arguments-    infixr 0 .$-    name .$ docs = wrap $ hang 2 (sep (manifest (text name) : docs))--    -- The main pretty-printer-    -- ------------------------    ---    pp :: PreOpenAcc acc aenv arrs -> Doc-    pp (Alet acc1 acc2)-      | isAlet acc2'-      = if isAlet acc1'-          then wrap $ vsep [ let_ <+> a <+> equals <$> indent 2 acc1'    <+> in_, acc2' ]-          else wrap $ vsep [ hang 2 (sep [let_ <+> a <+> equals, acc1']) <+> in_, acc2' ]--      | otherwise-      = wrap $ vsep [ hang 2 (sep [let_ <+> a <+> equals, acc1']), in_ </> acc2' ]-      where-        -- TLM: derp, can't unwrap into a PreOpenAcc to pattern match on Alet-        render doc  = displayS (renderCompact (plain doc)) ""-        isAlet doc  = "let" `isPrefixOf` render doc-        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 aenv tup-    pp (Avar idx)               = prj idx aenv-    pp (Aprj ix arrs)           = wrap $ prettyTupleIdx ix <+> ppA arrs-    pp (Apply afun acc)         = wrap $ sep [ ppAF afun, ppA acc ]-    pp (Acond e acc1 acc2)      = wrap $ hang 3 (vsep [if_ <+> ppE e, then_ <+> ppA acc1, else_ <+> ppA acc2])-    pp (Slice _ty acc ix)       = "slice"       .$ [ ppA acc, ppE ix ]-    pp (Use arrs)               = "use"         .$ [ prettyArrays (arrays (undefined :: arrs)) arrs ]-    pp (Unit e)                 = "unit"        .$ [ ppE e ]-    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 ]-    pp (Fold1 f acc)            = "fold1"       .$ [ ppF f, ppA acc ]-    pp (FoldSeg f e acc1 acc2)  = "foldSeg"     .$ [ ppF f, ppE e, ppA acc1, ppA acc2 ]-    pp (Fold1Seg f acc1 acc2)   = "fold1Seg"    .$ [ ppF f, ppA acc1, ppA acc2 ]-    pp (Scanl f e acc)          = "scanl"       .$ [ ppF f, ppE e, ppA acc ]-    pp (Scanl' f e acc)         = "scanl'"      .$ [ ppF f, ppE e, ppA acc ]-    pp (Scanl1 f acc)           = "scanl1"      .$ [ ppF f, ppA acc ]-    pp (Scanr f e acc)          = "scanr"       .$ [ ppF f, ppE e, ppA acc ]-    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" .$ [ 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 bndy, ppA acc ]-    pp (Stencil2 sten bndy1 acc1 bndy2 acc2)-                                = "stencil2"    .$ [ ppF sten, ppB bndy1, ppA acc1, ppB bndy2, ppA acc2 ]--    -- pp (Collect s)              = wrap $ hang (text "collect") 2-    --                                    $ encloseSep lbrace rbrace semi-    --                                    $ prettyPreOpenSeq prettyAcc wrap aenv Empty s---{----- 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-    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)--    ppE :: PreExp acc aenv e -> Doc-    ppE = prettyPreExp prettyAcc parens aenv--    ppF :: PreFun acc aenv f -> Doc-    ppF = parens . prettyPreFun prettyAcc aenv--    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)   = sep [ ppSlix s, text ":.", text "All"   ]-    ppSlix (SliceFixed s) = sep [ 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             -> tupled (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-    next :: Val aenv' -> PreOpenAfun acc aenv' f' -> Doc-    next aenv' (Abody body) = text "->" <+> align (pp noParens aenv' body)-    next aenv' (Alam afun') =-      let a = char 'a' <> int (sizeEnv aenv')-      in  a <+> next (aenv' `Push` a) afun'----- Pretty print a scalar function.----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 "->" <+> align (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.----prettyPreExp :: PrettyAcc acc -> (Doc -> Doc) -> Val aenv -> PreExp acc aenv t -> Doc-prettyPreExp pp wrap = prettyPreOpenExp pp wrap Empty--prettyPreOpenExp-    :: forall acc t env aenv.-       PrettyAcc acc-    -> (Doc -> Doc)                             -- apply to compound expressions-    -> Val env                                  -- environment of scalar variables-    -> Val aenv                                 -- environment of array variables-    -> PreOpenExp acc env aenv t-    -> Doc-prettyPreOpenExp prettyAcc wrap env aenv = pp-  where-    ppE, ppE' :: PreOpenExp acc env aenv e -> Doc-    ppE  = prettyPreOpenExp prettyAcc parens env aenv-    ppE' = prettyPreOpenExp prettyAcc noParens env aenv--    ppSh :: PreOpenExp acc env aenv sh -> Doc-    ppSh x = encase (ppE' x)-      where-        encase = case x of-                   Var{}    -> id-                   IndexNil -> id-                   IndexAny -> id-                   Const{}  -> id-                   _        -> parens--    ppF :: PreOpenFun acc env aenv f -> Doc-    ppF = parens . prettyPreOpenFun prettyAcc env aenv--    ppA :: acc aenv a -> Doc-    ppA = prettyAcc parens aenv--    -- pretty print a named array operation with its arguments-    infixr 0 .$-    name .$ docs = wrap $ hang 2 (sep (text name : docs))--    -- The main pretty-printer-    -- ------------------------    ---    pp :: PreOpenExp acc env aenv t -> Doc-    pp (Let e1 e2)-      | isLet e2-      = if isLet e1-          then wrap $ vsep [ let_ <+> x <+> equals <$> indent 2 e1'    <+> in_, e2' ]-          else wrap $ vsep [ hang 2 (sep [let_ <+> x <+> equals, e1']) <+> in_, e2' ]-      | otherwise-      = wrap $ vsep [ hang 2 (sep [let_ <+> x <+> equals, e1']), in_ </> e2' ]-      where-        isLet (Let _ _)     = True-        isLet _             = False-        e1'                 = align $ prettyPreOpenExp prettyAcc noParens env            aenv e1-        e2'                 = align $ prettyPreOpenExp prettyAcc noParens (env `Push` x) aenv e2-        x                   = char 'x' <> int (sizeEnv env)--    pp (PrimApp p a)-      | Tuple (NilTup `SnocTup` x `SnocTup` y) <- a-      = if infixOp-          then wrap $ sep [ppE x, f, ppE y]-          else hang 2 (sep [f, ppSh x, ppSh y])-      | otherwise-      = wrap $ hang 2 (sep [f', ppE a])-      where-        -- sometimes the infix function arguments are obstructed. If so, add-        -- parentheses and print prefix.-        ---        (infixOp, f) = prettyPrim p-        f'           = if infixOp then parens f else f--    pp (PrimConst a)            = prettyConst a-    pp (Tuple tup)              = prettyTuple (eltType (undefined::t)) prettyAcc env aenv tup-    pp (Var idx)                = prj idx env-    pp (Const v)                = text $ show (toElt v :: t)-    pp (Prj idx e)              = wrap $ prettyTupleIdx idx <+> ppE e-    pp (Cond c t e)             = wrap $ hang 3 (vsep [ if_ <+> ppE' c, then_ <+> ppE' t, else_ <+> ppE' e ])-    pp Undef                    = text "undef"-    pp IndexNil                 = char 'Z'-    pp IndexAny                 = text "indexAny"-    pp (IndexCons t h)          = sep [ ppE' t, text ":.", ppE' h ]-    pp (IndexHead ix)           = "indexHead"  .$ [ ppE ix ]-    pp (IndexTail ix)           = "indexTail"  .$ [ ppE ix ]-    pp (IndexSlice _ slix sh)   = "indexSlice" .$ [ ppSh slix, ppSh sh ]-    pp (IndexFull _ slix sl)    = "indexFull"  .$ [ ppSh slix, ppSh sl ]-    pp (ToIndex sh ix)          = "toIndex"    .$ [ ppSh sh, ppSh ix ]-    pp (FromIndex sh ix)        = "fromIndex"  .$ [ ppSh sh, ppSh 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"  .$ [ 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 '!',  ppSh i ]-    pp (LinearIndex idx i)      = wrap $ cat [ ppA idx, text "!!", ppSh i ]-    pp (Coerce x)               = "coerce<" ++ showsTypeRep (typeOf (undefined::t)) ">" .$ [ ppE x ]----- Pretty print nested pairs as a proper tuple.----prettyAtuple-    :: forall acc aenv t.-       PrettyAcc acc-    -> Val aenv-    -> Atuple (acc aenv) t-    -> Doc-prettyAtuple pp aenv = tupled False . collect-  where-    collect :: Atuple (acc aenv) t' -> [Doc]-    collect NilAtup          = []-    collect (SnocAtup tup a) = collect tup ++ [pp noParens aenv a]--prettyTuple-    :: forall acc env aenv t p.-       TupleType t-    -> PrettyAcc acc-    -> Val env-    -> Val aenv-    -> Tuple (PreOpenExp acc env aenv) p-    -> Doc-prettyTuple tt pp env aenv = tupled simd . collect-  where-    collect :: Tuple (PreOpenExp acc env aenv) t' -> [Doc]-    collect NilTup          = []-    collect (SnocTup tup e) = collect tup ++ [prettyPreOpenExp pp noParens env aenv e]--    simd :: Bool-    simd | TypeRscalar VectorScalarType{} <- tt = True-         | otherwise                            = False----- Pretty print an index for a tuple projection----prettyTupleIdx :: TupleIdx t e -> Doc-prettyTupleIdx ix = char '#' <> int (toInt ix)-  where-    toInt :: TupleIdx t e -> Int-    toInt ZeroTupIdx       = 0-    toInt (SuccTupIdx tup) = toInt tup + 1---- Pretty print a primitive constant----prettyConst :: PrimConst a -> Doc-prettyConst (PrimMinBound _) = text "minBound"-prettyConst (PrimMaxBound _) = text "maxBound"-prettyConst (PrimPi       _) = text "pi"---- Pretty print a primitive operation. The first parameter indicates whether the--- 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 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 PrimIsInfinite{}         = (False, text "isInfinite")-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")--{---- Pretty print type----prettyAnyType :: ScalarType a -> Doc-prettyAnyType ty = text $ show ty--}---- TLM: seems to flatten the nesting structure----prettyArrays :: ArraysR arrs -> arrs -> Doc-prettyArrays arrs = tupled False . collect arrs-  where-    collect :: ArraysR arrs -> arrs -> [Doc]-    collect ArraysRunit         _        = []-    collect ArraysRarray        arr      = [prettyArray arr]-    collect (ArraysRpair r1 r2) (a1, a2) = collect r1 a1 ++ collect r2 a2--prettyArray :: forall dim e. Array dim e -> Doc-prettyArray arr@(Array sh _)-  = hang 2 $ sep [ text "Array"-                 , parens . text $ showShape (toElt sh :: dim)-                 , dataDoc ]-  where-    showDoc :: forall a. Show a => a -> Doc-    showDoc = text . show-    l       = toList arr-    dataDoc | length l <= 1000 = showDoc l-            | otherwise        = showDoc (take 1000 l) <+>-                                 text "{truncated at 1000 elements}"----- Auxiliary pretty printing combinators-----parens :: Doc -> Doc-parens = PP.parens . align--noParens :: Doc -> Doc-noParens = id--tupled :: Bool -> [Doc] -> Doc-tupled True  = encloseSep langle rangle comma . map align-tupled False = encloseSep lparen rparen comma . map align----- ANSI colourisation-----control :: Doc -> Doc-control = dullyellow--manifest :: Doc -> Doc-manifest = blue---- delayed :: Doc -> Doc--- delayed = green--let_, in_ :: Doc-let_ = control (text "let")-in_  = control (text "in")--if_, then_, else_ :: Doc-if_   = control (text "if")-then_ = control (text "then")-else_ = control (text "else")----- 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-----{---- Show scalar values----runScalarShow :: ScalarType a -> (a -> String)-runScalarShow (NumScalarType (IntegralNumType ty))-  | IntegralDict <- integralDict ty = show-runScalarShow (NumScalarType (FloatingNumType ty))-  | FloatingDict <- floatingDict ty = show-runScalarShow (NonNumScalarType ty)-  | NonNumDict   <- nonNumDict ty   = show--}+{-# LANGUAGE FlexibleInstances   #-}+{-# LANGUAGE GADTs               #-}+{-# LANGUAGE LambdaCase          #-}+{-# LANGUAGE OverloadedStrings   #-}+{-# LANGUAGE PatternGuards       #-}+{-# LANGUAGE RankNTypes          #-}+{-# LANGUAGE RecordWildCards     #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TypeApplications    #-}+{-# LANGUAGE TypeOperators       #-}+{-# LANGUAGE ViewPatterns        #-}+-- |+-- Module      : Data.Array.Accelerate.Pretty.Print+-- Copyright   : [2008..2020] The Accelerate Team+-- License     : BSD3+--+-- Maintainer  : Trevor L. McDonell <trevor.mcdonell@gmail.com>+-- Stability   : experimental+-- Portability : non-portable (GHC extensions)+--++module Data.Array.Accelerate.Pretty.Print (++  PrettyAcc, ExtractAcc,+  prettyPreOpenAcc,+  prettyPreOpenAfun,+  prettyOpenExp, prettyExp,+  prettyOpenFun, prettyFun,+  prettyArray,+  prettyConst,+  prettyELhs,+  prettyALhs,++  -- ** Internals+  Adoc,+  Val(..),+  PrettyEnv(..),+  Context(..),+  Keyword(..),+  Operator(..),+  parensIf, needsParens,+  ansiKeyword,+  shiftwidth,+  context0,+  app,+  manifest, delayed,+  primOperator,+  isInfix,+  prj, sizeEnv,++) where++import Data.Array.Accelerate.AST                                    hiding ( Direction )+import Data.Array.Accelerate.AST.Idx+import Data.Array.Accelerate.AST.LeftHandSide+import Data.Array.Accelerate.AST.Var+import Data.Array.Accelerate.Representation.Array+import Data.Array.Accelerate.Representation.Elt+import Data.Array.Accelerate.Representation.Stencil+import Data.Array.Accelerate.Representation.Tag+import Data.Array.Accelerate.Representation.Type+import Data.Array.Accelerate.Sugar.Foreign+import Data.Array.Accelerate.Type+import qualified Data.Array.Accelerate.AST                          as AST++import Data.Char+import Data.String+import Data.Text.Prettyprint.Doc+import Data.Text.Prettyprint.Doc.Render.Terminal+import Prelude                                                      hiding ( exp )+++-- Implementation+-- --------------++type PrettyAcc  acc = forall aenv a. Context -> Val aenv -> acc aenv a -> Adoc+type ExtractAcc acc = forall aenv a. acc aenv a -> PreOpenAcc acc aenv a++type Adoc = Doc Keyword++data Keyword+  = Statement     -- do | case of | let in+  | Conditional   -- if then else+  | Manifest      -- collective operations (kernel functions)+  | Delayed       -- fused operators+  deriving (Eq, Show)++let_, in_ :: Adoc+let_ = annotate Statement "let"+in_  = annotate Statement "in"++case_, of_ :: Adoc+case_ = annotate Statement "case"+of_   = annotate Statement "of"++if_, then_, else_ :: Adoc+if_   = annotate Statement "if"+then_ = annotate Statement "then"+else_ = annotate Statement "else"++manifest :: Operator -> Adoc+manifest = annotate Manifest . opName++delayed :: Operator -> Adoc+delayed = annotate Delayed . opName++ansiKeyword :: Keyword -> AnsiStyle+ansiKeyword Statement   = colorDull Yellow+ansiKeyword Conditional = colorDull Yellow+ansiKeyword Manifest    = color Blue+ansiKeyword Delayed     = color Green+++-- Array computations+-- ------------------++prettyPreOpenAfun+    :: forall acc aenv f.+       PrettyAcc acc+    -> Val aenv+    -> PreOpenAfun acc aenv f+    -> Adoc+prettyPreOpenAfun prettyAcc aenv0 = next (pretty '\\') aenv0+  where+    next :: Adoc -> Val aenv' -> PreOpenAfun acc aenv' f' -> Adoc+    next vs aenv (Abody body)   = hang shiftwidth (sep [vs <> "->", prettyAcc context0 aenv body])+    next vs aenv (Alam lhs lam) =+      let (aenv', lhs') = prettyALhs True aenv lhs+      in  next (vs <> lhs' <> space) aenv' lam++prettyPreOpenAcc+    :: forall acc aenv arrs.+       Context+    -> PrettyAcc acc+    -> ExtractAcc acc+    -> Val aenv+    -> PreOpenAcc acc aenv arrs+    -> Adoc+prettyPreOpenAcc ctx prettyAcc extractAcc aenv pacc =+  case pacc of+    Avar (Var _ idx)        -> prj idx aenv+    Alet{}                  -> prettyAlet ctx prettyAcc extractAcc aenv pacc+    Apair{}                 -> prettyAtuple prettyAcc extractAcc aenv pacc+    Anil                    -> "()"+    Apply _ f a             -> apply+      where+        op    = Operator ">->" Infix L 1+        apply = sep [ ppAF f, group (sep [opName op, ppA a]) ]++    Acond p t e             -> flatAlt multi single+      where+        p' = ppE p+        t' = ppA t+        e' = ppA e+        --+        single = parensIf (needsParens ctx (Operator "?|:" Infix N 0))+               $ sep [ p', "?|", t', pretty ':', e' ]+        multi  = hang 3+               $ vsep [ if_ <+> p'+                      , hang shiftwidth (sep [ then_, t' ])+                      , hang shiftwidth (sep [ else_, e' ]) ]++    Aforeign _ ff _ a        -> "aforeign"       .$ [ pretty (strForeign ff), ppA a ]+    Awhile p f a             -> "awhile"         .$ [ ppAF p, ppAF f, ppA a ]+    Use repr arr             -> "use"            .$ [ prettyArray repr arr ]+    Unit _ e                 -> "unit"           .$ [ ppE e ]+    Reshape _ sh a           -> "reshape"        .$ [ ppE sh, ppA a ]+    Generate _ sh f          -> "generate"       .$ [ ppE sh, ppF f ]+    Transform _ sh p f a     -> "transform"      .$ [ ppE sh, ppF p, ppF f, ppA a ]+    Replicate _ ix a         -> "replicate"      .$ [ ppE ix, ppA a ]+    Slice _ a ix             -> "slice"          .$ [ ppE ix, ppA a ]+    Map _ f a                -> "map"            .$ [ ppF f,  ppA a ]+    ZipWith _ f a b          -> "zipWith"        .$ [ ppF f,  ppA a, ppA b ]+    Fold f (Just z) a        -> "fold"           .$ [ ppF f,  ppE z, ppA a ]+    Fold f Nothing  a        -> "fold1"          .$ [ ppF f,  ppA a ]+    FoldSeg _ f (Just z) a s -> "foldSeg"        .$ [ ppF f,  ppE z, ppA a, ppA s ]+    FoldSeg _ f Nothing  a s -> "fold1Seg"       .$ [ ppF f,  ppA a, ppA s ]+    Scan d f (Just z) a      -> ppD "scan" d ""  .$ [ ppF f,  ppE z, ppA a ]+    Scan d f Nothing  a      -> ppD "scan" d "1" .$ [ ppF f,  ppA a ]+    Scan' d f z a            -> ppD "scan" d "'" .$ [ ppF f,  ppE z, ppA a ]+    Permute f d p s          -> "permute"        .$ [ ppF f,  ppA d, ppF p, ppA s ]+    Backpermute _ sh f a     -> "backpermute"    .$ [ ppE sh, ppF f, ppA a ]+    Stencil s _ f b a        -> "stencil"        .$ [ ppF f,  ppB (stencilEltR s) b, ppA a ]+    Stencil2 s1 s2 _ f b1 a1 b2 a2+                             -> "stencil2"       .$ [ ppF f,  ppB (stencilEltR s1) b1, ppA a1, ppB (stencilEltR s2) b2, ppA a2 ]+  where+    infixr 0 .$+    f .$ xs+      = parensIf (needsParens ctx f)+      $ hang shiftwidth (sep (manifest f : xs))++    ppA :: acc aenv a -> Adoc+    ppA = prettyAcc app aenv++    ppAF :: PreOpenAfun acc aenv f -> Adoc+    ppAF = parens . prettyPreOpenAfun prettyAcc aenv++    ppE :: Exp aenv t -> Adoc+    ppE = prettyOpenExp app Empty aenv++    ppF :: Fun aenv t -> Adoc+    ppF = parens . prettyOpenFun Empty aenv++    ppB :: forall sh e.+           TypeR e+        -> Boundary aenv (Array sh e)+        -> Adoc+    ppB _  Clamp        = "clamp"+    ppB _  Mirror       = "mirror"+    ppB _  Wrap         = "wrap"+    ppB tp (Constant e) = prettyConst tp e+    ppB _  (Function f) = ppF f++    ppD :: String -> AST.Direction -> String -> Operator+    ppD f AST.LeftToRight k = fromString (f <> "l" <> k)+    ppD f AST.RightToLeft k = fromString (f <> "r" <> k)+++prettyAlet+    :: forall acc aenv arrs.+       Context+    -> PrettyAcc acc+    -> ExtractAcc acc+    -> Val aenv+    -> PreOpenAcc acc aenv arrs+    -> Adoc+prettyAlet ctx prettyAcc extractAcc aenv0+  = parensIf (needsParens ctx "let")+  . align . wrap . collect aenv0+  where+    collect :: Val aenv' -> PreOpenAcc acc aenv' a -> ([Adoc], Adoc)+    collect aenv =+      \case+        Alet lhs a1 a2 ->+          let (aenv', v)      = prettyALhs False aenv lhs+              a1'             = ppA aenv a1+              bnd | isAlet a1 = nest shiftwidth (vsep [v <+> equals, a1'])+                  | otherwise = v <+> align (equals <+> a1')+              (bnds, body)    = collect aenv' (extractAcc a2)+          in+          (bnd:bnds, body)+        --+        next       -> ([], prettyPreOpenAcc context0 prettyAcc extractAcc aenv next)++    isAlet :: acc aenv' a -> Bool+    isAlet (extractAcc -> Alet{}) = True+    isAlet _                      = False++    ppA :: Val aenv' -> acc aenv' a -> Adoc+    ppA = prettyAcc context0++    wrap :: ([Adoc], Adoc) -> Adoc+    wrap ([],   body) = body  -- shouldn't happen!+    wrap ([b],  body)+      = sep [ nest shiftwidth (sep [let_, b]), in_, body ]+    wrap (bnds, body)+      = vsep [ nest shiftwidth (vsep (let_:bnds))+             , in_+             , body+             ]++prettyAtuple+    :: forall acc aenv arrs.+       PrettyAcc acc+    -> ExtractAcc acc+    -> Val aenv+    -> PreOpenAcc acc aenv arrs+    -> Adoc+prettyAtuple prettyAcc extractAcc aenv0 acc = case collect acc of+    Nothing  -> align $ ppPair acc+    Just tup ->+      case tup of+        []  -> "()"+        [t] -> t+        _   -> align $ "T" <> pretty (length tup) <+> sep tup+  where+    ppPair :: PreOpenAcc acc aenv arrs' -> Adoc+    ppPair (Apair a1 a2) = "(" <> ppPair (extractAcc a1) <> "," <+> prettyAcc context0 aenv0 a2 <> ")"+    ppPair a             = prettyPreOpenAcc context0 prettyAcc extractAcc aenv0 a++    collect :: PreOpenAcc acc aenv arrs' -> Maybe [Adoc]+    collect Anil          = Just []+    collect (Apair a1 a2)+      | Just tup <- collect $ extractAcc a1+                          = Just $ tup ++ [prettyAcc app aenv0 a2]+    collect _             = Nothing++-- TODO: Should we also print the types of the declared variables? And the types of wildcards?+prettyALhs :: Bool -> Val env -> LeftHandSide s arrs env env' -> (Val env', Adoc)+prettyALhs requiresParens = prettyLhs requiresParens 'a'++prettyELhs :: Bool -> Val env -> LeftHandSide s arrs env env' -> (Val env', Adoc)+prettyELhs requiresParens = prettyLhs requiresParens 'x'++prettyLhs :: forall s env env' arrs. Bool -> Char -> Val env -> LeftHandSide s arrs env env' -> (Val env', Adoc)+prettyLhs requiresParens x env0 lhs = case collect lhs of+  Nothing          -> ppPair lhs+  Just (env1, tup) ->+    case tup of+      []  -> (env1, "()")+      _   -> (env1, parensIf requiresParens (pretty 'T' <> pretty (length tup) <+> sep tup))+  where+    ppPair :: LeftHandSide s arrs' env env'' -> (Val env'', Adoc)+    ppPair LeftHandSideUnit       = (env0, "()")+    ppPair LeftHandSideWildcard{} = (env0, "_")+    ppPair LeftHandSideSingle{}   = (env0 `Push` v, v)+      where+        v = pretty x <> pretty (sizeEnv env0)+    ppPair (LeftHandSidePair a b)          = (env2, tupled [doc1, doc2])+      where+        (env1, doc1) = ppPair a+        (env2, doc2) = prettyLhs False x env1 b++    collect :: LeftHandSide s arrs' env env'' -> Maybe (Val env'', [Adoc])+    collect (LeftHandSidePair l1 l2)+      | Just (env1, tup ) <- collect l1+      ,      (env2, doc2) <- prettyLhs True x env1 l2 = Just (env2, tup ++ [doc2])+    collect (LeftHandSideWildcard TupRunit) = Just (env0, [])+    collect _ = Nothing++prettyArray :: ArrayR (Array sh e) -> Array sh e -> Adoc+prettyArray aR@(ArrayR _ eR) = parens . fromString . showArray (showsElt eR) aR+++-- Scalar expressions+-- ------------------++prettyFun :: Val aenv -> Fun aenv f -> Adoc+prettyFun = prettyOpenFun Empty++prettyExp :: Val aenv -> Exp aenv t -> Adoc+prettyExp = prettyOpenExp context0 Empty++prettyOpenFun+    :: forall env aenv f.+       Val env+    -> Val aenv+    -> OpenFun env aenv f+    -> Adoc+prettyOpenFun env0 aenv = next (pretty '\\') env0+  where+    next :: Adoc -> Val env' -> OpenFun env' aenv f' -> Adoc+    next vs env (Body body)+      --   PrimApp f x                             <- body+      -- , op                                      <- primOperator f+      -- , isInfix op+      -- , Tuple (NilTup `SnocTup` a `SnocTup` b)  <- x+      -- , Var (SuccIdx ZeroIdx)                   <- a+      -- , Var ZeroIdx                             <- b+      -- = opName op -- surrounding context will add parens+      --+      = hang shiftwidth (sep [ vs <> "->"+                             , prettyOpenExp context0 env aenv body])+    next vs env (Lam lhs lam) =+      let (env', lhs') = prettyELhs True env lhs+      in  next (vs <> lhs' <> space) env' lam++prettyOpenExp+    :: forall env aenv t.+       Context+    -> Val env+    -> Val aenv+    -> OpenExp env aenv t+    -> Adoc+prettyOpenExp ctx env aenv exp =+  case exp of+    Evar (Var _ idx)      -> prj idx env+    Let{}                 -> prettyLet ctx env aenv exp+    PrimApp f x+      | a `Pair` b <- x   -> ppF2 op  (ppE a) (ppE b)+      | otherwise         -> ppF1 op' (ppE x)+      where+        op  = primOperator f+        op' = isInfix op ? (Operator (parens (opName op)) App L 10, op)+    --+    PrimConst c           -> prettyPrimConst c+    Const tp c            -> prettyConst (TupRsingle tp) c+    Pair{}                -> prettyTuple ctx env aenv exp+    Nil                   -> "()"+    VecPack   _ e         -> ppF1 "pack"   (ppE e)+    VecUnpack _ e         -> ppF1 "unpack" (ppE e)+    Case x xs d           -> prettyCase env aenv x xs d+    Cond p t e            -> flatAlt multi single+      where+        p' = ppE p context0+        t' = ppE t context0+        e' = ppE e context0+        --+        single = parensIf (needsParens ctx (Operator "?:" Infix N 0))+               $ sep [ p', pretty '?', t', pretty ':', e' ]+        multi  = hang 3+               $ vsep [ if_ <+> p'+                      , hang shiftwidth (sep [ then_, t' ])+                      , hang shiftwidth (sep [ else_, e' ]) ]+    --+    IndexSlice _ slix sh  -> ppF2 "indexSlice"  (ppE slix) (ppE sh)+    IndexFull _ slix sl   -> ppF2 "indexFull"   (ppE slix) (ppE sl)+    ToIndex _ sh ix       -> ppF2 "toIndex"     (ppE sh) (ppE ix)+    FromIndex _ sh ix     -> ppF2 "fromIndex"   (ppE sh) (ppE ix)+    While p f x           -> ppF3 "while"       (ppF p) (ppF f) (ppE x)+    Foreign _ ff _ e      -> ppF2 "foreign"     (\_ -> pretty (strForeign ff)) (ppE e)+    Shape arr             -> ppF1 "shape"       (ppA arr)+    ShapeSize _ sh        -> ppF1 "shapeSize"   (ppE sh)+    Index arr ix          -> ppF2 (Operator (pretty '!') Infix L 9) (ppA arr) (ppE ix)+    LinearIndex arr ix    -> ppF2 (Operator "!!"         Infix L 9) (ppA arr) (ppE ix)+    Coerce _ tp x         -> ppF1 (Operator (withTypeRep tp "coerce") App L 10) (ppE x)+    Undef tp              -> withTypeRep tp "undef"++  where+    ppE :: OpenExp env aenv e -> Context -> Adoc+    ppE e c = prettyOpenExp c env aenv e++    ppA :: ArrayVar aenv a -> Context -> Adoc+    ppA acc _ = prettyArrayVar aenv acc++    ppF :: OpenFun env aenv f -> Context -> Adoc+    ppF f _ = parens $ prettyOpenFun env aenv f++    ppF1 :: Operator -> (Context -> Adoc) -> Adoc+    ppF1 op x+      = parensIf (needsParens ctx op)+      $ combine [ opName op, x ctx' ]+      where+        ctx'    = isPrefix op ? (arg op R, app)+        combine = isPrefix op ? (cat, hang 2 . sep)++    ppF2 :: Operator -> (Context -> Adoc) -> (Context -> Adoc) -> Adoc+    ppF2 op x y+      = parensIf (needsParens ctx op)+      $ if isInfix op+          then sep [ x (arg op L), group (sep [opName op, y (arg op R)]) ]+          else hang 2 $ sep [ opName op, x app, y app ]++    ppF3 :: Operator -> (Context -> Adoc) -> (Context -> Adoc) -> (Context -> Adoc) -> Adoc+    ppF3 op x y z+      = parensIf (needsParens ctx op)+      $ hang 2+      $ sep [ opName op, x app, y app, z app ]++    withTypeRep :: ScalarType t -> Adoc -> Adoc+    withTypeRep t op = op <+> "@" <> pretty (show t)++prettyArrayVar+    :: forall aenv a.+       Val aenv+    -> ArrayVar aenv a+    -> Adoc+prettyArrayVar aenv (Var _ idx) = prj idx aenv++prettyLet+    :: forall env aenv t.+       Context+    -> Val env+    -> Val aenv+    -> OpenExp env aenv t+    -> Adoc+prettyLet ctx env0 aenv+  = parensIf (needsParens ctx "let")+  . align . wrap . collect env0+  where+    collect :: Val env' -> OpenExp env' aenv e -> ([Adoc], Adoc)+    collect env =+      \case+        Let lhs e1 e2 ->+          let (env', v)       = prettyELhs False env lhs+              e1'             = ppE env e1+              bnd | isLet e1  = nest shiftwidth (vsep [v <+> equals, e1'])+                  | otherwise = v <+> align (equals <+> e1')+              (bnds, body)    = collect env' e2+          in+          (bnd:bnds, body)+        --+        next     -> ([], ppE env next)++    isLet :: OpenExp env' aenv t' -> Bool+    isLet Let{} = True+    isLet _     = False++    ppE :: Val env' -> OpenExp env' aenv t' -> Adoc+    ppE env = prettyOpenExp context0 env aenv++    wrap :: ([Adoc], Adoc) -> Adoc+    wrap ([],   body) = body  -- shouldn't happen!+    wrap ([b],  body)+      = sep [ nest shiftwidth (sep [let_, b]), in_, body ]+    wrap (bnds, body)+      = vsep [ nest shiftwidth (vsep (let_ : bnds))+             , in_+             , body+             ]++prettyTuple+    :: forall env aenv t.+       Context+    -> Val env+    -> Val aenv+    -> OpenExp env aenv t+    -> Adoc+prettyTuple ctx env aenv exp = case collect exp of+    Nothing  -> align $ ppPair exp+    Just tup ->+      case tup of+        []  -> "()"+        [t] -> t+        _   -> align $ parensIf (ctxPrecedence ctx > 0) ("T" <> pretty (length tup) <+> sep tup)+  where+    ppPair :: OpenExp env aenv t' -> Adoc+    ppPair (Pair e1 e2) = "(" <> ppPair e1 <> "," <+> prettyOpenExp context0 env aenv e2 <> ")"+    ppPair e            = prettyOpenExp context0 env aenv e++    collect :: OpenExp env aenv t' -> Maybe [Adoc]+    collect Nil                = Just []+    collect (Pair e1 e2)+      | Just tup <- collect e1 = Just $ tup ++ [prettyOpenExp app env aenv e2]+    collect _                  = Nothing++prettyCase+    :: Val env+    -> Val aenv+    -> OpenExp env aenv a+    -> [(TAG, OpenExp env aenv b)]+    -> Maybe (OpenExp env aenv b)+    -> Adoc+prettyCase env aenv x xs def+  = hang shiftwidth+  $ vsep [ case_ <+> x' <+> of_+         , flatAlt (vcat xs') (encloseSep "{ " " }" "; " xs')+         ]+  where+    x'  = prettyOpenExp context0 env aenv x+    xs' = map (\(t,e) -> pretty t <+> "->" <+> prettyOpenExp context0 env aenv e) xs+       ++ case def of+            Nothing -> []+            Just d  -> ["_" <+> "->" <+> prettyOpenExp context0 env aenv d]++{-++prettyAtuple+    :: forall acc aenv arrs.+       PrettyAcc acc+    -> ExtractAcc acc+    -> Val aenv+    -> PreOpenAcc acc aenv arrs+    -> Adoc+prettyAtuple prettyAcc extractAcc aenv0 acc = case collect acc of+  Just tup -> align $ "T" <> pretty (length tup) <+> sep tup+  Nothing  -> align $ ppPair acc+  where+    ppPair :: PreOpenAcc acc aenv arrs' -> Adoc+    ppPair (Apair a1 a2) = "(" <> ppPair (extractAcc a1) <> "," <+> prettyAcc context0 aenv0 a2 <> ")"+    ppPair a             = prettyPreOpenAcc context0 prettyAcc extractAcc aenv0 a++    collect :: PreOpenAcc acc aenv arrs' -> Maybe [Adoc]+    collect Anil          = Just []+    collect (Apair a1 a2)+      | Just tup <- collect $ extractAcc a1+                          = Just $ tup ++ [prettyAcc app aenv0 a2]+    collect _             = Nothing+-}++prettyConst :: TypeR e -> e -> Adoc+prettyConst tp x =+  let y = showElt tp x+  in  parensIf (any isSpace y) (pretty y)++prettyPrimConst :: PrimConst a -> Adoc+prettyPrimConst PrimMinBound{} = "minBound"+prettyPrimConst PrimMaxBound{} = "maxBound"+prettyPrimConst PrimPi{}       = "pi"+++-- Primitive operators+-- -------------------+--+-- The core of the pretty printer is how to correctly handle precedence,+-- associativity, and fixity of the primitive scalar operators.+--++data Direction = L | N | R+  deriving Eq++data Fixity = App | Infix | Prefix+  deriving Eq++type Precedence    = Int+type Associativity = Direction++data Context = Context+  { ctxAssociativity  :: Associativity+  , ctxPosition       :: Direction+  , ctxPrecedence     :: Precedence+  }++data Operator = Operator+  { opName            :: Adoc+  , opFixity          :: Fixity+  , opAssociativity   :: Associativity+  , opPrecedence      :: Precedence+  }++instance IsString Operator where+  fromString s = Operator (fromString s) App L 10++needsParens :: Context -> Operator -> Bool+needsParens Context{..} Operator{..}+  | ctxPrecedence     < opPrecedence    = False+  | ctxPrecedence     > opPrecedence    = True+  | ctxAssociativity /= opAssociativity = True+  | otherwise                           = ctxPosition /= opAssociativity++context0 :: Context+context0 = Context N N 0++app :: Context+app = Context L N 10++arg :: Operator -> Direction -> Context+arg Operator{..} side = Context opAssociativity side opPrecedence++isPrefix :: Operator -> Bool+isPrefix Operator{..} = opFixity == Prefix++isInfix :: Operator -> Bool+isInfix Operator{..}  = opFixity == Infix++primOperator :: PrimFun a -> Operator+primOperator PrimAdd{}                = Operator (pretty '+')         Infix  L 6+primOperator PrimSub{}                = Operator (pretty '-')         Infix  L 6+primOperator PrimMul{}                = Operator (pretty '*')         Infix  L 7+primOperator PrimNeg{}                = Operator (pretty '-')         Prefix L 6  -- Haskell's only prefix operator+primOperator PrimAbs{}                = Operator "abs"                App    L 10+primOperator PrimSig{}                = Operator "signum"             App    L 10+primOperator PrimQuot{}               = Operator "quot"               App    L 10+primOperator PrimRem{}                = Operator "rem"                App    L 10+primOperator PrimQuotRem{}            = Operator "quotRem"            App    L 10+primOperator PrimIDiv{}               = Operator "div"                App    L 10+primOperator PrimMod{}                = Operator "mod"                App    L 10+primOperator PrimDivMod{}             = Operator "divMod"             App    L 10+primOperator PrimBAnd{}               = Operator ".&."                Infix  L 7+primOperator PrimBOr{}                = Operator ".|."                Infix  L 5+primOperator PrimBXor{}               = Operator "xor"                App    L 10+primOperator PrimBNot{}               = Operator "complement"         App    L 10+primOperator PrimBShiftL{}            = Operator "shiftL"             App    L 10+primOperator PrimBShiftR{}            = Operator "shiftR"             App    L 10+primOperator PrimBRotateL{}           = Operator "rotateL"            App    L 10+primOperator PrimBRotateR{}           = Operator "rotateR"            App    L 10+primOperator PrimPopCount{}           = Operator "popCount"           App    L 10+primOperator PrimCountLeadingZeros{}  = Operator "countLeadingZeros"  App    L 10+primOperator PrimCountTrailingZeros{} = Operator "countTrailingZeros" App    L 10+primOperator PrimFDiv{}               = Operator (pretty '/')         Infix  L 7+primOperator PrimRecip{}              = Operator "recip"              App    L 10+primOperator PrimSin{}                = Operator "sin"                App    L 10+primOperator PrimCos{}                = Operator "cos"                App    L 10+primOperator PrimTan{}                = Operator "tan"                App    L 10+primOperator PrimAsin{}               = Operator "asin"               App    L 10+primOperator PrimAcos{}               = Operator "acos"               App    L 10+primOperator PrimAtan{}               = Operator "atan"               App    L 10+primOperator PrimSinh{}               = Operator "sinh"               App    L 10+primOperator PrimCosh{}               = Operator "cosh"               App    L 10+primOperator PrimTanh{}               = Operator "tanh"               App    L 10+primOperator PrimAsinh{}              = Operator "asinh"              App    L 10+primOperator PrimAcosh{}              = Operator "acosh"              App    L 10+primOperator PrimAtanh{}              = Operator "atanh"              App    L 10+primOperator PrimExpFloating{}        = Operator "exp"                App    L 10+primOperator PrimSqrt{}               = Operator "sqrt"               App    L 10+primOperator PrimLog{}                = Operator "log"                App    L 10+primOperator PrimFPow{}               = Operator "**"                 Infix  R 8+primOperator PrimLogBase{}            = Operator "logBase"            App    L 10+primOperator PrimTruncate{}           = Operator "truncate"           App    L 10+primOperator PrimRound{}              = Operator "round"              App    L 10+primOperator PrimFloor{}              = Operator "floor"              App    L 10+primOperator PrimCeiling{}            = Operator "ceiling"            App    L 10+primOperator PrimAtan2{}              = Operator "atan2"              App    L 10+primOperator PrimIsNaN{}              = Operator "isNaN"              App    L 10+primOperator PrimIsInfinite{}         = Operator "isInfinite"         App    L 10+primOperator PrimLt{}                 = Operator "<"                  Infix  N 4+primOperator PrimGt{}                 = Operator ">"                  Infix  N 4+primOperator PrimLtEq{}               = Operator "<="                 Infix  N 4+primOperator PrimGtEq{}               = Operator ">="                 Infix  N 4+primOperator PrimEq{}                 = Operator "=="                 Infix  N 4+primOperator PrimNEq{}                = Operator "/="                 Infix  N 4+primOperator PrimMax{}                = Operator "max"                App    L 10+primOperator PrimMin{}                = Operator "min"                App    L 10+primOperator PrimLAnd                 = Operator "&&"                 Infix  R 3+primOperator PrimLOr                  = Operator "||"                 Infix  R 2+primOperator PrimLNot                 = Operator "not"                App    L 10+primOperator PrimFromIntegral{}       = Operator "fromIntegral"       App    L 10+primOperator PrimToFloating{}         = Operator "toFloating"         App    L 10+++-- Environments+-- ------------++data Val env where+  Empty ::                    Val ()+  Push  :: Val env -> Adoc -> Val (env, t)++class PrettyEnv env where+  prettyEnv :: Adoc -> Val env++instance PrettyEnv () where+  prettyEnv _ = Empty++instance PrettyEnv env => PrettyEnv (env, t) where+  prettyEnv v =+    let env = prettyEnv v :: Val env+        x   = v <> pretty (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 -> Adoc+prj ZeroIdx      (Push _ v)   = v+prj (SuccIdx ix) (Push env _) = prj ix env+++-- Utilities+-- ---------++shiftwidth :: Int+shiftwidth = 2++infix 0 ?+(?) :: Bool -> (a, a) -> a+True  ? (t,_) = t+False ? (_,f) = f++parensIf :: Bool -> Doc ann -> Doc ann+parensIf True  = group . parens . align+parensIf False = id 
− src/Data/Array/Accelerate/Product.hs
@@ -1,227 +0,0 @@-{-# LANGUAGE ConstraintKinds       #-}-{-# LANGUAGE FlexibleInstances     #-}-{-# LANGUAGE GADTs                 #-}-{-# 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--import Data.Array.Accelerate.Type----- |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)))--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, cst p)-  => IsProduct cst (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p) where-  type ProdRepr (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p) = (ProdRepr (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o), p)-  fromProd _ (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p)-    = (((((((((((((((((), a), b), c), d), e), f), g), h), i), j), k), l), m), n), o), p)-  toProd _ (((((((((((((((((), a), b), c), d), e), f), g), h), i), j), k), l), m), n), o), p)-    = (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p)-  prod p _-    = ProdRsnoc (prod p (undefined :: (a,b,c,d,e,f,g,h,i,j,k,l,m,n,o)))--instance cst a => IsProduct cst (V2 a) where-  type ProdRepr (V2 a)  = ProdRepr (a, a)-  fromProd cst (V2 a b) = fromProd cst (a, b)-  toProd cst p          = let (a, b) = toProd cst p in V2 a b-  prod cst _            = prod cst (undefined :: (a,a))--instance cst a => IsProduct cst (V3 a) where-  type ProdRepr (V3 a)    = ProdRepr (a, a, a)-  fromProd cst (V3 a b c) = fromProd cst (a, b, c)-  toProd cst p            = let (a, b, c) = toProd cst p in V3 a b c-  prod cst _              = prod cst (undefined :: (a,a,a))--instance cst a => IsProduct cst (V4 a) where-  type ProdRepr (V4 a)      = ProdRepr (a, a, a, a)-  fromProd cst (V4 a b c d) = fromProd cst (a, b, c, d)-  toProd cst p              = let (a, b, c, d) = toProd cst p in V4 a b c d-  prod cst _                = prod cst (undefined :: (a,a,a,a))--instance cst a => IsProduct cst (V8 a) where-  type ProdRepr (V8 a) = ProdRepr (a, a, a, a, a, a, a, a)-  fromProd cst (V8 a b c d e f g h)-    = fromProd cst (a, b, c, d, e, f, g, h)-  toProd cst p-    = let (a, b, c, d, e, f, g, h) = toProd cst p-      in  V8 a b c d e f g h-  prod cst _-    = prod cst (undefined :: (a,a,a,a,a,a,a,a))--instance cst a => IsProduct cst (V16 a) where-  type ProdRepr (V16 a) = ProdRepr (a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a)-  fromProd cst (V16 a b c d e f g h i j k l m n o p)-    = fromProd cst (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p)-  toProd cst x-    = let (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p) = toProd cst x-      in  V16 a b c d e f g h i j k l m n o p-  prod cst _-    = prod cst (undefined :: (a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a))-
+ src/Data/Array/Accelerate/Representation/Array.hs view
@@ -0,0 +1,261 @@+{-# LANGUAGE BangPatterns        #-}+{-# LANGUAGE FlexibleInstances   #-}+{-# LANGUAGE GADTs               #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TemplateHaskell     #-}+{-# LANGUAGE TypeApplications    #-}+{-# OPTIONS_HADDOCK hide #-}+-- |+-- Module      : Data.Array.Accelerate.Representation.Array+-- Copyright   : [2008..2020] The Accelerate Team+-- License     : BSD3+--+-- Maintainer  : Trevor L. McDonell <trevor.mcdonell@gmail.com>+-- Stability   : experimental+-- Portability : non-portable (GHC extensions)+--++module Data.Array.Accelerate.Representation.Array+  where++import Data.Array.Accelerate.Array.Data+import Data.Array.Accelerate.Error+import Data.Array.Accelerate.Type+import Data.Array.Accelerate.Representation.Elt+import Data.Array.Accelerate.Representation.Shape                   hiding ( zip )+import Data.Array.Accelerate.Representation.Type++import Language.Haskell.TH+import Language.Haskell.TH.Syntax+import System.IO.Unsafe+import Text.Show                                                    ( showListWith )+import Prelude                                                      hiding ( (!!) )+import qualified Data.Vector.Unboxed                                as U+++-- | Array data type, where the type arguments regard the representation+-- types of the shape and elements.+--+data Array sh e where+  Array :: sh                         -- extent of dimensions = shape+        -> ArrayData e                -- array payload+        -> Array sh 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 = Vector++type Scalar = Array DIM0    -- ^ A singleton array with one element+type Vector = Array DIM1    -- ^ A one-dimensional array+type Matrix = Array DIM2    -- ^ A two-dimensional array++-- | Type witnesses shape and data layout of an array+--+data ArrayR a where+  ArrayR :: { arrayRshape :: ShapeR sh+            , arrayRtype  :: TypeR e+            }+         -> ArrayR (Array sh e)++instance Show (ArrayR a) where+  show (ArrayR shR eR) = "Array DIM" ++ show (rank shR) ++ " " ++ show eR++type ArraysR = TupR ArrayR++instance Show (TupR ArrayR e) where+  show TupRunit           = "()"+  show (TupRsingle aR)    = show aR+  show (TupRpair aR1 aR2) = "(" ++ show aR1 ++ "," ++ show aR2 ++ ")"++showArraysR :: ArraysR a -> ShowS+showArraysR = shows++arraysRarray :: ShapeR sh -> TypeR e -> ArraysR (Array sh e)+arraysRarray shR eR = TupRsingle (ArrayR shR eR)++arraysRpair :: ArrayR a -> ArrayR b -> ArraysR (((), a), b)+arraysRpair a b = TupRunit `TupRpair` TupRsingle a `TupRpair` TupRsingle b++-- | Creates a new, uninitialized Accelerate array.+--+allocateArray :: ArrayR (Array sh e) -> sh -> IO (Array sh e)+allocateArray (ArrayR shR eR) sh = do+  adata  <- newArrayData eR (size shR sh)+  return $! Array sh adata++-- | Create an array from its representation function, applied at each+-- index of the array.+--+fromFunction :: ArrayR (Array sh e) -> sh -> (sh -> e) -> Array sh e+fromFunction repr sh f = unsafePerformIO $! fromFunctionM repr sh (return . f)++-- | Create an array using a monadic function applied at each index.+--+-- @since 1.2.0.0+--+fromFunctionM :: ArrayR (Array sh e) -> sh -> (sh -> IO e) -> IO (Array sh e)+fromFunctionM (ArrayR shR eR) sh f = do+  let !n = size shR sh+  arr <- newArrayData eR n+  --+  let write !i+        | i >= n    = return ()+        | otherwise = do+            v <- f (fromIndex shR sh i)+            writeArrayData eR arr i v+            write (i+1)+  --+  write 0+  return $! arr `seq` Array sh arr+++-- | Convert a list into an Accelerate 'Array' in dense row-major order.+--+fromList :: forall sh e. ArrayR (Array sh e) -> sh -> [e] -> Array sh e+fromList (ArrayR shR eR) sh xs = adata `seq` Array 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 shR sh+    (adata, _) = runArrayData @e $ do+                  arr <- newArrayData eR n+                  let go !i _ | i >= n = return ()+                      go !i (v:vs)     = writeArrayData eR arr i 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 :: ArrayR (Array sh e) -> Array sh e -> [e]+toList (ArrayR shR eR) (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                  = size shR sh+    go !i | i >= n      = []+          | otherwise   = indexArrayData eR adata i : go (i+1)++concatVectors :: forall e. TypeR e -> [Vector e] -> Vector e+concatVectors tR vs = adata `seq` Array ((), len) adata+  where+    offsets     = scanl (+) 0 (map (size dim1 . shape) vs)+    len         = last offsets+    (adata, _)  = runArrayData @e $ do+      arr <- newArrayData tR len+      sequence_ [ writeArrayData tR arr (i + k) (indexArrayData tR ad i)+                | (Array ((), n) ad, k) <- vs `zip` offsets+                , i <- [0 .. n - 1] ]+      return (arr, undefined)++shape :: Array sh e -> sh+shape (Array sh _) = sh++reshape :: HasCallStack => ShapeR sh -> sh -> ShapeR sh' -> Array sh' e -> Array sh e+reshape shR sh shR' (Array sh' adata)+  = boundsCheck "shape mismatch" (size shR sh == size shR' sh')+  $ Array sh adata++(!) :: (ArrayR (Array sh e), Array sh e) -> sh -> e+(!) = uncurry indexArray++(!!) :: (TypeR e, Array sh e) -> Int -> e+(!!) = uncurry linearIndexArray++indexArray :: ArrayR (Array sh e) -> Array sh e -> sh -> e+indexArray (ArrayR shR adR) (Array sh adata) ix = indexArrayData adR adata (toIndex shR sh ix)++linearIndexArray :: TypeR e -> Array sh e -> Int -> e+linearIndexArray adR (Array _ adata) = indexArrayData adR adata++showArray :: (e -> ShowS) -> ArrayR (Array sh e) -> Array sh e -> String+showArray f arrR@(ArrayR shR _) arr@(Array sh _) = case shR of+  ShapeRz                         -> "Scalar Z "                       ++ list+  ShapeRsnoc ShapeRz              -> "Vector (" ++ shapeString ++ ") " ++ list+  ShapeRsnoc (ShapeRsnoc ShapeRz) -> "Matrix (" ++ shapeString ++ ") " ++ showMatrix f arrR arr+  _                               -> "Array ("  ++ shapeString ++ ") " ++ list+  where+    shapeString = showShape shR sh+    list        = showListWith f (toList arrR arr) ""++showArrayShort :: Int -> (e -> ShowS) -> ArrayR (Array sh e) -> Array sh e -> String+showArrayShort n f arrR arr = '[' : go 0 (toList arrR arr)+  where+    go _ []       = "]"+    go i (x:xs)+      | i >= n    = " ..]"+      | otherwise = ',' : f x (go (i+1) xs)++-- 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.+--+showMatrix :: (e -> ShowS) -> ArrayR (Array DIM2 e) -> Array DIM2 e -> String+showMatrix f (ArrayR _ arrR) arr@(Array sh _)+  | rows * cols == 0 = "[]"+  | otherwise        = "\n  [" ++ ppMat 0 0+    where+      (((), rows), cols) = sh+      lengths            = U.generate (rows*cols) (\i -> length (f (linearIndexArray arrR arr i) ""))+      widths             = U.generate cols (\c -> U.maximum (U.generate rows (\r -> lengths U.! (r*cols+c))))+      --+      ppMat :: Int -> Int -> String+      ppMat !r !c | c >= cols = ppMat (r+1) 0+      ppMat !r !c             =+        let+            !i    = r*cols+c+            !l    = lengths U.! i+            !w    = widths  U.! c+            !pad  = 1+            cell  = replicate (w-l+pad) ' ' ++ f (linearIndexArray arrR arr i) ""+            --+            before+              | r > 0 && c == 0 = "\n   "+              | otherwise       = ""+            --+            after+              | r >= rows-1 && c >= cols-1 = "]"+              | otherwise                  = ',' : ppMat r (c+1)+        in+        before ++ cell ++ after++reduceRank :: ArrayR (Array (sh, Int) e) -> ArrayR (Array sh e)+reduceRank (ArrayR (ShapeRsnoc shR) aeR) = ArrayR shR aeR++rnfArray :: ArrayR a -> a -> ()+rnfArray (ArrayR shR adR) (Array sh ad) = rnfShape shR sh `seq` rnfArrayData adR ad++rnfArrayR :: ArrayR arr -> ()+rnfArrayR (ArrayR shR tR) = rnfShapeR shR `seq` rnfTupR rnfScalarType tR++rnfArraysR :: ArraysR arrs -> arrs -> ()+rnfArraysR TupRunit           ()      = ()+rnfArraysR (TupRsingle arrR)  arr     = rnfArray arrR arr+rnfArraysR (TupRpair aR1 aR2) (a1,a2) = rnfArraysR aR1 a1 `seq` rnfArraysR aR2 a2++liftArrayR :: ArrayR a -> Q (TExp (ArrayR a))+liftArrayR (ArrayR shR tR) = [|| ArrayR $$(liftShapeR shR) $$(liftTypeR tR) ||]++liftArraysR :: ArraysR arrs -> Q (TExp (ArraysR arrs))+liftArraysR TupRunit          = [|| TupRunit ||]+liftArraysR (TupRsingle repr) = [|| TupRsingle $$(liftArrayR repr) ||]+liftArraysR (TupRpair a b)    = [|| TupRpair $$(liftArraysR a) $$(liftArraysR b) ||]++liftArray :: forall sh e. ArrayR (Array sh e) -> Array sh e -> Q (TExp (Array sh e))+liftArray (ArrayR shR adR) (Array sh adata) =+  [|| Array $$(liftElt (shapeType shR) sh) $$(liftArrayData sz adR adata) ||] `at` [t| Array $(liftTypeQ (shapeType shR)) $(liftTypeQ adR) |]+  where+    sz :: Int+    sz = size shR sh++    at :: Q (TExp t) -> Q Type -> Q (TExp t)+    at e t = unsafeTExpCoerce $ sigE (unTypeQ e) t+
+ src/Data/Array/Accelerate/Representation/Elt.hs view
@@ -0,0 +1,160 @@+{-# LANGUAGE GADTs           #-}+{-# LANGUAGE MagicHash       #-}+{-# LANGUAGE TemplateHaskell #-}+{-# LANGUAGE TupleSections   #-}+{-# OPTIONS_HADDOCK hide #-}+-- |+-- Module      : Data.Array.Accelerate.Representation.Elt+-- Copyright   : [2008..2020] The Accelerate Team+-- License     : BSD3+--+-- Maintainer  : Trevor L. McDonell <trevor.mcdonell@gmail.com>+-- Stability   : experimental+-- Portability : non-portable (GHC extensions)+--++module Data.Array.Accelerate.Representation.Elt+  where++import Data.Array.Accelerate.Representation.Type+import Data.Array.Accelerate.Type+import Data.Primitive.Vec++import Control.Monad.ST+import Data.List                                                    ( intercalate )+import Data.Primitive.ByteArray+import Foreign.Storable+import Language.Haskell.TH+++undefElt :: TypeR t -> t+undefElt = tuple+  where+    tuple :: TypeR t -> t+    tuple TupRunit         = ()+    tuple (TupRpair ta tb) = (tuple ta, tuple tb)+    tuple (TupRsingle t)   = scalar t++    scalar :: ScalarType t -> t+    scalar (SingleScalarType t) = single t+    scalar (VectorScalarType t) = vector t++    vector :: VectorType t -> t+    vector (VectorType n t) = runST $ do+      mba           <- newByteArray (n * bytesElt (TupRsingle (SingleScalarType t)))+      ByteArray ba# <- unsafeFreezeByteArray mba+      return (Vec ba#)++    single :: SingleType t -> t+    single (NumSingleType t) = num t++    num :: NumType t -> t+    num (IntegralNumType t) = integral t+    num (FloatingNumType t) = floating t++    integral :: IntegralType t -> t+    integral TypeInt    = 0+    integral TypeInt8   = 0+    integral TypeInt16  = 0+    integral TypeInt32  = 0+    integral TypeInt64  = 0+    integral TypeWord   = 0+    integral TypeWord8  = 0+    integral TypeWord16 = 0+    integral TypeWord32 = 0+    integral TypeWord64 = 0++    floating :: FloatingType t -> t+    floating TypeHalf   = 0+    floating TypeFloat  = 0+    floating TypeDouble = 0++bytesElt :: TypeR e -> Int+bytesElt = tuple+  where+    tuple :: TypeR t -> Int+    tuple TupRunit         = 0+    tuple (TupRpair ta tb) = tuple ta + tuple tb+    tuple (TupRsingle t)   = scalar t++    scalar :: ScalarType t -> Int+    scalar (SingleScalarType t) = single t+    scalar (VectorScalarType t) = vector t++    vector :: VectorType t -> Int+    vector (VectorType n t) = n * single t++    single :: SingleType t -> Int+    single (NumSingleType t) = num t++    num :: NumType t -> Int+    num (IntegralNumType t) = integral t+    num (FloatingNumType t) = floating t++    integral :: IntegralType t -> Int+    integral TypeInt    = sizeOf (undefined::Int)+    integral TypeInt8   = 1+    integral TypeInt16  = 2+    integral TypeInt32  = 4+    integral TypeInt64  = 8+    integral TypeWord   = sizeOf (undefined::Word)+    integral TypeWord8  = 1+    integral TypeWord16 = 2+    integral TypeWord32 = 4+    integral TypeWord64 = 8++    floating :: FloatingType t -> Int+    floating TypeHalf   = 2+    floating TypeFloat  = 4+    floating TypeDouble = 8++showElt :: TypeR e -> e -> String+showElt t v = showsElt t v ""++showsElt :: TypeR e -> e -> ShowS+showsElt = tuple+  where+    tuple :: TypeR e -> e -> ShowS+    tuple TupRunit         ()       = showString "()"+    tuple (TupRpair t1 t2) (e1, e2) = showString "(" . tuple t1 e1 . showString ", " . tuple t2 e2 . showString ")"+    tuple (TupRsingle tp)  val      = scalar tp val++    scalar :: ScalarType e -> e -> ShowS+    scalar (SingleScalarType t) e = single t e+    scalar (VectorScalarType t) e = vector t e++    single :: SingleType e -> e -> ShowS+    single (NumSingleType t) = num t++    num :: NumType e -> e -> ShowS+    num (IntegralNumType t) = integral t+    num (FloatingNumType t) = floating t++    integral :: IntegralType e -> e -> ShowS+    integral TypeInt    = shows+    integral TypeInt8   = shows+    integral TypeInt16  = shows+    integral TypeInt32  = shows+    integral TypeInt64  = shows+    integral TypeWord   = shows+    integral TypeWord8  = shows+    integral TypeWord16 = shows+    integral TypeWord32 = shows+    integral TypeWord64 = shows++    floating :: FloatingType e -> e -> ShowS+    floating TypeHalf   = shows+    floating TypeFloat  = shows+    floating TypeDouble = shows++    vector :: VectorType (Vec n a) -> Vec n a -> ShowS+    vector (VectorType _ s) vec+      | SingleDict <- singleDict s+      = showString+      $ "<" ++ intercalate ", " ((\v -> single s v "") <$> listOfVec vec) ++ ">"++liftElt :: TypeR t -> t -> Q (TExp t)+liftElt TupRunit         ()    = [|| () ||]+liftElt (TupRsingle t)   x     = [|| $$(liftScalar t x) ||]+liftElt (TupRpair ta tb) (a,b) = [|| ($$(liftElt ta a), $$(liftElt tb b)) ||]+
+ src/Data/Array/Accelerate/Representation/Shape.hs view
@@ -0,0 +1,196 @@+{-# LANGUAGE GADTs           #-}+{-# LANGUAGE TupleSections   #-}+{-# LANGUAGE TemplateHaskell #-}+{-# OPTIONS_HADDOCK hide #-}+-- |+-- Module      : Data.Array.Accelerate.Representation.Shape+-- Copyright   : [2008..2020] The Accelerate Team+-- License     : BSD3+--+-- Maintainer  : Trevor L. McDonell <trevor.mcdonell@gmail.com>+-- Stability   : experimental+-- Portability : non-portable (GHC extensions)+--++module Data.Array.Accelerate.Representation.Shape+  where++import Data.Array.Accelerate.Error+import Data.Array.Accelerate.Type+import Data.Array.Accelerate.Representation.Type++import Language.Haskell.TH+import Prelude                                                      hiding ( zip )++import GHC.Base                                                     ( quotInt, remInt )+++-- | Shape and index representations as nested pairs+--+data ShapeR sh where+  ShapeRz    :: ShapeR ()+  ShapeRsnoc :: ShapeR sh -> ShapeR (sh, Int)++-- | Nicely format a shape as a string+--+showShape :: ShapeR sh -> sh -> String+showShape shr = foldr (\sh str -> str ++ " :. " ++ show sh) "Z" . shapeToList shr++-- Synonyms for common shape types+--+type DIM0 = ()+type DIM1 = ((), Int)+type DIM2 = (((), Int), Int)+type DIM3 = ((((), Int), Int), Int)++dim0 :: ShapeR DIM0+dim0 = ShapeRz++dim1 :: ShapeR DIM1+dim1 = ShapeRsnoc dim0++dim2 :: ShapeR DIM2+dim2 = ShapeRsnoc dim1++dim3 :: ShapeR DIM3+dim3 = ShapeRsnoc dim2++-- | Number of dimensions of a /shape/ or /index/ (>= 0)+--+rank :: ShapeR sh -> Int+rank ShapeRz          = 0+rank (ShapeRsnoc shr) = rank shr + 1++-- | Total number of elements in an array of the given shape+--+size :: ShapeR sh -> sh -> Int+size ShapeRz () = 1+size (ShapeRsnoc shr) (sh, sz)+  | sz <= 0   = 0+  | otherwise = size shr sh * sz++-- | The empty shape+--+empty :: ShapeR sh -> sh+empty ShapeRz          = ()+empty (ShapeRsnoc shr) = (empty shr, 0)++-- | Yield the intersection of two shapes+--+intersect :: ShapeR sh -> sh -> sh -> sh+intersect = zip min++-- | Yield the union of two shapes+--+union :: ShapeR sh -> sh -> sh -> sh+union = zip max++zip :: (Int -> Int -> Int) -> ShapeR sh -> sh -> sh -> sh+zip _ ShapeRz          ()      ()      = ()+zip f (ShapeRsnoc shr) (as, a) (bs, b) = (zip f shr as bs, f a b)++eq :: ShapeR sh -> sh -> sh -> Bool+eq ShapeRz          ()      ()        = True+eq (ShapeRsnoc shr) (sh, i) (sh', i') = i == i' && eq shr 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 :: HasCallStack => ShapeR sh -> sh -> sh -> Int+toIndex ShapeRz () () = 0+toIndex (ShapeRsnoc shr) (sh, sz) (ix, i)+  = indexCheck i sz+  $ toIndex shr sh ix * sz + i++-- | Inverse of 'toIndex'+--+fromIndex :: HasCallStack => ShapeR sh -> sh -> Int -> sh+fromIndex ShapeRz () _ = ()+fromIndex (ShapeRsnoc shr) (sh, sz) i+  = (fromIndex shr sh (i `quotInt` sz), r)+  -- If we assume that the index is in range, there is no point in computing+  -- the remainder for the highest dimension since i < sz must hold.+  --+  where+    r = case shr of -- Check if rank of shr is 0+      ShapeRz -> indexCheck i sz i+      _       -> i `remInt` sz++-- | Iterate through the entire shape, applying the function in the second+-- argument; third argument combines results and fourth is an initial value+-- that is combined with the results; the index space is traversed in+-- row-major order+--+iter :: ShapeR sh -> sh -> (sh -> a) -> (a -> a -> a) -> a -> a+iter ShapeRz          ()       f _ _ = f ()+iter (ShapeRsnoc shr) (sh, sz) f c r = iter shr sh (\ix -> iter' (ix,0)) c r+  where+    iter' (ix,i) | i >= sz   = r+                 | otherwise = f (ix,i) `c` iter' (ix,i+1)++-- | Variant of 'iter' without an initial value+--+iter1 :: HasCallStack => ShapeR sh -> sh -> (sh -> a) -> (a -> a -> a) -> a+iter1 ShapeRz          ()       f _ = f ()+iter1 (ShapeRsnoc _  ) (_,  0)  _ _ = boundsError "empty iteration space"+iter1 (ShapeRsnoc shr) (sh, sz) f c = iter1 shr sh (\ix -> iter1' (ix,0)) c+  where+    iter1' (ix,i) | i == sz-1 = f (ix,i)+                  | otherwise = f (ix,i) `c` iter1' (ix,i+1)++-- Operations to facilitate conversion with IArray++-- | Convert a minpoint-maxpoint index into a shape+--+rangeToShape :: ShapeR sh -> (sh, sh) -> sh+rangeToShape ShapeRz          ((), ())                 = ()+rangeToShape (ShapeRsnoc shr) ((sh1, sz1), (sh2, sz2)) = (rangeToShape shr (sh1, sh2), sz2 - sz1 + 1)++-- | Converse of 'rangeToShape'+--+shapeToRange :: ShapeR sh -> sh -> (sh, sh)+shapeToRange ShapeRz          ()       = ((), ())+shapeToRange (ShapeRsnoc shr) (sh, sz) = let (low, high) = shapeToRange shr sh in ((low, 0), (high, sz - 1))++-- | Convert a shape or index into its list of dimensions+--+shapeToList :: ShapeR sh -> sh -> [Int]+shapeToList ShapeRz          ()      = []+shapeToList (ShapeRsnoc shr) (sh,sz) = sz : shapeToList shr sh++-- | Convert a list of dimensions into a shape+--+listToShape :: HasCallStack => ShapeR sh -> [Int] -> sh+listToShape shr ds =+  case listToShape' shr ds of+    Just sh -> sh+    Nothing -> error "listToShape: unable to convert list to a shape at the specified type"++-- | Attempt to convert a list of dimensions into a shape+--+listToShape' :: ShapeR sh -> [Int] -> Maybe sh+listToShape' ShapeRz          []     = Just ()+listToShape' (ShapeRsnoc shr) (x:xs) = (, x) <$> listToShape' shr xs+listToShape' _                _      = Nothing++shapeType :: ShapeR sh -> TypeR sh+shapeType ShapeRz          = TupRunit+shapeType (ShapeRsnoc shr) =+  shapeType shr+  `TupRpair`+  TupRsingle (SingleScalarType (NumSingleType (IntegralNumType TypeInt)))++rnfShape :: ShapeR sh -> sh -> ()+rnfShape ShapeRz          ()      = ()+rnfShape (ShapeRsnoc shr) (sh, s) = s `seq` rnfShape shr sh++rnfShapeR :: ShapeR sh -> ()+rnfShapeR ShapeRz          = ()+rnfShapeR (ShapeRsnoc shr) = rnfShapeR shr++liftShapeR :: ShapeR sh -> Q (TExp (ShapeR sh))+liftShapeR ShapeRz         = [|| ShapeRz ||]+liftShapeR (ShapeRsnoc sh) = [|| ShapeRsnoc $$(liftShapeR sh) ||]+
+ src/Data/Array/Accelerate/Representation/Slice.hs view
@@ -0,0 +1,108 @@+{-# LANGUAGE FlexibleInstances   #-}+{-# LANGUAGE GADTs               #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TemplateHaskell     #-}+{-# LANGUAGE TypeApplications    #-}+{-# LANGUAGE TypeFamilies        #-}+{-# OPTIONS_HADDOCK hide #-}+-- |+-- Module      : Data.Array.Accelerate.Representation.Slice+-- Copyright   : [2008..2020] The Accelerate Team+-- License     : BSD3+--+-- Maintainer  : Trevor L. McDonell <trevor.mcdonell@gmail.com>+-- Stability   : experimental+-- Portability : non-portable (GHC extensions)+--++module Data.Array.Accelerate.Representation.Slice+  where++import Data.Array.Accelerate.Representation.Shape++import Language.Haskell.TH+++-- | Class of slice representations (which are nested pairs)+--+class Slice sl where+  type SliceShape    sl      -- the projected slice+  type CoSliceShape  sl      -- the complement of the slice+  type FullShape     sl      -- the combined dimension+  sliceIndex :: SliceIndex sl (SliceShape sl) (CoSliceShape sl) (FullShape sl)++instance Slice () where+  type SliceShape    () = ()+  type CoSliceShape  () = ()+  type FullShape     () = ()+  sliceIndex = SliceNil++instance Slice sl => Slice (sl, ()) where+  type SliceShape   (sl, ()) = (SliceShape  sl, Int)+  type CoSliceShape (sl, ()) = CoSliceShape sl+  type FullShape    (sl, ()) = (FullShape   sl, Int)+  sliceIndex = SliceAll (sliceIndex @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 = SliceFixed (sliceIndex @sl)++-- |Generalised array index, which may index only in a subset of the dimensions+-- of a shape.+--+data SliceIndex ix slice coSlice sliceDim where+  SliceNil   :: SliceIndex () () () ()+  SliceAll   :: SliceIndex ix slice co dim -> SliceIndex (ix, ()) (slice, Int) co       (dim, Int)+  SliceFixed :: SliceIndex ix slice co dim -> SliceIndex (ix, Int) slice      (co, Int) (dim, Int)++instance Show (SliceIndex ix slice coSlice sliceDim) where+  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++sliceShapeR :: SliceIndex slix sl co dim -> ShapeR sl+sliceShapeR SliceNil        = ShapeRz+sliceShapeR (SliceAll sl)   = ShapeRsnoc $ sliceShapeR sl+sliceShapeR (SliceFixed sl) = sliceShapeR sl++sliceDomainR :: SliceIndex slix sl co dim -> ShapeR dim+sliceDomainR SliceNil        = ShapeRz+sliceDomainR (SliceAll sl)   = ShapeRsnoc $ sliceDomainR sl+sliceDomainR (SliceFixed sl) = ShapeRsnoc $ sliceDomainR sl++-- | Enumerate all slices within a given bound. The innermost dimension changes+-- most rapidly.+--+-- See 'Data.Array.Accelerate.Sugar.Slice.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]]++rnfSliceIndex :: SliceIndex ix slice co sh -> ()+rnfSliceIndex SliceNil        = ()+rnfSliceIndex (SliceAll sh)   = rnfSliceIndex sh+rnfSliceIndex (SliceFixed sh) = rnfSliceIndex sh++liftSliceIndex :: SliceIndex ix slice co sh -> Q (TExp (SliceIndex ix slice co sh))+liftSliceIndex SliceNil          = [|| SliceNil ||]+liftSliceIndex (SliceAll rest)   = [|| SliceAll $$(liftSliceIndex rest) ||]+liftSliceIndex (SliceFixed rest) = [|| SliceFixed $$(liftSliceIndex rest) ||]+
+ src/Data/Array/Accelerate/Representation/Stencil.hs view
@@ -0,0 +1,161 @@+{-# LANGUAGE GADTs           #-}+{-# LANGUAGE TemplateHaskell #-}+{-# OPTIONS_HADDOCK hide #-}+-- |+-- Module      : Data.Array.Accelerate.Representation.Stencil+-- Copyright   : [2008..2020] The Accelerate Team+-- License     : BSD3+--+-- Maintainer  : Trevor L. McDonell <trevor.mcdonell@gmail.com>+-- Stability   : experimental+-- Portability : non-portable (GHC extensions)+--++module Data.Array.Accelerate.Representation.Stencil (++  -- ** Stencil patterns+  StencilR(..),+  stencilArrayR,+  stencilR, stencilEltR, stencilShapeR, stencilHalo,+  rnfStencilR,+  liftStencilR,++) where++import Data.Array.Accelerate.Representation.Array+import Data.Array.Accelerate.Representation.Shape+import Data.Array.Accelerate.Representation.Type++import Language.Haskell.TH+++-- | GADT reifying the 'Stencil' class+--+data StencilR sh e pat where+  StencilRunit3 :: TypeR e -> StencilR DIM1 e (Tup3 e e e)+  StencilRunit5 :: TypeR e -> StencilR DIM1 e (Tup5 e e e e e)+  StencilRunit7 :: TypeR e -> StencilR DIM1 e (Tup7 e e e e e e e)+  StencilRunit9 :: TypeR e -> StencilR DIM1 e (Tup9 e e e e e e e e e)++  StencilRtup3  :: StencilR sh e pat1+                -> StencilR sh e pat2+                -> StencilR sh e pat3+                -> StencilR (sh, Int) e (Tup3 pat1 pat2 pat3)++  StencilRtup5  :: StencilR sh e pat1+                -> StencilR sh e pat2+                -> StencilR sh e pat3+                -> StencilR sh e pat4+                -> StencilR sh e pat5+                -> StencilR (sh, Int) e (Tup5 pat1 pat2 pat3 pat4 pat5)++  StencilRtup7  :: StencilR sh e pat1+                -> StencilR sh e pat2+                -> StencilR sh e pat3+                -> StencilR sh e pat4+                -> StencilR sh e pat5+                -> StencilR sh e pat6+                -> StencilR sh e pat7+                -> StencilR (sh, Int) e (Tup7 pat1 pat2 pat3 pat4 pat5 pat6 pat7)++  StencilRtup9  :: StencilR sh e pat1+                -> StencilR sh e pat2+                -> StencilR sh e pat3+                -> StencilR sh e pat4+                -> StencilR sh e pat5+                -> StencilR sh e pat6+                -> StencilR sh e pat7+                -> StencilR sh e pat8+                -> StencilR sh e pat9+                -> StencilR (sh, Int) e (Tup9 pat1 pat2 pat3 pat4 pat5 pat6 pat7 pat8 pat9)++stencilEltR :: StencilR sh e pat -> TypeR e+stencilEltR (StencilRunit3 t) = t+stencilEltR (StencilRunit5 t) = t+stencilEltR (StencilRunit7 t) = t+stencilEltR (StencilRunit9 t) = t+stencilEltR (StencilRtup3 sR _ _) = stencilEltR sR+stencilEltR (StencilRtup5 sR _ _ _ _) = stencilEltR sR+stencilEltR (StencilRtup7 sR _ _ _ _ _ _) = stencilEltR sR+stencilEltR (StencilRtup9 sR _ _ _ _ _ _ _ _) = stencilEltR sR++stencilShapeR :: StencilR sh e pat -> ShapeR sh+stencilShapeR (StencilRunit3 _) = ShapeRsnoc ShapeRz+stencilShapeR (StencilRunit5 _) = ShapeRsnoc ShapeRz+stencilShapeR (StencilRunit7 _) = ShapeRsnoc ShapeRz+stencilShapeR (StencilRunit9 _) = ShapeRsnoc ShapeRz+stencilShapeR (StencilRtup3 sR _ _) = ShapeRsnoc $ stencilShapeR sR+stencilShapeR (StencilRtup5 sR _ _ _ _) = ShapeRsnoc $ stencilShapeR sR+stencilShapeR (StencilRtup7 sR _ _ _ _ _ _) = ShapeRsnoc $ stencilShapeR sR+stencilShapeR (StencilRtup9 sR _ _ _ _ _ _ _ _) = ShapeRsnoc $ stencilShapeR sR++stencilR :: StencilR sh e pat -> TypeR pat+stencilR (StencilRunit3 t) = tupR3 t t t+stencilR (StencilRunit5 t) = tupR5 t t t t t+stencilR (StencilRunit7 t) = tupR7 t t t t t t t+stencilR (StencilRunit9 t) = tupR9 t t t t t t t t t+stencilR (StencilRtup3 s1 s2 s3) = tupR3 (stencilR s1) (stencilR s2) (stencilR s3)+stencilR (StencilRtup5 s1 s2 s3 s4 s5) = tupR5 (stencilR s1) (stencilR s2) (stencilR s3) (stencilR s4) (stencilR s5)+stencilR (StencilRtup7 s1 s2 s3 s4 s5 s6 s7) = tupR7 (stencilR s1) (stencilR s2) (stencilR s3) (stencilR s4) (stencilR s5) (stencilR s6) (stencilR s7)+stencilR (StencilRtup9 s1 s2 s3 s4 s5 s6 s7 s8 s9) = tupR9 (stencilR s1) (stencilR s2) (stencilR s3) (stencilR s4) (stencilR s5) (stencilR s6) (stencilR s7) (stencilR s8) (stencilR s9)++stencilArrayR :: StencilR sh e pat -> ArrayR (Array sh e)+stencilArrayR sR = ArrayR (stencilShapeR sR) (stencilEltR sR)++stencilHalo :: StencilR sh e stencil -> (ShapeR sh, sh)+stencilHalo = go'+  where+    go' :: StencilR sh e stencil -> (ShapeR sh, sh)+    go' StencilRunit3{} = (dim1, ((), 1))+    go' StencilRunit5{} = (dim1, ((), 2))+    go' StencilRunit7{} = (dim1, ((), 3))+    go' StencilRunit9{} = (dim1, ((), 4))+    --+    go' (StencilRtup3 a b c            ) = (ShapeRsnoc shR, cons shR 1 $ foldl1 (union shR) [a', go b, go c])+      where (shR, a') = go' a+    go' (StencilRtup5 a b c d e        ) = (ShapeRsnoc shR, cons shR 2 $ foldl1 (union shR) [a', go b, go c, go d, go e])+      where (shR, a') = go' a+    go' (StencilRtup7 a b c d e f g    ) = (ShapeRsnoc shR, cons shR 3 $ foldl1 (union shR) [a', go b, go c, go d, go e, go f, go g])+      where (shR, a') = go' a+    go' (StencilRtup9 a b c d e f g h i) = (ShapeRsnoc shR, cons shR 4 $ foldl1 (union shR) [a', go b, go c, go d, go e, go f, go g, go h, go i])+      where (shR, a') = go' a++    go :: StencilR sh e stencil -> sh+    go = snd . go'++    cons :: ShapeR sh -> Int -> sh -> (sh, Int)+    cons ShapeRz          ix ()       = ((), ix)+    cons (ShapeRsnoc shr) ix (sh, sz) = (cons shr ix sh, sz)++tupR3 :: TupR s t1 -> TupR s t2 -> TupR s t3 -> TupR s (Tup3 t1 t2 t3)+tupR3 t1 t2 t3 = TupRunit `TupRpair` t1 `TupRpair` t2 `TupRpair` t3++tupR5 :: TupR s t1 -> TupR s t2 -> TupR s t3 -> TupR s t4 -> TupR s t5 -> TupR s (Tup5 t1 t2 t3 t4 t5)+tupR5 t1 t2 t3 t4 t5 = TupRunit `TupRpair` t1 `TupRpair` t2 `TupRpair` t3 `TupRpair` t4 `TupRpair` t5++tupR7 :: TupR s t1 -> TupR s t2 -> TupR s t3 -> TupR s t4 -> TupR s t5 -> TupR s t6 -> TupR s t7 -> TupR s (Tup7 t1 t2 t3 t4 t5 t6 t7)+tupR7 t1 t2 t3 t4 t5 t6 t7 = TupRunit `TupRpair` t1 `TupRpair` t2 `TupRpair` t3 `TupRpair` t4 `TupRpair` t5 `TupRpair` t6 `TupRpair` t7++tupR9 :: TupR s t1 -> TupR s t2 -> TupR s t3 -> TupR s t4 -> TupR s t5 -> TupR s t6 -> TupR s t7 -> TupR s t8 -> TupR s t9 -> TupR s (Tup9 t1 t2 t3 t4 t5 t6 t7 t8 t9)+tupR9 t1 t2 t3 t4 t5 t6 t7 t8 t9 = TupRunit `TupRpair` t1 `TupRpair` t2 `TupRpair` t3 `TupRpair` t4 `TupRpair` t5 `TupRpair` t6 `TupRpair` t7 `TupRpair` t8 `TupRpair` t9++rnfStencilR :: StencilR sh e pat -> ()+rnfStencilR (StencilRunit3 t) = rnfTypeR t+rnfStencilR (StencilRunit5 t) = rnfTypeR t+rnfStencilR (StencilRunit7 t) = rnfTypeR t+rnfStencilR (StencilRunit9 t) = rnfTypeR t+rnfStencilR (StencilRtup3 s1 s2 s3) = rnfStencilR s1 `seq` rnfStencilR s2 `seq` rnfStencilR s3+rnfStencilR (StencilRtup5 s1 s2 s3 s4 s5) = rnfStencilR s1 `seq` rnfStencilR s2 `seq` rnfStencilR s3 `seq` rnfStencilR s4 `seq` rnfStencilR s5+rnfStencilR (StencilRtup7 s1 s2 s3 s4 s5 s6 s7) = rnfStencilR s1 `seq` rnfStencilR s2 `seq` rnfStencilR s3 `seq` rnfStencilR s4 `seq` rnfStencilR s5 `seq` rnfStencilR s6 `seq` rnfStencilR s7+rnfStencilR (StencilRtup9 s1 s2 s3 s4 s5 s6 s7 s8 s9) = rnfStencilR s1 `seq` rnfStencilR s2 `seq` rnfStencilR s3 `seq` rnfStencilR s4 `seq` rnfStencilR s5 `seq` rnfStencilR s6 `seq` rnfStencilR s7 `seq` rnfStencilR s8 `seq` rnfStencilR s9++liftStencilR :: StencilR sh e pat -> Q (TExp (StencilR sh e pat))+liftStencilR (StencilRunit3 tp) = [|| StencilRunit3 $$(liftTypeR tp) ||]+liftStencilR (StencilRunit5 tp) = [|| StencilRunit5 $$(liftTypeR tp) ||]+liftStencilR (StencilRunit7 tp) = [|| StencilRunit7 $$(liftTypeR tp) ||]+liftStencilR (StencilRunit9 tp) = [|| StencilRunit9 $$(liftTypeR tp) ||]+liftStencilR (StencilRtup3 s1 s2 s3) = [|| StencilRtup3 $$(liftStencilR s1) $$(liftStencilR s2) $$(liftStencilR s3) ||]+liftStencilR (StencilRtup5 s1 s2 s3 s4 s5) = [|| StencilRtup5 $$(liftStencilR s1) $$(liftStencilR s2) $$(liftStencilR s3) $$(liftStencilR s4) $$(liftStencilR s5) ||]+liftStencilR (StencilRtup7 s1 s2 s3 s4 s5 s6 s7) = [|| StencilRtup7 $$(liftStencilR s1) $$(liftStencilR s2) $$(liftStencilR s3) $$(liftStencilR s4) $$(liftStencilR s5) $$(liftStencilR s6) $$(liftStencilR s7) ||]+liftStencilR (StencilRtup9 s1 s2 s3 s4 s5 s6 s7 s8 s9) = [|| StencilRtup9 $$(liftStencilR s1) $$(liftStencilR s2) $$(liftStencilR s3) $$(liftStencilR s4) $$(liftStencilR s5) $$(liftStencilR s6) $$(liftStencilR s7) $$(liftStencilR s8) $$(liftStencilR s9) ||]+
+ src/Data/Array/Accelerate/Representation/Tag.hs view
@@ -0,0 +1,68 @@+{-# LANGUAGE GADTs           #-}+{-# LANGUAGE TemplateHaskell #-}+{-# OPTIONS_HADDOCK hide #-}+-- |+-- Module      : Data.Array.Accelerate.Representation.Tag+-- Copyright   : [2008..2020] The Accelerate Team+-- License     : BSD3+--+-- Maintainer  : Trevor L. McDonell <trevor.mcdonell@gmail.com>+-- Stability   : experimental+-- Portability : non-portable (GHC extensions)+--++module Data.Array.Accelerate.Representation.Tag+  where++import Data.Array.Accelerate.Type++import Language.Haskell.TH+++-- | The type of the runtime value used to distinguish constructor+-- alternatives in a sum type.+--+type TAG = Word8++-- | This structure both witnesses the layout of our representation types+-- (as TupR does) and represents a complete path of pattern matching+-- through this type. It indicates which fields of the structure represent+-- the union tags (TagRtag) or store undefined values (TagRundef).+--+-- The function 'eltTags' produces all valid paths through the type. For+-- example the type '(Bool,Bool)' produces the following:+--+--   ghci> putStrLn . unlines . map show $ eltTags @(Bool,Bool)+--   (((),(0#,())),(0#,()))     -- (False, False)+--   (((),(0#,())),(1#,()))     -- (False, True)+--   (((),(1#,())),(0#,()))     -- (True, False)+--   (((),(1#,())),(1#,()))     -- (True, True)+--+data TagR a where+  TagRunit   :: TagR ()+  TagRsingle :: ScalarType a -> TagR a+  TagRundef  :: ScalarType a -> TagR a+  TagRtag    :: TAG -> TagR a -> TagR (TAG, a)+  TagRpair   :: TagR a -> TagR b -> TagR (a, b)++instance Show (TagR a) where+  show TagRunit         = "()"+  show TagRsingle{}     = "."+  show TagRundef{}      = "undef"+  show (TagRtag v t)    = "(" ++ show v ++ "#," ++ show t ++ ")"+  show (TagRpair ta tb) = "(" ++ show ta ++ "," ++ show tb ++ ")"++rnfTag :: TagR a -> ()+rnfTag TagRunit         = ()+rnfTag (TagRsingle t)   = rnfScalarType t+rnfTag (TagRundef t)    = rnfScalarType t+rnfTag (TagRtag v t)    = v `seq` rnfTag t+rnfTag (TagRpair ta tb) = rnfTag ta `seq` rnfTag tb++liftTag :: TagR a -> Q (TExp (TagR a))+liftTag TagRunit         = [|| TagRunit ||]+liftTag (TagRsingle t)   = [|| TagRsingle $$(liftScalarType t) ||]+liftTag (TagRundef t)    = [|| TagRundef $$(liftScalarType t) ||]+liftTag (TagRtag v t)    = [|| TagRtag v $$(liftTag t) ||]+liftTag (TagRpair ta tb) = [|| TagRpair $$(liftTag ta) $$(liftTag tb) ||]+
+ src/Data/Array/Accelerate/Representation/Type.hs view
@@ -0,0 +1,118 @@+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE GADTs             #-}+{-# LANGUAGE RankNTypes        #-}+{-# LANGUAGE TemplateHaskell   #-}+{-# OPTIONS_HADDOCK hide #-}+-- |+-- Module      : Data.Array.Accelerate.Representation.Type+-- Copyright   : [2008..2020] The Accelerate Team+-- License     : BSD3+--+-- Maintainer  : Trevor L. McDonell <trevor.mcdonell@gmail.com>+-- Stability   : experimental+-- Portability : non-portable (GHC extensions)+--++module Data.Array.Accelerate.Representation.Type+  where++import Data.Array.Accelerate.Type+import Data.Primitive.Vec++import Language.Haskell.TH+++-- | Both arrays (Acc) and expressions (Exp) are represented as nested+-- pairs consisting of:+--+--   * unit (void)+--+--   * pairs: representing compound values (i.e. tuples) where each component+--     will be stored in a separate array.+--+--   * single array / scalar types+--     in case of expressions: values which go in registers. These may be single value+--     types such as int and float, or SIMD vectors of single value types such+--     as <4 * float>. We do not allow vectors-of-vectors.+--+data TupR s a where+  TupRunit   ::                         TupR s ()+  TupRsingle :: s a                  -> TupR s a+  TupRpair   :: TupR s a -> TupR s b -> TupR s (a, b)++instance Show (TupR ScalarType a) where+  show TupRunit       = "()"+  show (TupRsingle t) = show t+  show (TupRpair a b) = "(" ++ show a ++ "," ++ show b ++")"++type TypeR = TupR ScalarType++rnfTupR :: (forall b. s b -> ()) -> TupR s a -> ()+rnfTupR _ TupRunit       = ()+rnfTupR f (TupRsingle s) = f s+rnfTupR f (TupRpair a b) = rnfTupR f a `seq` rnfTupR f b++rnfTypeR :: TypeR t -> ()+rnfTypeR = rnfTupR rnfScalarType++liftTupR :: (forall b. s b -> Q (TExp (s b))) -> TupR s a -> Q (TExp (TupR s a))+liftTupR _ TupRunit       = [|| TupRunit ||]+liftTupR f (TupRsingle s) = [|| TupRsingle $$(f s) ||]+liftTupR f (TupRpair a b) = [|| TupRpair $$(liftTupR f a) $$(liftTupR f b) ||]++liftTypeR :: TypeR t -> Q (TExp (TypeR t))+liftTypeR TupRunit         = [|| TupRunit ||]+liftTypeR (TupRsingle t)   = [|| TupRsingle $$(liftScalarType t) ||]+liftTypeR (TupRpair ta tb) = [|| TupRpair $$(liftTypeR ta) $$(liftTypeR tb) ||]++liftTypeQ :: TypeR t -> TypeQ+liftTypeQ = tuple+  where+    tuple :: TypeR t -> TypeQ+    tuple TupRunit         = [t| () |]+    tuple (TupRpair t1 t2) = [t| ($(tuple t1), $(tuple t2)) |]+    tuple (TupRsingle t)   = scalar t++    scalar :: ScalarType t -> TypeQ+    scalar (SingleScalarType t) = single t+    scalar (VectorScalarType t) = vector t++    vector :: VectorType (Vec n a) -> TypeQ+    vector (VectorType n t) = [t| Vec $(litT (numTyLit (toInteger n))) $(single t) |]++    single :: SingleType t -> TypeQ+    single (NumSingleType t) = num t++    num :: NumType t -> TypeQ+    num (IntegralNumType t) = integral t+    num (FloatingNumType t) = floating t++    integral :: IntegralType t -> TypeQ+    integral TypeInt    = [t| Int |]+    integral TypeInt8   = [t| Int8 |]+    integral TypeInt16  = [t| Int16 |]+    integral TypeInt32  = [t| Int32 |]+    integral TypeInt64  = [t| Int64 |]+    integral TypeWord   = [t| Word |]+    integral TypeWord8  = [t| Word8 |]+    integral TypeWord16 = [t| Word16 |]+    integral TypeWord32 = [t| Word32 |]+    integral TypeWord64 = [t| Word64 |]++    floating :: FloatingType t -> TypeQ+    floating TypeHalf   = [t| Half |]+    floating TypeFloat  = [t| Float |]+    floating TypeDouble = [t| Double |]++runQ $+  let+      mkT :: Int -> Q Dec+      mkT n =+        let xs  = [ mkName ('x' : show i) | i <- [0 .. n-1] ]+            ts  = map varT xs+            rhs = foldl (\a b -> [t| ($a, $b) |]) [t| () |] ts+         in+         tySynD (mkName ("Tup" ++ show n)) (map plainTV xs) rhs+  in+  mapM mkT [2..16]+
+ src/Data/Array/Accelerate/Representation/Vec.hs view
@@ -0,0 +1,95 @@+{-# LANGUAGE DataKinds           #-}+{-# LANGUAGE GADTs               #-}+{-# LANGUAGE KindSignatures      #-}+{-# LANGUAGE MagicHash           #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TemplateHaskell     #-}+{-# LANGUAGE TypeOperators       #-}+{-# OPTIONS_HADDOCK hide #-}+-- |+-- Module      : Data.Array.Accelerate.Representation.Vec+-- Copyright   : [2008..2020] The Accelerate Team+-- License     : BSD3+--+-- Maintainer  : Trevor L. McDonell <trevor.mcdonell@gmail.com>+-- Stability   : experimental+-- Portability : non-portable (GHC extensions)+--++module Data.Array.Accelerate.Representation.Vec+  where++import Data.Array.Accelerate.Type+import Data.Array.Accelerate.Representation.Type+import Data.Primitive.Vec++import Control.Monad.ST+import Data.Primitive.ByteArray+import Data.Primitive.Types+import Language.Haskell.TH++import GHC.Base                                         ( Int(..), Int#, (-#) )+import GHC.TypeNats+++-- | Declares the size of a SIMD vector and the type of its elements. This+-- data type is used to denote the relation between a vector type (Vec+-- n single) with its tuple representation (tuple). Conversions between+-- those types are exposed through 'pack' and 'unpack'.+--+data VecR (n :: Nat) single tuple where+  VecRnil  :: SingleType s -> VecR 0       s ()+  VecRsucc :: VecR n s t   -> VecR (n + 1) s (t, s)++vecRvector :: KnownNat n => VecR n s tuple -> VectorType (Vec n s)+vecRvector = uncurry VectorType . go+  where+    go :: VecR n s tuple -> (Int, SingleType s)+    go (VecRnil tp)                       = (0,     tp)+    go (VecRsucc vec) | (n, tp) <- go vec = (n + 1, tp)++vecRtuple :: VecR n s tuple -> TypeR tuple+vecRtuple = snd . go+  where+    go :: VecR n s tuple -> (SingleType s, TypeR tuple)+    go (VecRnil tp)                           = (tp, TupRunit)+    go (VecRsucc vec) | (tp, tuple) <- go vec = (tp, TupRpair tuple (TupRsingle (SingleScalarType tp)))++pack :: forall n single tuple. KnownNat n => VecR n single tuple -> tuple -> Vec n single+pack vecR tuple+  | VectorType n single <- vecRvector vecR+  , SingleDict          <- singleDict single+  = runST $ do+      mba <- newByteArray (n * sizeOf (undefined :: single))+      go (n - 1) vecR tuple mba+      ByteArray ba# <- unsafeFreezeByteArray mba+      return $! Vec ba#+  where+    go :: Prim single => Int -> VecR n' single tuple' -> tuple' -> MutableByteArray s -> ST s ()+    go _ (VecRnil _)  ()      _   = return ()+    go i (VecRsucc r) (xs, x) mba = do+      writeByteArray mba i x+      go (i - 1) r xs mba++unpack :: forall n single tuple. KnownNat n => VecR n single tuple -> Vec n single -> tuple+unpack vecR (Vec ba#)+  | VectorType n single <- vecRvector vecR+  , (I# n#)             <- n+  , SingleDict          <- singleDict single+  = go (n# -# 1#) vecR+  where+    go :: Prim single => Int# -> VecR n' single tuple' -> tuple'+    go _  (VecRnil _)  = ()+    go i# (VecRsucc r) = x `seq` xs `seq` (xs, x)+      where+        xs = go (i# -# 1#) r+        x  = indexByteArray# ba# i#++rnfVecR :: VecR n single tuple -> ()+rnfVecR (VecRnil tp)   = rnfSingleType tp+rnfVecR (VecRsucc vec) = rnfVecR vec++liftVecR :: VecR n single tuple -> Q (TExp (VecR n single tuple))+liftVecR (VecRnil tp)   = [|| VecRnil $$(liftSingleType tp) ||]+liftVecR (VecRsucc vec) = [|| VecRsucc $$(liftVecR vec) ||]+
src/Data/Array/Accelerate/Smart.hs view
@@ -1,2313 +1,1355 @@-{-# LANGUAGE DeriveDataTypeable    #-}-{-# LANGUAGE FlexibleContexts      #-}-{-# LANGUAGE FlexibleInstances     #-}-{-# LANGUAGE GADTs                 #-}-{-# LANGUAGE MultiParamTypeClasses #-}-{-# LANGUAGE ScopedTypeVariables   #-}-{-# LANGUAGE StandaloneDeriving    #-}-{-# LANGUAGE TypeFamilies          #-}-{-# LANGUAGE TypeOperators         #-}-{-# OPTIONS_HADDOCK hide #-}--- |--- Module      : Data.Array.Accelerate.Smart--- 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(..), PreBoundary(..), Stencil(..), Level,--  -- * Smart constructors for literals-  constant, undef,--  -- * Smart constructors and destructors for tuples-  tup2, tup3, tup4, tup5, tup6, tup7, tup8, tup9, tup10, tup11, tup12, tup13, tup14, tup15, tup16,-  untup2, untup3, untup4, untup5, untup6, untup7, untup8, untup9, untup10, untup11, untup12, untup13, untup14, untup15, untup16,--  atup2, atup3, atup4, atup5, atup6, atup7, atup8, atup9, atup10, atup11, atup12, atup13, atup14, atup15, atup16,-  unatup2, unatup3, unatup4, unatup5, unatup6, unatup7, unatup8, unatup9, unatup10, unatup11, unatup12, unatup13, unatup14, unatup15, unatup16,--  -- * 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, mkIsInfinite,--  -- * 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(..), PreBoundary(..), Boundary-                                                       , 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.------ [/A simple example/]------ As a simple example, to compute a vector dot product we can 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.------ [/Avoiding nested parallelism/]------ As mentioned above, embedded scalar computations of type 'Exp' can not--- initiate further collective operations.------ Suppose we wanted to extend our above @dotp@ function to matrix-vector--- multiplication. First, let's rewrite our @dotp@ function to take 'Acc' arrays--- as input (which is typically what we want):------ > dotp :: Num a => Acc (Vector a) -> Acc (Vector a) -> Acc (Scalar a)--- > dotp xs ys = fold (+) 0 ( zipWith (*) xs ys )------ We might then be inclined to lift our dot-product program to the following--- (incorrect) matrix-vector product, by applying @dotp@ to each row of the--- input matrix:------ > mvm_ndp :: Num a => Acc (Matrix a) -> Acc (Vector a) -> Acc (Vector a)--- > mvm_ndp mat vec =--- >   let Z :. rows :. cols  = unlift (shape mat)  :: Z :. Exp Int :. Exp Int--- >   in  generate (index1 rows)--- >                (\row -> the $ dotp vec (slice mat (lift (row :. All))))------ Here, we use 'Data.Array.Accelerate.generate' to create a one-dimensional--- vector by applying at each index a function to 'Data.Array.Accelerate.slice'--- out the corresponding @row@ of the matrix to pass to the @dotp@ function.--- However, since both 'Data.Array.Accelerate.generate' and--- 'Data.Array.Accelerate.slice' are data-parallel operations, and moreover that--- 'Data.Array.Accelerate.slice' /depends on/ the argument @row@ given to it by--- the 'Data.Array.Accelerate.generate' function, this definition requires--- nested data-parallelism, and is thus not permitted. The clue that this--- definition is invalid is that in order to create a program which will be--- accepted by the type checker, we must use the function--- 'Data.Array.Accelerate.the' to retrieve the result of the @dotp@ operation,--- effectively concealing that @dotp@ is a collective array computation in order--- to match the type expected by 'Data.Array.Accelerate.generate', which is that--- of scalar expressions. Additionally, since we have fooled the type-checker,--- this problem will only be discovered at program runtime.------ In order to avoid this problem, we can make use of the fact that operations--- in Accelerate are /rank polymorphic/. The 'Data.Array.Accelerate.fold'--- operation reduces along the innermost dimension of an array of arbitrary--- rank, reducing the rank (dimensionality) of the array by one. Thus, we can--- 'Data.Array.Accelerate.replicate' the input vector to as many @rows@ there--- are in the input matrix, and perform the dot-product of the vector with every--- row simultaneously:------ > mvm :: A.Num a => Acc (Matrix a) -> Acc (Vector a) -> Acc (Vector a)--- > mvm mat vec =--- >   let Z :. rows :. cols = unlift (shape mat) :: Z :. Exp Int :. Exp Int--- >       vec'              = A.replicate (lift (Z :. rows :. All)) vec--- >   in--- >   A.fold (+) 0 ( A.zipWith (*) mat vec' )------ Note that the intermediate, replicated array @vec'@ is never actually created--- in memory; it will be fused directly into the operation which consumes it. We--- discuss fusion next.------ [/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:------ <<images/fusion_example_1.png>>------ <<images/fusion_example_2.png>>------ 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:------ <<images/fusion_example_3.png>>------ 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)-                -> PreBoundary acc exp (Array sh 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)-                -> PreBoundary acc exp (Array sh a)-                -> acc (Array sh a)-                -> PreBoundary acc exp (Array sh 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--  Undef         :: Elt t-                => PreExp acc exp t--  Coerce        :: (Elt a, Elt b)-                => exp a-                -> PreExp acc exp b------ 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--atup16 :: (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 p)-       => (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 p)-       -> Acc (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p)-atup16 (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p)-  = 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-            `SnocAtup` p--unatup2 :: (Arrays a, Arrays b)-        => Acc (a, b)-        -> (Acc a, Acc b)-unatup2 e =-  ( Acc $ tix1 `Aprj` e-  , Acc $ tix0 `Aprj` e )--unatup3 :: (Arrays a, Arrays b, Arrays c)-        => Acc (a, b, c)-        -> (Acc a, Acc b, Acc c)-unatup3 e =-  ( Acc $ tix2 `Aprj` e-  , Acc $ tix1 `Aprj` e-  , Acc $ tix0 `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 $ tix3 `Aprj` e-  , Acc $ tix2 `Aprj` e-  , Acc $ tix1 `Aprj` e-  , Acc $ tix0 `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 $ tix4 `Aprj` e-  , Acc $ tix3 `Aprj` e-  , Acc $ tix2 `Aprj` e-  , Acc $ tix1 `Aprj` e-  , Acc $ tix0 `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 $ tix5 `Aprj` e-  , Acc $ tix4 `Aprj` e-  , Acc $ tix3 `Aprj` e-  , Acc $ tix2 `Aprj` e-  , Acc $ tix1 `Aprj` e-  , Acc $ tix0 `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 $ tix6 `Aprj` e-  , Acc $ tix5 `Aprj` e-  , Acc $ tix4 `Aprj` e-  , Acc $ tix3 `Aprj` e-  , Acc $ tix2 `Aprj` e-  , Acc $ tix1 `Aprj` e-  , Acc $ tix0 `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 $ tix7 `Aprj` e-  , Acc $ tix6 `Aprj` e-  , Acc $ tix5 `Aprj` e-  , Acc $ tix4 `Aprj` e-  , Acc $ tix3 `Aprj` e-  , Acc $ tix2 `Aprj` e-  , Acc $ tix1 `Aprj` e-  , Acc $ tix0 `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 $ tix8 `Aprj` e-  , Acc $ tix7 `Aprj` e-  , Acc $ tix6 `Aprj` e-  , Acc $ tix5 `Aprj` e-  , Acc $ tix4 `Aprj` e-  , Acc $ tix3 `Aprj` e-  , Acc $ tix2 `Aprj` e-  , Acc $ tix1 `Aprj` e-  , Acc $ tix0 `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 $ tix9 `Aprj` e-  , Acc $ tix8 `Aprj` e-  , Acc $ tix7 `Aprj` e-  , Acc $ tix6 `Aprj` e-  , Acc $ tix5 `Aprj` e-  , Acc $ tix4 `Aprj` e-  , Acc $ tix3 `Aprj` e-  , Acc $ tix2 `Aprj` e-  , Acc $ tix1 `Aprj` e-  , Acc $ tix0 `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 $ tix10 `Aprj` e-  , Acc $ tix9  `Aprj` e-  , Acc $ tix8  `Aprj` e-  , Acc $ tix7  `Aprj` e-  , Acc $ tix6  `Aprj` e-  , Acc $ tix5  `Aprj` e-  , Acc $ tix4  `Aprj` e-  , Acc $ tix3  `Aprj` e-  , Acc $ tix2  `Aprj` e-  , Acc $ tix1  `Aprj` e-  , Acc $ tix0  `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 $ tix11 `Aprj` e-  , Acc $ tix10 `Aprj` e-  , Acc $ tix9  `Aprj` e-  , Acc $ tix8  `Aprj` e-  , Acc $ tix7  `Aprj` e-  , Acc $ tix6  `Aprj` e-  , Acc $ tix5  `Aprj` e-  , Acc $ tix4  `Aprj` e-  , Acc $ tix3  `Aprj` e-  , Acc $ tix2  `Aprj` e-  , Acc $ tix1  `Aprj` e-  , Acc $ tix0  `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 $ tix12 `Aprj` e-  , Acc $ tix11 `Aprj` e-  , Acc $ tix10 `Aprj` e-  , Acc $ tix9  `Aprj` e-  , Acc $ tix8  `Aprj` e-  , Acc $ tix7  `Aprj` e-  , Acc $ tix6  `Aprj` e-  , Acc $ tix5  `Aprj` e-  , Acc $ tix4  `Aprj` e-  , Acc $ tix3  `Aprj` e-  , Acc $ tix2  `Aprj` e-  , Acc $ tix1  `Aprj` e-  , Acc $ tix0  `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 $ tix13 `Aprj` e-  , Acc $ tix12 `Aprj` e-  , Acc $ tix11 `Aprj` e-  , Acc $ tix10 `Aprj` e-  , Acc $ tix9  `Aprj` e-  , Acc $ tix8  `Aprj` e-  , Acc $ tix7  `Aprj` e-  , Acc $ tix6  `Aprj` e-  , Acc $ tix5  `Aprj` e-  , Acc $ tix4  `Aprj` e-  , Acc $ tix3  `Aprj` e-  , Acc $ tix2  `Aprj` e-  , Acc $ tix1  `Aprj` e-  , Acc $ tix0  `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 $ tix14 `Aprj` e-  , Acc $ tix13 `Aprj` e-  , Acc $ tix12 `Aprj` e-  , Acc $ tix11 `Aprj` e-  , Acc $ tix10 `Aprj` e-  , Acc $ tix9  `Aprj` e-  , Acc $ tix8  `Aprj` e-  , Acc $ tix7  `Aprj` e-  , Acc $ tix6  `Aprj` e-  , Acc $ tix5  `Aprj` e-  , Acc $ tix4  `Aprj` e-  , Acc $ tix3  `Aprj` e-  , Acc $ tix2  `Aprj` e-  , Acc $ tix1  `Aprj` e-  , Acc $ tix0  `Aprj` e )--unatup16-    :: (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 p)-    => Acc (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p)-    -> (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 p)-unatup16 e =-  ( Acc $ tix15 `Aprj` e-  , Acc $ tix14 `Aprj` e-  , Acc $ tix13 `Aprj` e-  , Acc $ tix12 `Aprj` e-  , Acc $ tix11 `Aprj` e-  , Acc $ tix10 `Aprj` e-  , Acc $ tix9  `Aprj` e-  , Acc $ tix8  `Aprj` e-  , Acc $ tix7  `Aprj` e-  , Acc $ tix6  `Aprj` e-  , Acc $ tix5  `Aprj` e-  , Acc $ tix4  `Aprj` e-  , Acc $ tix3  `Aprj` e-  , Acc $ tix2  `Aprj` e-  , Acc $ tix1  `Aprj` e-  , Acc $ tix0  `Aprj` e )----- Smart constructors for stencils--- ----------------------------------- | Boundary condition specification for stencil operations----newtype Boundary t = Boundary (PreBoundary Acc Exp t)--data PreBoundary acc exp t where-  Clamp     :: PreBoundary acc exp t-  Mirror    :: PreBoundary acc exp t-  Wrap      :: PreBoundary acc exp t--  Constant  :: Elt e-            => e-            -> PreBoundary acc exp (Array sh e)--  Function  :: (Shape sh, Elt e)-            => (Exp sh -> exp e)-            -> PreBoundary acc exp (Array sh e)----- 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 :: {-dummy-} sh-             -> {-dummy-} a-             -> 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--tix9 :: TupleIdx ((((((((((t, s9), s8), s7), s6), s5), s4), s3), s2), s1), s0) s9-tix9 = SuccTupIdx tix8--tix10 :: TupleIdx (((((((((((t, s10), s9), s8), s7), s6), s5), s4), s3), s2), s1), s0) s10-tix10 = SuccTupIdx tix9--tix11 :: TupleIdx ((((((((((((t, s11), s10), s9), s8), s7), s6), s5), s4), s3), s2), s1), s0) s11-tix11 = SuccTupIdx tix10--tix12 :: TupleIdx (((((((((((((t, s12), s11), s10), s9), s8), s7), s6), s5), s4), s3), s2), s1), s0) s12-tix12 = SuccTupIdx tix11--tix13 :: TupleIdx ((((((((((((((t, s13), s12), s11), s10), s9), s8), s7), s6), s5), s4), s3), s2), s1), s0) s13-tix13 = SuccTupIdx tix12--tix14 :: TupleIdx (((((((((((((((t, s14), s13), s12), s11), s10), s9), s8), s7), s6), s5), s4), s3), s2), s1), s0) s14-tix14 = SuccTupIdx tix13--tix15 :: TupleIdx ((((((((((((((((t, s15), s14), s13), s12), s11), s10), s9), s8), s7), s6), s5), s4), s3), s2), s1), s0) s15-tix15 = SuccTupIdx tix14--{----- 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---- | 'undef' can be used anywhere a constant is expected, and indicates that the--- consumer of the value can receive an unspecified bit pattern.------ This is useful because a store of an undefined value can be assumed to not--- have any effect; we can assume that the value is overwritten with bits that--- happen to match what was already there. However, a store /to/ an undefined--- location could clobber arbitrary memory, therefore, its use in such a context--- would introduce undefined /behaviour/.------ There are (at least) two cases where you may want to use this:------   1. The 'Data.Array.Accelerate.Language.permute' function requires an array---      of default values, into which the new values are combined. However, if---      you are sure the default values are not used, and will (eventually) be---      completely overwritten, then 'Data.Array.Accelerate.Prelude.fill'ing an---      array with this value will give you a new uninitialised array.------   2. In the definition of sum data types. See for example---      "Data.Array.Accelerate.Data.Maybe" and---      "Data.Array.Accelerate.Data.Either".------ @since 1.2.0.0----undef :: Elt t => Exp t-undef = Exp Undef---- 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--tup16 :: (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 p)-      => (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 p)-      -> Exp (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p)-tup16 (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p)-  = 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-           `SnocTup` p--untup2 :: (Elt a, Elt b) => Exp (a, b) -> (Exp a, Exp b)-untup2 e =-  ( Exp $ tix1 `Prj` e-  , Exp $ tix0 `Prj` e )--untup3 :: (Elt a, Elt b, Elt c) => Exp (a, b, c) -> (Exp a, Exp b, Exp c)-untup3 e =-  ( Exp $ tix2 `Prj` e-  , Exp $ tix1 `Prj` e-  , Exp $ tix0 `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 $ tix3 `Prj` e-  , Exp $ tix2 `Prj` e-  , Exp $ tix1 `Prj` e-  , Exp $ tix0 `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 $ tix4 `Prj` e-  , Exp $ tix3 `Prj` e-  , Exp $ tix2 `Prj` e-  , Exp $ tix1 `Prj` e-  , Exp $ tix0 `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 $ tix5 `Prj` e-  , Exp $ tix4 `Prj` e-  , Exp $ tix3 `Prj` e-  , Exp $ tix2 `Prj` e-  , Exp $ tix1 `Prj` e-  , Exp $ tix0 `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 $ tix6 `Prj` e-  , Exp $ tix5 `Prj` e-  , Exp $ tix4 `Prj` e-  , Exp $ tix3 `Prj` e-  , Exp $ tix2 `Prj` e-  , Exp $ tix1 `Prj` e-  , Exp $ tix0 `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 $ tix7 `Prj` e-  , Exp $ tix6 `Prj` e-  , Exp $ tix5 `Prj` e-  , Exp $ tix4 `Prj` e-  , Exp $ tix3 `Prj` e-  , Exp $ tix2 `Prj` e-  , Exp $ tix1 `Prj` e-  , Exp $ tix0 `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 $ tix8 `Prj` e-  , Exp $ tix7 `Prj` e-  , Exp $ tix6 `Prj` e-  , Exp $ tix5 `Prj` e-  , Exp $ tix4 `Prj` e-  , Exp $ tix3 `Prj` e-  , Exp $ tix2 `Prj` e-  , Exp $ tix1 `Prj` e-  , Exp $ tix0 `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 $ tix9 `Prj` e-  , Exp $ tix8 `Prj` e-  , Exp $ tix7 `Prj` e-  , Exp $ tix6 `Prj` e-  , Exp $ tix5 `Prj` e-  , Exp $ tix4 `Prj` e-  , Exp $ tix3 `Prj` e-  , Exp $ tix2 `Prj` e-  , Exp $ tix1 `Prj` e-  , Exp $ tix0 `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 $ tix10 `Prj` e-  , Exp $ tix9  `Prj` e-  , Exp $ tix8  `Prj` e-  , Exp $ tix7  `Prj` e-  , Exp $ tix6  `Prj` e-  , Exp $ tix5  `Prj` e-  , Exp $ tix4  `Prj` e-  , Exp $ tix3  `Prj` e-  , Exp $ tix2  `Prj` e-  , Exp $ tix1  `Prj` e-  , Exp $ tix0  `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 $ tix11 `Prj` e-  , Exp $ tix10 `Prj` e-  , Exp $ tix9  `Prj` e-  , Exp $ tix8  `Prj` e-  , Exp $ tix7  `Prj` e-  , Exp $ tix6  `Prj` e-  , Exp $ tix5  `Prj` e-  , Exp $ tix4  `Prj` e-  , Exp $ tix3  `Prj` e-  , Exp $ tix2  `Prj` e-  , Exp $ tix1  `Prj` e-  , Exp $ tix0  `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 $ tix12 `Prj` e-  , Exp $ tix11 `Prj` e-  , Exp $ tix10 `Prj` e-  , Exp $ tix9  `Prj` e-  , Exp $ tix8  `Prj` e-  , Exp $ tix7  `Prj` e-  , Exp $ tix6  `Prj` e-  , Exp $ tix5  `Prj` e-  , Exp $ tix4  `Prj` e-  , Exp $ tix3  `Prj` e-  , Exp $ tix2  `Prj` e-  , Exp $ tix1  `Prj` e-  , Exp $ tix0  `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 $ tix13 `Prj` e-  , Exp $ tix12 `Prj` e-  , Exp $ tix11 `Prj` e-  , Exp $ tix10 `Prj` e-  , Exp $ tix9  `Prj` e-  , Exp $ tix8  `Prj` e-  , Exp $ tix7  `Prj` e-  , Exp $ tix6  `Prj` e-  , Exp $ tix5  `Prj` e-  , Exp $ tix4  `Prj` e-  , Exp $ tix3  `Prj` e-  , Exp $ tix2  `Prj` e-  , Exp $ tix1  `Prj` e-  , Exp $ tix0  `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 $ tix14 `Prj` e-  , Exp $ tix13 `Prj` e-  , Exp $ tix12 `Prj` e-  , Exp $ tix11 `Prj` e-  , Exp $ tix10 `Prj` e-  , Exp $ tix9  `Prj` e-  , Exp $ tix8  `Prj` e-  , Exp $ tix7  `Prj` e-  , Exp $ tix6  `Prj` e-  , Exp $ tix5  `Prj` e-  , Exp $ tix4  `Prj` e-  , Exp $ tix3  `Prj` e-  , Exp $ tix2  `Prj` e-  , Exp $ tix1  `Prj` e-  , Exp $ tix0  `Prj` e )--untup16 :: (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 p)-        => Exp (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p)-        -> (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 p)-untup16 e =-  ( Exp $ tix15 `Prj` e-  , Exp $ tix14 `Prj` e-  , Exp $ tix13 `Prj` e-  , Exp $ tix12 `Prj` e-  , Exp $ tix11 `Prj` e-  , Exp $ tix10 `Prj` e-  , Exp $ tix9  `Prj` e-  , Exp $ tix8  `Prj` e-  , Exp $ tix7  `Prj` e-  , Exp $ tix6  `Prj` e-  , Exp $ tix5  `Prj` e-  , Exp $ tix4  `Prj` e-  , Exp $ tix3  `Prj` e-  , Exp $ tix2  `Prj` e-  , Exp $ tix1  `Prj` e-  , Exp $ tix0  `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--mkIsInfinite :: (Elt t, IsFloating t) => Exp t -> Exp Bool-mkIsInfinite x = Exp $ PrimIsInfinite floatingType `PrimApp` x---- FIXME: add missing operations from Floating, RealFrac & RealFloat---- Relational and equality operators--mkLt :: (Elt t, IsSingle t) => Exp t -> Exp t -> Exp Bool-mkLt x y = Exp $ PrimLt singleType `PrimApp` tup2 (x, y)--mkGt :: (Elt t, IsSingle t) => Exp t -> Exp t -> Exp Bool-mkGt x y = Exp $ PrimGt singleType `PrimApp` tup2 (x, y)--mkLtEq :: (Elt t, IsSingle t) => Exp t -> Exp t -> Exp Bool-mkLtEq x y = Exp $ PrimLtEq singleType `PrimApp` tup2 (x, y)--mkGtEq :: (Elt t, IsSingle t) => Exp t -> Exp t -> Exp Bool-mkGtEq x y = Exp $ PrimGtEq singleType `PrimApp` tup2 (x, y)--mkEq :: (Elt t, IsSingle t) => Exp t -> Exp t -> Exp Bool-mkEq x y = Exp $ PrimEq singleType `PrimApp` tup2 (x, y)--mkNEq :: (Elt t, IsSingle t) => Exp t -> Exp t -> Exp Bool-mkNEq x y = Exp $ PrimNEq singleType `PrimApp` tup2 (x, y)--mkMax :: (Elt t, IsSingle t) => Exp t -> Exp t -> Exp t-mkMax x y = Exp $ PrimMax singleType `PrimApp` tup2 (x, y)--mkMin :: (Elt t, IsSingle t) => Exp t -> Exp t -> Exp t-mkMin x y = Exp $ PrimMin singleType `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: Restricted to scalar types with a type-level BitSizeEq constraint to--- make this version "safe"-mkBitcast :: (Elt a, Elt b, IsScalar (EltRepr a), IsScalar (EltRepr b), BitSizeEq (EltRepr a) (EltRepr b)) => Exp a -> Exp b-mkBitcast = mkUnsafeCoerce--mkUnsafeCoerce :: (Elt a, Elt b) => Exp a -> Exp b-mkUnsafeCoerce = Exp . Coerce----- 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 (Tag i)            = "Tag" ++ show i-showPreExpOp (Const c)          = "Const " ++ show c-showPreExpOp Undef              = "Undef"-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"+{-# LANGUAGE AllowAmbiguousTypes   #-}+{-# LANGUAGE CPP                   #-}+{-# LANGUAGE DataKinds             #-}+{-# LANGUAGE FlexibleContexts      #-}+{-# LANGUAGE FlexibleInstances     #-}+{-# LANGUAGE GADTs                 #-}+{-# LANGUAGE LambdaCase            #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE ScopedTypeVariables   #-}+{-# LANGUAGE TemplateHaskell       #-}+{-# LANGUAGE TypeApplications      #-}+{-# LANGUAGE TypeFamilies          #-}+{-# LANGUAGE TypeOperators         #-}+{-# OPTIONS_HADDOCK hide #-}+-- |+-- Module      : Data.Array.Accelerate.Smart+-- Copyright   : [2008..2020] The Accelerate Team+-- License     : BSD3+--+-- Maintainer  : Trevor L. McDonell <trevor.mcdonell@gmail.com>+-- 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+  -- ** Array computations+  Acc(..), SmartAcc(..), PreSmartAcc(..),+  Level, Direction(..),++  -- ** Scalar expressions+  Exp(..), SmartExp(..), PreSmartExp(..),+  Stencil(..),+  Boundary(..), PreBoundary(..),+  PrimBool,+  PrimMaybe,++  -- ** Extracting type information+  HasArraysR(..),+  HasTypeR(..),++  -- ** Smart constructors for literals+  constant, undef,++  -- ** Smart destructors for shapes+  indexHead, indexTail,++  -- ** 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, mkIsInfinite,++  -- ** Smart constructors for type coercion functions+  mkFromIntegral, mkToFloating, mkBitcast, mkCoerce, Coerce(..),++  -- ** Auxiliary functions+  ($$), ($$$), ($$$$), ($$$$$),+  ApplyAcc(..),+  unAcc, unAccFunction, mkExp, unExp, unExpFunction, unExpBinaryFunction, unPair, mkPairToTuple,++  -- ** Miscellaneous+  showPreAccOp,+  showPreExpOp,++) where+++import Data.Array.Accelerate.AST.Idx+import Data.Array.Accelerate.Error+import Data.Array.Accelerate.Representation.Array+import Data.Array.Accelerate.Representation.Elt+import Data.Array.Accelerate.Representation.Shape+import Data.Array.Accelerate.Representation.Slice+import Data.Array.Accelerate.Representation.Stencil                 hiding ( StencilR, stencilR )+import Data.Array.Accelerate.Representation.Tag+import Data.Array.Accelerate.Representation.Type+import Data.Array.Accelerate.Representation.Vec+import Data.Array.Accelerate.Sugar.Array                            ( Arrays )+import Data.Array.Accelerate.Sugar.Elt+import Data.Array.Accelerate.Sugar.Foreign+import Data.Array.Accelerate.Sugar.Shape                            ( (:.)(..) )+import Data.Array.Accelerate.Type+import qualified Data.Array.Accelerate.Representation.Stencil       as R+import qualified Data.Array.Accelerate.Sugar.Array                  as Sugar+import qualified Data.Array.Accelerate.Sugar.Shape                  as Sugar++import Data.Array.Accelerate.AST                                    ( Direction(..)+                                                                    , PrimBool, PrimMaybe+                                                                    , PrimFun(..), primFunType+                                                                    , PrimConst(..), primConstType )+import Data.Primitive.Vec++import Data.Kind+import Prelude++import GHC.TypeLits+++-- 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.+--+-- [/A simple example/]+--+-- As a simple example, to compute a vector dot product we can 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.+--+-- [/Avoiding nested parallelism/]+--+-- As mentioned above, embedded scalar computations of type 'Exp' can not+-- initiate further collective operations.+--+-- Suppose we wanted to extend our above @dotp@ function to matrix-vector+-- multiplication. First, let's rewrite our @dotp@ function to take 'Acc' arrays+-- as input (which is typically what we want):+--+-- > dotp :: Num a => Acc (Vector a) -> Acc (Vector a) -> Acc (Scalar a)+-- > dotp xs ys = fold (+) 0 ( zipWith (*) xs ys )+--+-- We might then be inclined to lift our dot-product program to the following+-- (incorrect) matrix-vector product, by applying @dotp@ to each row of the+-- input matrix:+--+-- > mvm_ndp :: Num a => Acc (Matrix a) -> Acc (Vector a) -> Acc (Vector a)+-- > mvm_ndp mat vec =+-- >   let Z :. rows :. cols  = unlift (shape mat)  :: Z :. Exp Int :. Exp Int+-- >   in  generate (index1 rows)+-- >                (\row -> the $ dotp vec (slice mat (lift (row :. All))))+--+-- Here, we use 'Data.Array.Accelerate.generate' to create a one-dimensional+-- vector by applying at each index a function to 'Data.Array.Accelerate.slice'+-- out the corresponding @row@ of the matrix to pass to the @dotp@ function.+-- However, since both 'Data.Array.Accelerate.generate' and+-- 'Data.Array.Accelerate.slice' are data-parallel operations, and moreover that+-- 'Data.Array.Accelerate.slice' /depends on/ the argument @row@ given to it by+-- the 'Data.Array.Accelerate.generate' function, this definition requires+-- nested data-parallelism, and is thus not permitted. The clue that this+-- definition is invalid is that in order to create a program which will be+-- accepted by the type checker, we must use the function+-- 'Data.Array.Accelerate.the' to retrieve the result of the @dotp@ operation,+-- effectively concealing that @dotp@ is a collective array computation in order+-- to match the type expected by 'Data.Array.Accelerate.generate', which is that+-- of scalar expressions. Additionally, since we have fooled the type-checker,+-- this problem will only be discovered at program runtime.+--+-- In order to avoid this problem, we can make use of the fact that operations+-- in Accelerate are /rank polymorphic/. The 'Data.Array.Accelerate.fold'+-- operation reduces along the innermost dimension of an array of arbitrary+-- rank, reducing the rank (dimensionality) of the array by one. Thus, we can+-- 'Data.Array.Accelerate.replicate' the input vector to as many @rows@ there+-- are in the input matrix, and perform the dot-product of the vector with every+-- row simultaneously:+--+-- > mvm :: A.Num a => Acc (Matrix a) -> Acc (Vector a) -> Acc (Vector a)+-- > mvm mat vec =+-- >   let Z :. rows :. cols = unlift (shape mat) :: Z :. Exp Int :. Exp Int+-- >       vec'              = A.replicate (lift (Z :. rows :. All)) vec+-- >   in+-- >   A.fold (+) 0 ( A.zipWith (*) mat vec' )+--+-- Note that the intermediate, replicated array @vec'@ is never actually created+-- in memory; it will be fused directly into the operation which consumes it. We+-- discuss fusion next.+--+-- [/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:+--+-- <<images/fusion_example_1.png>>+--+-- <<images/fusion_example_2.png>>+--+-- 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:+--+-- <<images/fusion_example_3.png>>+--+-- 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 (SmartAcc (Sugar.ArraysR a))++newtype SmartAcc a = SmartAcc (PreSmartAcc SmartAcc SmartExp a)+++-- 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 PreSmartAcc acc exp as where+    -- Needed for conversion to de Bruijn form+  Atag          :: ArraysR as+                -> Level                        -- environment size at defining occurrence+                -> PreSmartAcc acc exp as++  Pipe          :: ArraysR as+                -> ArraysR bs+                -> ArraysR cs+                -> (SmartAcc as -> acc bs)+                -> (SmartAcc bs -> acc cs)+                -> acc as+                -> PreSmartAcc acc exp cs++  Aforeign      :: Foreign asm+                => ArraysR bs+                -> asm (as -> bs)+                -> (SmartAcc as -> SmartAcc bs)+                -> acc as+                -> PreSmartAcc acc exp bs++  Acond         :: exp PrimBool+                -> acc as+                -> acc as+                -> PreSmartAcc acc exp as++  Awhile        :: ArraysR arrs+                -> (SmartAcc arrs -> acc (Scalar PrimBool))+                -> (SmartAcc arrs -> acc arrs)+                -> acc arrs+                -> PreSmartAcc acc exp arrs++  Anil          :: PreSmartAcc acc exp ()++  Apair         :: acc arrs1+                -> acc arrs2+                -> PreSmartAcc acc exp (arrs1, arrs2)++  Aprj          :: PairIdx (arrs1, arrs2) arrs+                -> acc (arrs1, arrs2)+                -> PreSmartAcc acc exp arrs++  Use           :: ArrayR (Array sh e)+                -> Array sh e+                -> PreSmartAcc acc exp (Array sh e)++  Unit          :: TypeR e+                -> exp e+                -> PreSmartAcc acc exp (Scalar e)++  Generate      :: ArrayR (Array sh e)+                -> exp sh+                -> (SmartExp sh -> exp e)+                -> PreSmartAcc acc exp (Array sh e)++  Reshape       :: ShapeR sh+                -> exp sh+                -> acc (Array sh' e)+                -> PreSmartAcc acc exp (Array sh e)++  Replicate     :: SliceIndex slix sl co sh+                -> exp slix+                -> acc                 (Array sl e)+                -> PreSmartAcc acc exp (Array sh e)++  Slice         :: SliceIndex slix sl co sh+                -> acc                 (Array sh e)+                -> exp slix+                -> PreSmartAcc acc exp (Array sl e)++  Map           :: TypeR e+                -> TypeR e'+                -> (SmartExp e -> exp e')+                -> acc (Array sh e)+                -> PreSmartAcc acc exp (Array sh e')++  ZipWith       :: TypeR e1+                -> TypeR e2+                -> TypeR e3+                -> (SmartExp e1 -> SmartExp e2 -> exp e3)+                -> acc (Array sh e1)+                -> acc (Array sh e2)+                -> PreSmartAcc acc exp (Array sh e3)++  Fold          :: TypeR e+                -> (SmartExp e -> SmartExp e -> exp e)+                -> Maybe (exp e)+                -> acc (Array (sh, Int) e)+                -> PreSmartAcc acc exp (Array sh e)++  FoldSeg       :: IntegralType i+                -> TypeR e+                -> (SmartExp e -> SmartExp e -> exp e)+                -> Maybe (exp e)+                -> acc (Array (sh, Int) e)+                -> acc (Segments i)+                -> PreSmartAcc acc exp (Array (sh, Int) e)++  Scan          :: Direction+                -> TypeR e+                -> (SmartExp e -> SmartExp e -> exp e)+                -> Maybe (exp e)+                -> acc (Array (sh, Int) e)+                -> PreSmartAcc acc exp (Array (sh, Int) e)++  Scan'         :: Direction+                -> TypeR e+                -> (SmartExp e -> SmartExp e -> exp e)+                -> exp e+                -> acc (Array (sh, Int) e)+                -> PreSmartAcc acc exp (Array (sh, Int) e, Array sh e)++  Permute       :: ArrayR (Array sh e)+                -> (SmartExp e -> SmartExp e -> exp e)+                -> acc (Array sh' e)+                -> (SmartExp sh -> exp (PrimMaybe sh'))+                -> acc (Array sh e)+                -> PreSmartAcc acc exp (Array sh' e)++  Backpermute   :: ShapeR sh'+                -> exp sh'+                -> (SmartExp sh' -> exp sh)+                -> acc (Array sh e)+                -> PreSmartAcc acc exp (Array sh' e)++  Stencil       :: R.StencilR sh a stencil+                -> TypeR b+                -> (SmartExp stencil -> exp b)+                -> PreBoundary acc exp (Array sh a)+                -> acc (Array sh a)+                -> PreSmartAcc acc exp (Array sh b)++  Stencil2      :: R.StencilR sh a stencil1+                -> R.StencilR sh b stencil2+                -> TypeR c+                -> (SmartExp stencil1 -> SmartExp stencil2 -> exp c)+                -> PreBoundary acc exp (Array sh a)+                -> acc (Array sh a)+                -> PreBoundary acc exp (Array sh b)+                -> acc (Array sh b)+                -> PreSmartAcc acc exp (Array sh c)+++-- 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.+--++-- | 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 (SmartExp (EltR t))+newtype SmartExp t = SmartExp (PreSmartExp SmartAcc SmartExp t)++-- | Scalar expressions to parametrise collective array operations, themselves parameterised over+-- the type of collective array operations.+--+data PreSmartExp acc exp t where+  -- Needed for conversion to de Bruijn form+  Tag           :: TypeR t+                -> Level                        -- environment size at defining occurrence+                -> PreSmartExp acc exp t++  -- Needed for embedded pattern matching+  Match         :: TagR t+                -> exp t+                -> PreSmartExp acc exp t++  -- All the same constructors as 'AST.Exp', plus projection+  Const         :: ScalarType t+                -> t+                -> PreSmartExp acc exp t++  Nil           :: PreSmartExp acc exp ()++  Pair          :: exp t1+                -> exp t2+                -> PreSmartExp acc exp (t1, t2)++  Prj           :: PairIdx (t1, t2) t+                -> exp (t1, t2)+                -> PreSmartExp acc exp t++  VecPack       :: KnownNat n+                => VecR n s tup+                -> exp tup+                -> PreSmartExp acc exp (Vec n s)++  VecUnpack     :: KnownNat n+                => VecR n s tup+                -> exp (Vec n s)+                -> PreSmartExp acc exp tup++  ToIndex       :: ShapeR sh+                -> exp sh+                -> exp sh+                -> PreSmartExp acc exp Int++  FromIndex     :: ShapeR sh+                -> exp sh+                -> exp Int+                -> PreSmartExp acc exp sh++  Case          :: exp a+                -> [(TagR a, exp b)]+                -> PreSmartExp acc exp b++  Cond          :: exp PrimBool+                -> exp t+                -> exp t+                -> PreSmartExp acc exp t++  While         :: TypeR t+                -> (SmartExp t -> exp PrimBool)+                -> (SmartExp t -> exp t)+                -> exp t+                -> PreSmartExp acc exp t++  PrimConst     :: PrimConst t+                -> PreSmartExp acc exp t++  PrimApp       :: PrimFun (a -> r)+                -> exp a+                -> PreSmartExp acc exp r++  Index         :: TypeR t+                -> acc (Array sh t)+                -> exp sh+                -> PreSmartExp acc exp t++  LinearIndex   :: TypeR t+                -> acc (Array sh t)+                -> exp Int+                -> PreSmartExp acc exp t++  Shape         :: ShapeR sh+                -> acc (Array sh e)+                -> PreSmartExp acc exp sh++  ShapeSize     :: ShapeR sh+                -> exp sh+                -> PreSmartExp acc exp Int++  Foreign       :: Foreign asm+                => TypeR y+                -> asm (x -> y)+                -> (SmartExp x -> SmartExp y) -- RCE: Using SmartExp instead of exp to aid in sharing recovery.+                -> exp x+                -> PreSmartExp acc exp y++  Undef         :: ScalarType t+                -> PreSmartExp acc exp t++  Coerce        :: BitSizeEq a b+                => ScalarType a+                -> ScalarType b+                -> exp a+                -> PreSmartExp acc exp b+++-- Smart constructors for stencils+-- -------------------------------++-- | Boundary condition specification for stencil operations+--+data Boundary t where+  Boundary  :: PreBoundary SmartAcc SmartExp (Array (EltR sh) (EltR e))+            -> Boundary (Sugar.Array sh e)++data PreBoundary acc exp t where+  Clamp     :: PreBoundary acc exp t+  Mirror    :: PreBoundary acc exp t+  Wrap      :: PreBoundary acc exp t++  Constant  :: e+            -> PreBoundary acc exp (Array sh e)++  Function  :: (SmartExp sh -> exp e)+            -> PreBoundary acc exp (Array sh e)+++-- 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 Stencil sh e stencil where+  type StencilR sh stencil :: Type++  stencilR   :: R.StencilR (EltR sh) (EltR e) (StencilR sh stencil)+  stencilPrj :: SmartExp (StencilR sh stencil) -> stencil++-- DIM1+instance Elt e => Stencil Sugar.DIM1 e (Exp e, Exp e, Exp e) where+  type StencilR Sugar.DIM1 (Exp e, Exp e, Exp e)+    = EltR (e, e, e)+  stencilR = StencilRunit3 @(EltR e) $ eltR @e+  stencilPrj s = (Exp $ prj2 s,+                  Exp $ prj1 s,+                  Exp $ prj0 s)++instance Elt e => Stencil Sugar.DIM1 e (Exp e, Exp e, Exp e, Exp e, Exp e) where+  type StencilR Sugar.DIM1 (Exp e, Exp e, Exp e, Exp e, Exp e)+    = EltR (e, e, e, e, e)+  stencilR = StencilRunit5 $ eltR @e+  stencilPrj s = (Exp $ prj4 s,+                  Exp $ prj3 s,+                  Exp $ prj2 s,+                  Exp $ prj1 s,+                  Exp $ prj0 s)++instance Elt e => Stencil Sugar.DIM1 e (Exp e, Exp e, Exp e, Exp e, Exp e, Exp e, Exp e) where+  type StencilR Sugar.DIM1 (Exp e, Exp e, Exp e, Exp e, Exp e, Exp e, Exp e)+    = EltR (e, e, e, e, e, e, e)+  stencilR = StencilRunit7 $ eltR @e+  stencilPrj s = (Exp $ prj6 s,+                  Exp $ prj5 s,+                  Exp $ prj4 s,+                  Exp $ prj3 s,+                  Exp $ prj2 s,+                  Exp $ prj1 s,+                  Exp $ prj0 s)++instance Elt e => Stencil Sugar.DIM1 e (Exp e, Exp e, Exp e, Exp e, Exp e, Exp e, Exp e, Exp e, Exp e)+  where+  type StencilR Sugar.DIM1 (Exp e, Exp e, Exp e, Exp e, Exp e, Exp e, Exp e, Exp e, Exp e)+    = EltR (e, e, e, e, e, e, e, e, e)+  stencilR = StencilRunit9 $ eltR @e+  stencilPrj s = (Exp $ prj8 s,+                  Exp $ prj7 s,+                  Exp $ prj6 s,+                  Exp $ prj5 s,+                  Exp $ prj4 s,+                  Exp $ prj3 s,+                  Exp $ prj2 s,+                  Exp $ prj1 s,+                  Exp $ prj0 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 StencilR (sh:.Int:.Int) (row2, row1, row0)+    = Tup3 (StencilR (sh:.Int) row2) (StencilR (sh:.Int) row1) (StencilR (sh:.Int) row0)+  stencilR = StencilRtup3 (stencilR @(sh:.Int) @a @row2) (stencilR @(sh:.Int) @a @row1) (stencilR @(sh:.Int) @a @row0)+  stencilPrj s = (stencilPrj @(sh:.Int) @a $ prj2 s,+                  stencilPrj @(sh:.Int) @a $ prj1 s,+                  stencilPrj @(sh:.Int) @a $ prj0 s)++instance (Stencil (sh:.Int) a row4,+          Stencil (sh:.Int) a row3,+          Stencil (sh:.Int) a row2,+          Stencil (sh:.Int) a row1,+          Stencil (sh:.Int) a row0) => Stencil (sh:.Int:.Int) a (row4, row3, row2, row1, row0) where+  type StencilR (sh:.Int:.Int) (row4, row3, row2, row1, row0)+    = Tup5 (StencilR (sh:.Int) row4) (StencilR (sh:.Int) row3) (StencilR (sh:.Int) row2)+       (StencilR (sh:.Int) row1) (StencilR (sh:.Int) row0)+  stencilR = StencilRtup5 (stencilR @(sh:.Int) @a @row4) (stencilR @(sh:.Int) @a @row3)+                  (stencilR @(sh:.Int) @a @row2) (stencilR @(sh:.Int) @a @row1) (stencilR @(sh:.Int) @a @row0)+  stencilPrj s = (stencilPrj @(sh:.Int) @a $ prj4 s,+                  stencilPrj @(sh:.Int) @a $ prj3 s,+                  stencilPrj @(sh:.Int) @a $ prj2 s,+                  stencilPrj @(sh:.Int) @a $ prj1 s,+                  stencilPrj @(sh:.Int) @a $ prj0 s)++instance (Stencil (sh:.Int) a row6,+          Stencil (sh:.Int) a row5,+          Stencil (sh:.Int) a row4,+          Stencil (sh:.Int) a row3,+          Stencil (sh:.Int) a row2,+          Stencil (sh:.Int) a row1,+          Stencil (sh:.Int) a row0)+  => Stencil (sh:.Int:.Int) a (row6, row5, row4, row3, row2, row1, row0) where+  type StencilR (sh:.Int:.Int) (row6, row5, row4, row3, row2, row1, row0)+    = Tup7 (StencilR (sh:.Int) row6) (StencilR (sh:.Int) row5) (StencilR (sh:.Int) row4)+       (StencilR (sh:.Int) row3) (StencilR (sh:.Int) row2) (StencilR (sh:.Int) row1)+       (StencilR (sh:.Int) row0)+  stencilR = StencilRtup7 (stencilR @(sh:.Int) @a @row6)+                  (stencilR @(sh:.Int) @a @row5) (stencilR @(sh:.Int) @a @row4) (stencilR @(sh:.Int) @a @row3)+                  (stencilR @(sh:.Int) @a @row2) (stencilR @(sh:.Int) @a @row1) (stencilR @(sh:.Int) @a @row0)+  stencilPrj s = (stencilPrj @(sh:.Int) @a $ prj6 s,+                  stencilPrj @(sh:.Int) @a $ prj5 s,+                  stencilPrj @(sh:.Int) @a $ prj4 s,+                  stencilPrj @(sh:.Int) @a $ prj3 s,+                  stencilPrj @(sh:.Int) @a $ prj2 s,+                  stencilPrj @(sh:.Int) @a $ prj1 s,+                  stencilPrj @(sh:.Int) @a $ prj0 s)++instance (Stencil (sh:.Int) a row8,+          Stencil (sh:.Int) a row7,+          Stencil (sh:.Int) a row6,+          Stencil (sh:.Int) a row5,+          Stencil (sh:.Int) a row4,+          Stencil (sh:.Int) a row3,+          Stencil (sh:.Int) a row2,+          Stencil (sh:.Int) a row1,+          Stencil (sh:.Int) a row0)+  => Stencil (sh:.Int:.Int) a (row8, row7, row6, row5, row4, row3, row2, row1, row0) where+  type StencilR (sh:.Int:.Int) (row8, row7, row6, row5, row4, row3, row2, row1, row0)+    = Tup9 (StencilR (sh:.Int) row8) (StencilR (sh:.Int) row7) (StencilR (sh:.Int) row6)+       (StencilR (sh:.Int) row5) (StencilR (sh:.Int) row4) (StencilR (sh:.Int) row3)+       (StencilR (sh:.Int) row2) (StencilR (sh:.Int) row1) (StencilR (sh:.Int) row0)+  stencilR = StencilRtup9+                  (stencilR @(sh:.Int) @a @row8) (stencilR @(sh:.Int) @a @row7) (stencilR @(sh:.Int) @a @row6)+                  (stencilR @(sh:.Int) @a @row5) (stencilR @(sh:.Int) @a @row4) (stencilR @(sh:.Int) @a @row3)+                  (stencilR @(sh:.Int) @a @row2) (stencilR @(sh:.Int) @a @row1) (stencilR @(sh:.Int) @a @row0)+  stencilPrj s = (stencilPrj @(sh:.Int) @a $ prj8 s,+                  stencilPrj @(sh:.Int) @a $ prj7 s,+                  stencilPrj @(sh:.Int) @a $ prj6 s,+                  stencilPrj @(sh:.Int) @a $ prj5 s,+                  stencilPrj @(sh:.Int) @a $ prj4 s,+                  stencilPrj @(sh:.Int) @a $ prj3 s,+                  stencilPrj @(sh:.Int) @a $ prj2 s,+                  stencilPrj @(sh:.Int) @a $ prj1 s,+                  stencilPrj @(sh:.Int) @a $ prj0 s)++prjTail :: SmartExp (t, a) -> SmartExp t+prjTail = SmartExp . Prj PairIdxLeft++prj0 :: SmartExp (t, a) -> SmartExp a+prj0 = SmartExp . Prj PairIdxRight++prj1 :: SmartExp ((t, a), s0) -> SmartExp a+prj1 = prj0 . prjTail++prj2 :: SmartExp (((t, a), s1), s0) -> SmartExp a+prj2 = prj1 . prjTail++prj3 :: SmartExp ((((t, a), s2), s1), s0) -> SmartExp a+prj3 = prj2 . prjTail++prj4 :: SmartExp (((((t, a), s3), s2), s1), s0) -> SmartExp a+prj4 = prj3 . prjTail++prj5 :: SmartExp ((((((t, a), s4), s3), s2), s1), s0) -> SmartExp a+prj5 = prj4 . prjTail++prj6 :: SmartExp (((((((t, a), s5), s4), s3), s2), s1), s0) -> SmartExp a+prj6 = prj5 . prjTail++prj7 :: SmartExp ((((((((t, a), s6), s5), s4), s3), s2), s1), s0) -> SmartExp a+prj7 = prj6 . prjTail++prj8 :: SmartExp (((((((((t, a), s7), s6), s5), s4), s3), s2), s1), s0) -> SmartExp a+prj8 = prj7 . prjTail+++-- Extracting type information+-- ---------------------------++class HasArraysR f where+  arraysR :: f a -> ArraysR a++instance HasArraysR SmartAcc where+  arraysR (SmartAcc e) = arraysR e++arrayR :: HasArraysR f => f (Array sh e) -> ArrayR (Array sh e)+arrayR acc = case arraysR acc of+  TupRsingle repr -> repr++instance HasArraysR acc => HasArraysR (PreSmartAcc acc exp) where+  arraysR = \case+    Atag repr _               -> repr+    Pipe _ _ repr  _ _ _      -> repr+    Aforeign repr _ _ _       -> repr+    Acond _ a _               -> arraysR a+    Awhile _ _ _ a            -> arraysR a+    Anil                      -> TupRunit+    Apair a1 a2               -> arraysR a1 `TupRpair` arraysR a2+    Aprj idx a | TupRpair t1 t2 <- arraysR a+                              -> case idx of+                                   PairIdxLeft  -> t1+                                   PairIdxRight -> t2+    Aprj _ _                  -> error "Ejector seat? You're joking!"+    Use repr _                -> TupRsingle repr+    Unit tp _                 -> TupRsingle $ ArrayR ShapeRz $ tp+    Generate repr _ _         -> TupRsingle repr+    Reshape shr _ a           -> let ArrayR _ tp = arrayR a+                                 in  TupRsingle $ ArrayR shr tp+    Replicate si _ a          -> let ArrayR _ tp = arrayR a+                                 in  TupRsingle $ ArrayR (sliceDomainR si) tp+    Slice si a _              -> let ArrayR _ tp = arrayR a+                                 in  TupRsingle $ ArrayR (sliceShapeR si) tp+    Map _ tp _ a              -> let ArrayR shr _ = arrayR a+                                 in  TupRsingle $ ArrayR shr tp+    ZipWith _ _ tp _ a _      -> let ArrayR shr _ = arrayR a+                                 in  TupRsingle $ ArrayR shr tp+    Fold _ _ _ a              -> let ArrayR (ShapeRsnoc shr) tp = arrayR a+                                 in  TupRsingle (ArrayR shr tp)+    FoldSeg _ _ _ _ a _       -> arraysR a+    Scan _ _ _ _ a            -> arraysR a+    Scan' _ _ _ _ a           -> let repr@(ArrayR (ShapeRsnoc shr) tp) = arrayR a+                                 in  TupRsingle repr `TupRpair` TupRsingle (ArrayR shr tp)+    Permute _ _ a _ _         -> arraysR a+    Backpermute shr _ _ a     -> let ArrayR _ tp = arrayR a+                                 in  TupRsingle (ArrayR shr tp)+    Stencil s tp _ _ _        -> TupRsingle $ ArrayR (stencilShapeR s) tp+    Stencil2 s _ tp _ _ _ _ _ -> TupRsingle $ ArrayR (stencilShapeR s) tp+++class HasTypeR f where+  typeR :: HasCallStack => f t -> TypeR t++instance HasTypeR SmartExp where+  typeR (SmartExp e) = typeR e++instance HasTypeR exp => HasTypeR (PreSmartExp acc exp) where+  typeR = \case+    Tag tp _                        -> tp+    Match _ e                       -> typeR e+    Const tp _                      -> TupRsingle tp+    Nil                             -> TupRunit+    Pair e1 e2                      -> typeR e1 `TupRpair` typeR e2+    Prj idx e+      | TupRpair t1 t2 <- typeR e   -> case idx of+                                         PairIdxLeft  -> t1+                                         PairIdxRight -> t2+    Prj _ _                         -> error "I never joke about my work"+    VecPack   vecR _                -> TupRsingle $ VectorScalarType $ vecRvector vecR+    VecUnpack vecR _                -> vecRtuple vecR+    ToIndex _ _ _                   -> TupRsingle scalarTypeInt+    FromIndex shr _ _               -> shapeType shr+    Case _ ((_,c):_)                -> typeR c+    Case{}                          -> internalError "encountered empty case"+    Cond _ e _                      -> typeR e+    While t _ _ _                   -> t+    PrimConst c                     -> TupRsingle $ SingleScalarType $ primConstType c+    PrimApp f _                     -> snd $ primFunType f+    Index tp _ _                    -> tp+    LinearIndex tp _ _              -> tp+    Shape shr _                     -> shapeType shr+    ShapeSize _ _                   -> TupRsingle scalarTypeInt+    Foreign tp _ _ _                -> tp+    Undef tp                        -> TupRsingle tp+    Coerce _ tp _                   -> TupRsingle tp+++-- Smart constructors+-- ------------------++-- | 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 :: forall e. (HasCallStack, Elt e) => e -> Exp e+constant = Exp . go (eltR @e) . fromElt+  where+    go :: HasCallStack => TypeR t -> t -> SmartExp t+    go TupRunit         ()       = SmartExp $ Nil+    go (TupRsingle tp)  c        = SmartExp $ Const tp c+    go (TupRpair t1 t2) (c1, c2) = SmartExp $ go t1 c1 `Pair` go t2 c2++-- | 'undef' can be used anywhere a constant is expected, and indicates that the+-- consumer of the value can receive an unspecified bit pattern.+--+-- This is useful because a store of an undefined value can be assumed to not+-- have any effect; we can assume that the value is overwritten with bits that+-- happen to match what was already there. However, a store /to/ an undefined+-- location could clobber arbitrary memory, therefore, its use in such a context+-- would introduce undefined /behaviour/.+--+-- There are (at least) two cases where you may want to use this:+--+--   1. The 'Data.Array.Accelerate.Language.permute' function requires an array+--      of default values, into which the new values are combined. However, if+--      you are sure the default values are not used, and will (eventually) be+--      completely overwritten, then 'Data.Array.Accelerate.Prelude.fill'ing an+--      array with this value will give you a new uninitialised array.+--+--   2. In the definition of sum data types. See for example+--      "Data.Array.Accelerate.Data.Maybe" and+--      "Data.Array.Accelerate.Data.Either".+--+-- @since 1.2.0.0+--+undef :: forall e. Elt e => Exp e+undef = Exp $ go $ eltR @e+  where+    go :: TypeR t -> SmartExp t+    go TupRunit         = SmartExp $ Nil+    go (TupRsingle t)   = SmartExp $ Undef t+    go (TupRpair t1 t2) = SmartExp $ go t1 `Pair` go t2++-- | Get the innermost dimension of a shape.+--+-- The innermost dimension (right-most component of the shape) is the index of+-- the array which varies most rapidly, and corresponds to elements of the array+-- which are adjacent in memory.+--+-- Another way to think of this is, for example when writing nested loops over+-- an array in C, this index corresponds to the index iterated over by the+-- innermost nested loop.+--+indexHead :: (Elt sh, Elt a) => Exp (sh :. a) -> Exp a+indexHead (Exp x) = mkExp $ Prj PairIdxRight x++-- | Get all but the innermost element of a shape+--+indexTail :: (Elt sh, Elt a) => Exp (sh :. a) -> Exp sh+indexTail (Exp x) = mkExp $ Prj PairIdxLeft x+++-- Smart constructor for constants+--++mkMinBound :: (Elt t, IsBounded (EltR t)) => Exp t+mkMinBound = mkExp $ PrimConst (PrimMinBound boundedType)++mkMaxBound :: (Elt t, IsBounded (EltR t)) => Exp t+mkMaxBound = mkExp $ PrimConst (PrimMaxBound boundedType)++mkPi :: (Elt r, IsFloating (EltR r)) => Exp r+mkPi = mkExp $ PrimConst (PrimPi floatingType)+++-- Smart constructors for primitive applications+--++-- Operators from Floating++mkSin :: (Elt t, IsFloating (EltR t)) => Exp t -> Exp t+mkSin = mkPrimUnary $ PrimSin floatingType++mkCos :: (Elt t, IsFloating (EltR t)) => Exp t -> Exp t+mkCos = mkPrimUnary $ PrimCos floatingType++mkTan :: (Elt t, IsFloating (EltR t)) => Exp t -> Exp t+mkTan = mkPrimUnary $ PrimTan floatingType++mkAsin :: (Elt t, IsFloating (EltR t)) => Exp t -> Exp t+mkAsin = mkPrimUnary $ PrimAsin floatingType++mkAcos :: (Elt t, IsFloating (EltR t)) => Exp t -> Exp t+mkAcos = mkPrimUnary $ PrimAcos floatingType++mkAtan :: (Elt t, IsFloating (EltR t)) => Exp t -> Exp t+mkAtan = mkPrimUnary $ PrimAtan floatingType++mkSinh :: (Elt t, IsFloating (EltR t)) => Exp t -> Exp t+mkSinh = mkPrimUnary $ PrimSinh floatingType++mkCosh :: (Elt t, IsFloating (EltR t)) => Exp t -> Exp t+mkCosh = mkPrimUnary $ PrimCosh floatingType++mkTanh :: (Elt t, IsFloating (EltR t)) => Exp t -> Exp t+mkTanh = mkPrimUnary $ PrimTanh floatingType++mkAsinh :: (Elt t, IsFloating (EltR t)) => Exp t -> Exp t+mkAsinh = mkPrimUnary $ PrimAsinh floatingType++mkAcosh :: (Elt t, IsFloating (EltR t)) => Exp t -> Exp t+mkAcosh = mkPrimUnary $ PrimAcosh floatingType++mkAtanh :: (Elt t, IsFloating (EltR t)) => Exp t -> Exp t+mkAtanh = mkPrimUnary $ PrimAtanh floatingType++mkExpFloating :: (Elt t, IsFloating (EltR t)) => Exp t -> Exp t+mkExpFloating = mkPrimUnary $ PrimExpFloating floatingType++mkSqrt :: (Elt t, IsFloating (EltR t)) => Exp t -> Exp t+mkSqrt = mkPrimUnary $ PrimSqrt floatingType++mkLog :: (Elt t, IsFloating (EltR t)) => Exp t -> Exp t+mkLog = mkPrimUnary $ PrimLog floatingType++mkFPow :: (Elt t, IsFloating (EltR t)) => Exp t -> Exp t -> Exp t+mkFPow = mkPrimBinary $ PrimFPow floatingType++mkLogBase :: (Elt t, IsFloating (EltR t)) => Exp t -> Exp t -> Exp t+mkLogBase = mkPrimBinary $ PrimLogBase floatingType++-- Operators from Num++mkAdd :: (Elt t, IsNum (EltR t)) => Exp t -> Exp t -> Exp t+mkAdd = mkPrimBinary $ PrimAdd numType++mkSub :: (Elt t, IsNum (EltR t)) => Exp t -> Exp t -> Exp t+mkSub = mkPrimBinary $ PrimSub numType++mkMul :: (Elt t, IsNum (EltR t)) => Exp t -> Exp t -> Exp t+mkMul = mkPrimBinary $ PrimMul numType++mkNeg :: (Elt t, IsNum (EltR t)) => Exp t -> Exp t+mkNeg = mkPrimUnary $ PrimNeg numType++mkAbs :: (Elt t, IsNum (EltR t)) => Exp t -> Exp t+mkAbs = mkPrimUnary $ PrimAbs numType++mkSig :: (Elt t, IsNum (EltR t)) => Exp t -> Exp t+mkSig = mkPrimUnary $ PrimSig numType++-- Operators from Integral++mkQuot :: (Elt t, IsIntegral (EltR t)) => Exp t -> Exp t -> Exp t+mkQuot = mkPrimBinary $ PrimQuot integralType++mkRem :: (Elt t, IsIntegral (EltR t)) => Exp t -> Exp t -> Exp t+mkRem = mkPrimBinary $ PrimRem integralType++mkQuotRem :: (Elt t, IsIntegral (EltR t)) => Exp t -> Exp t -> (Exp t, Exp t)+mkQuotRem (Exp x) (Exp y) =+  let pair = SmartExp $ PrimQuotRem integralType `PrimApp` SmartExp (Pair x y)+  in  (mkExp $ Prj PairIdxLeft pair, mkExp $ Prj PairIdxRight pair)++mkIDiv :: (Elt t, IsIntegral (EltR t)) => Exp t -> Exp t -> Exp t+mkIDiv = mkPrimBinary $ PrimIDiv integralType++mkMod :: (Elt t, IsIntegral (EltR t)) => Exp t -> Exp t -> Exp t+mkMod = mkPrimBinary $ PrimMod integralType++mkDivMod :: (Elt t, IsIntegral (EltR t)) => Exp t -> Exp t -> (Exp t, Exp t)+mkDivMod (Exp x) (Exp y) =+  let pair = SmartExp $ PrimDivMod integralType `PrimApp` SmartExp (Pair x y)+  in  (mkExp $ Prj PairIdxLeft pair, mkExp $ Prj PairIdxRight pair)++-- Operators from Bits and FiniteBits++mkBAnd :: (Elt t, IsIntegral (EltR t)) => Exp t -> Exp t -> Exp t+mkBAnd = mkPrimBinary $ PrimBAnd integralType++mkBOr :: (Elt t, IsIntegral (EltR t)) => Exp t -> Exp t -> Exp t+mkBOr = mkPrimBinary $ PrimBOr integralType++mkBXor :: (Elt t, IsIntegral (EltR t)) => Exp t -> Exp t -> Exp t+mkBXor = mkPrimBinary $ PrimBXor integralType++mkBNot :: (Elt t, IsIntegral (EltR t)) => Exp t -> Exp t+mkBNot = mkPrimUnary $ PrimBNot integralType++mkBShiftL :: (Elt t, IsIntegral (EltR t)) => Exp t -> Exp Int -> Exp t+mkBShiftL = mkPrimBinary $ PrimBShiftL integralType++mkBShiftR :: (Elt t, IsIntegral (EltR t)) => Exp t -> Exp Int -> Exp t+mkBShiftR = mkPrimBinary $ PrimBShiftR integralType++mkBRotateL :: (Elt t, IsIntegral (EltR t)) => Exp t -> Exp Int -> Exp t+mkBRotateL = mkPrimBinary $ PrimBRotateL integralType++mkBRotateR :: (Elt t, IsIntegral (EltR t)) => Exp t -> Exp Int -> Exp t+mkBRotateR = mkPrimBinary $ PrimBRotateR integralType++mkPopCount :: (Elt t, IsIntegral (EltR t)) => Exp t -> Exp Int+mkPopCount = mkPrimUnary $ PrimPopCount integralType++mkCountLeadingZeros :: (Elt t, IsIntegral (EltR t)) => Exp t -> Exp Int+mkCountLeadingZeros = mkPrimUnary $ PrimCountLeadingZeros integralType++mkCountTrailingZeros :: (Elt t, IsIntegral (EltR t)) => Exp t -> Exp Int+mkCountTrailingZeros = mkPrimUnary $ PrimCountTrailingZeros integralType+++-- Operators from Fractional++mkFDiv :: (Elt t, IsFloating (EltR t)) => Exp t -> Exp t -> Exp t+mkFDiv = mkPrimBinary $ PrimFDiv floatingType++mkRecip :: (Elt t, IsFloating (EltR t)) => Exp t -> Exp t+mkRecip = mkPrimUnary $ PrimRecip floatingType++-- Operators from RealFrac++mkTruncate :: (Elt a, Elt b, IsFloating (EltR a), IsIntegral (EltR b)) => Exp a -> Exp b+mkTruncate = mkPrimUnary $ PrimTruncate floatingType integralType++mkRound :: (Elt a, Elt b, IsFloating (EltR a), IsIntegral (EltR b)) => Exp a -> Exp b+mkRound = mkPrimUnary $ PrimRound floatingType integralType++mkFloor :: (Elt a, Elt b, IsFloating (EltR a), IsIntegral (EltR b)) => Exp a -> Exp b+mkFloor = mkPrimUnary $ PrimFloor floatingType integralType++mkCeiling :: (Elt a, Elt b, IsFloating (EltR a), IsIntegral (EltR b)) => Exp a -> Exp b+mkCeiling = mkPrimUnary $ PrimCeiling floatingType integralType++-- Operators from RealFloat++mkAtan2 :: (Elt t, IsFloating (EltR t)) => Exp t -> Exp t -> Exp t+mkAtan2 = mkPrimBinary $ PrimAtan2 floatingType++mkIsNaN :: (Elt t, IsFloating (EltR t)) => Exp t -> Exp Bool+mkIsNaN = mkPrimUnaryBool $ PrimIsNaN floatingType++mkIsInfinite :: (Elt t, IsFloating (EltR t)) => Exp t -> Exp Bool+mkIsInfinite = mkPrimUnaryBool $ PrimIsInfinite floatingType++-- FIXME: add missing operations from Floating, RealFrac & RealFloat++-- Relational and equality operators++mkLt :: (Elt t, IsSingle (EltR t)) => Exp t -> Exp t -> Exp Bool+mkLt = mkPrimBinaryBool $ PrimLt singleType++mkGt :: (Elt t, IsSingle (EltR t)) => Exp t -> Exp t -> Exp Bool+mkGt = mkPrimBinaryBool $ PrimGt singleType++mkLtEq :: (Elt t, IsSingle (EltR t)) => Exp t -> Exp t -> Exp Bool+mkLtEq = mkPrimBinaryBool $ PrimLtEq singleType++mkGtEq :: (Elt t, IsSingle (EltR t)) => Exp t -> Exp t -> Exp Bool+mkGtEq = mkPrimBinaryBool $ PrimGtEq singleType++mkEq :: (Elt t, IsSingle (EltR t)) => Exp t -> Exp t -> Exp Bool+mkEq = mkPrimBinaryBool $ PrimEq singleType++mkNEq :: (Elt t, IsSingle (EltR t)) => Exp t -> Exp t -> Exp Bool+mkNEq = mkPrimBinaryBool $ PrimNEq singleType++mkMax :: (Elt t, IsSingle (EltR t)) => Exp t -> Exp t -> Exp t+mkMax = mkPrimBinary $ PrimMax singleType++mkMin :: (Elt t, IsSingle (EltR t)) => Exp t -> Exp t -> Exp t+mkMin = mkPrimBinary $ PrimMin singleType++-- Logical operators++mkLAnd :: Exp Bool -> Exp Bool -> Exp Bool+mkLAnd (Exp a) (Exp b) = mkExp $ SmartExp (PrimApp PrimLAnd (SmartExp $ Pair x y)) `Pair` SmartExp Nil+  where+    x = SmartExp $ Prj PairIdxLeft a+    y = SmartExp $ Prj PairIdxLeft b++mkLOr :: Exp Bool -> Exp Bool -> Exp Bool+mkLOr (Exp a) (Exp b) = mkExp $ SmartExp (PrimApp PrimLOr (SmartExp $ Pair x y)) `Pair` SmartExp Nil+  where+    x = SmartExp $ Prj PairIdxLeft a+    y = SmartExp $ Prj PairIdxLeft b++mkLNot :: Exp Bool -> Exp Bool+mkLNot (Exp a) = mkExp $ SmartExp (PrimApp PrimLNot x) `Pair` SmartExp Nil+  where+    x = SmartExp $ Prj PairIdxLeft a++-- Numeric conversions++mkFromIntegral :: (Elt a, Elt b, IsIntegral (EltR a), IsNum (EltR b)) => Exp a -> Exp b+mkFromIntegral = mkPrimUnary $ PrimFromIntegral integralType numType++mkToFloating :: (Elt a, Elt b, IsNum (EltR a), IsFloating (EltR b)) => Exp a -> Exp b+mkToFloating = mkPrimUnary $ PrimToFloating numType floatingType++-- Other conversions++-- NOTE: Restricted to scalar types with a type-level BitSizeEq constraint to+-- make this version "safe"+mkBitcast :: forall b a. (Elt a, Elt b, IsScalar (EltR a), IsScalar (EltR b), BitSizeEq (EltR a) (EltR b)) => Exp a -> Exp b+mkBitcast (Exp a) = mkExp $ Coerce (scalarType @(EltR a)) (scalarType @(EltR b)) a++mkCoerce :: Coerce (EltR a) (EltR b) => Exp a -> Exp b+mkCoerce (Exp a) = Exp $ mkCoerce' a++class Coerce a b where+  mkCoerce' :: SmartExp a -> SmartExp b++instance {-# OVERLAPS #-} (IsScalar a, IsScalar b, BitSizeEq a b) => Coerce a b where+  mkCoerce' = SmartExp . Coerce (scalarType @a) (scalarType @b)++instance (Coerce a1 b1, Coerce a2 b2) => Coerce (a1, a2) (b1, b2) where+  mkCoerce' a = SmartExp $ Pair (mkCoerce' $ SmartExp $ Prj PairIdxLeft a) (mkCoerce' $ SmartExp $ Prj PairIdxRight a)++instance Coerce a a where+  mkCoerce' = id++instance Coerce ((), a) a where+  mkCoerce' a = SmartExp $ Prj PairIdxRight a++instance Coerce a ((), a) where+  mkCoerce' = SmartExp . Pair (SmartExp Nil)++instance Coerce (a, ()) a where+  mkCoerce' a = SmartExp $ Prj PairIdxLeft a++instance Coerce a (a, ()) where+  mkCoerce' a = SmartExp (Pair a (SmartExp Nil))++++-- 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)++unAcc :: Arrays a => Acc a -> SmartAcc (Sugar.ArraysR a)+unAcc (Acc a) = a++unAccFunction :: (Arrays a, Arrays b) => (Acc a -> Acc b) -> SmartAcc (Sugar.ArraysR a) -> SmartAcc (Sugar.ArraysR b)+unAccFunction f = unAcc . f . Acc++mkExp :: PreSmartExp SmartAcc SmartExp (EltR t) -> Exp t+mkExp = Exp . SmartExp++unExp :: Exp e -> SmartExp (EltR e)+unExp (Exp e) = e++unExpFunction :: (Elt a, Elt b) => (Exp a -> Exp b) -> SmartExp (EltR a) -> SmartExp (EltR b)+unExpFunction f = unExp . f . Exp++unExpBinaryFunction :: (Elt a, Elt b, Elt c) => (Exp a -> Exp b -> Exp c) -> SmartExp (EltR a) -> SmartExp (EltR b) -> SmartExp (EltR c)+unExpBinaryFunction f a b = unExp $ f (Exp a) (Exp b)++mkPrimUnary :: (Elt a, Elt b) => PrimFun (EltR a -> EltR b) -> Exp a -> Exp b+mkPrimUnary prim (Exp a) = mkExp $ PrimApp prim a++mkPrimBinary :: (Elt a, Elt b, Elt c) => PrimFun ((EltR a, EltR b) -> EltR c) -> Exp a -> Exp b -> Exp c+mkPrimBinary prim (Exp a) (Exp b) = mkExp $ PrimApp prim (SmartExp $ Pair a b)++mkPrimUnaryBool :: Elt a => PrimFun (EltR a -> PrimBool) -> Exp a -> Exp Bool+mkPrimUnaryBool = mkCoerce @PrimBool $$ mkPrimUnary++mkPrimBinaryBool :: (Elt a, Elt b) => PrimFun ((EltR a, EltR b) -> PrimBool) -> Exp a -> Exp b -> Exp Bool+mkPrimBinaryBool = mkCoerce @PrimBool $$$ mkPrimBinary++unPair :: SmartExp (a, b) -> (SmartExp a, SmartExp b)+unPair e = (SmartExp $ Prj PairIdxLeft e, SmartExp $ Prj PairIdxRight e)++mkPairToTuple :: SmartAcc (a, b) -> SmartAcc (((), a), b)+mkPairToTuple e = SmartAcc Anil `pair` a `pair` b+  where+    a = SmartAcc $ Aprj PairIdxLeft e+    b = SmartAcc $ Aprj PairIdxRight e+    pair x y = SmartAcc $ Apair x y++class ApplyAcc a where+  type FromApplyAcc a+  applyAcc :: FromApplyAcc a -> a++instance ApplyAcc (SmartAcc a) where+  type FromApplyAcc (SmartAcc a) = PreSmartAcc SmartAcc SmartExp a+  applyAcc = SmartAcc++instance (Arrays a, ApplyAcc t) => ApplyAcc (Acc a -> t) where+  type FromApplyAcc (Acc a -> t) = SmartAcc (Sugar.ArraysR a) -> FromApplyAcc t+  applyAcc f a = applyAcc $ f (unAcc a)++instance (Elt a, ApplyAcc t) => ApplyAcc (Exp a -> t) where+  type FromApplyAcc (Exp a -> t) = SmartExp (EltR a) -> FromApplyAcc t+  applyAcc f a = applyAcc $ f (unExp a)++instance (Elt a, Elt b, ApplyAcc t) => ApplyAcc ((Exp a -> Exp b) -> t) where+  type FromApplyAcc ((Exp a -> Exp b) -> t) = (SmartExp (EltR a) -> SmartExp (EltR b)) -> FromApplyAcc t+  applyAcc f a = applyAcc $ f (unExpFunction a)++instance (Elt a, Elt b, Elt c, ApplyAcc t) => ApplyAcc ((Exp a -> Exp b -> Exp c) -> t) where+  type FromApplyAcc ((Exp a -> Exp b -> Exp c) -> t) = (SmartExp (EltR a) -> SmartExp (EltR b) -> SmartExp (EltR c)) -> FromApplyAcc t+  applyAcc f a = applyAcc $ f (unExpBinaryFunction a)++instance (Arrays a, Arrays b, ApplyAcc t) => ApplyAcc ((Acc a -> Acc b) -> t) where+  type FromApplyAcc ((Acc a -> Acc b) -> t) = (SmartAcc (Sugar.ArraysR a) -> SmartAcc (Sugar.ArraysR b)) -> FromApplyAcc t+  applyAcc f a = applyAcc $ f (unAccFunction a)+++-- Debugging+-- ---------++showPreAccOp :: forall acc exp arrs. PreSmartAcc acc exp arrs -> String+showPreAccOp (Atag _ i)            = "Atag " ++ show i+showPreAccOp (Use aR a)            = "Use "  ++ showArrayShort 5 (showsElt (arrayRtype aR)) aR a+showPreAccOp Pipe{}                = "Pipe"+showPreAccOp Acond{}               = "Acond"+showPreAccOp Awhile{}              = "Awhile"+showPreAccOp Apair{}               = "Apair"+showPreAccOp Anil{}                = "Anil"+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 _ _ z _)        = "Fold" ++ maybe "1" (const "") z+showPreAccOp (FoldSeg _ _ _ z _ _) = "Fold" ++ maybe "1" (const "") z ++ "Seg"+showPreAccOp (Scan d _ _ z _)      = "Scan" ++ showsDirection d (maybe "1" (const "") z)+showPreAccOp (Scan' d _ _ _ _)     = "Scan" ++ showsDirection d "'"+showPreAccOp Permute{}             = "Permute"+showPreAccOp Backpermute{}         = "Backpermute"+showPreAccOp Stencil{}             = "Stencil"+showPreAccOp Stencil2{}            = "Stencil2"+showPreAccOp Aforeign{}            = "Aforeign"++showsDirection :: Direction -> ShowS+showsDirection LeftToRight = ('l':)+showsDirection RightToLeft = ('r':)++showPreExpOp :: PreSmartExp acc exp t -> String+showPreExpOp (Tag _ i)          = "Tag" ++ show i+showPreExpOp Match{}            = "Match"+showPreExpOp (Const t c)        = "Const " ++ showElt (TupRsingle t) c+showPreExpOp (Undef _)          = "Undef"+showPreExpOp Nil{}              = "Nil"+showPreExpOp Pair{}             = "Pair"+showPreExpOp Prj{}              = "Prj"+showPreExpOp VecPack{}          = "VecPack"+showPreExpOp VecUnpack{}        = "VecUnpack"+showPreExpOp ToIndex{}          = "ToIndex"+showPreExpOp FromIndex{}        = "FromIndex"+showPreExpOp Case{}             = "Case"+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 Foreign{}          = "Foreign" showPreExpOp Coerce{}           = "Coerce" 
+ src/Data/Array/Accelerate/Sugar/Array.hs view
@@ -0,0 +1,319 @@+{-# LANGUAGE AllowAmbiguousTypes  #-}+{-# LANGUAGE DefaultSignatures    #-}+{-# LANGUAGE FlexibleContexts     #-}+{-# LANGUAGE FlexibleInstances    #-}+{-# LANGUAGE ScopedTypeVariables  #-}+{-# LANGUAGE TemplateHaskell      #-}+{-# LANGUAGE TypeApplications     #-}+{-# LANGUAGE TypeFamilies         #-}+{-# LANGUAGE TypeOperators        #-}+{-# LANGUAGE UndecidableInstances #-}+{-# OPTIONS_HADDOCK hide #-}+-- |+-- Module      : Data.Array.Accelerate.Sugar.Array+-- Copyright   : [2008..2020] The Accelerate Team+-- License     : BSD3+--+-- Maintainer  : Trevor L. McDonell <trevor.mcdonell@gmail.com>+-- Stability   : experimental+-- Portability : non-portable (GHC extensions)+--++module Data.Array.Accelerate.Sugar.Array+  where++import Data.Array.Accelerate.Sugar.Elt+import Data.Array.Accelerate.Sugar.Shape+import Data.Array.Accelerate.Representation.Type+import qualified Data.Array.Accelerate.Representation.Array         as R++import Control.DeepSeq+import Data.Kind+import Data.Typeable+import Language.Haskell.TH                                          hiding ( Type )+import Language.Haskell.TH.Extra+import System.IO.Unsafe++import GHC.Exts                                                     ( IsList )+import GHC.Generics+import qualified GHC.Exts                                           as GHC++-- $setup+-- >>> :seti -XOverloadedLists+++type Scalar = Array DIM0    -- ^ Scalar arrays hold a single element+type Vector = Array DIM1    -- ^ Vectors are one-dimensional arrays+type Matrix = Array DIM2    -- ^ Matrices are two-dimensional arrays++-- | 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 sub-arrays.+--+type Segments = Vector+++-- | 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 16-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.+--+newtype Array sh e = Array (R.Array (EltR sh) (EltR e))+  deriving Typeable++instance (Shape sh, Elt e, Eq sh, Eq e) => Eq (Array sh e) where+  arr1 == arr2 = shape arr1 == shape arr2 && toList arr1 == toList arr2+  arr1 /= arr2 = shape arr1 /= shape arr2 || toList arr1 /= toList arr2++instance (Shape sh, Elt e, Show e) => Show (Array sh e) where+  show (Array arr) = R.showArray (shows . toElt @e) (arrayR @sh @e) arr++instance Elt e => IsList (Array DIM1 e) where+  type Item (Vector e) = e+  toList      = toList+  fromListN n = fromList (Z:.n)+  fromList xs = GHC.fromListN (length xs) xs++instance (Shape sh, Elt e) => NFData (Array sh e) where+  rnf (Array arr) = R.rnfArray (arrayR @sh @e) arr++-- Note: [Embedded class constraints on Array]+--+-- Previously, we had embedded 'Shape' and 'Elt' constraints on the 'Array'+-- constructor. This was occasionally convenient, however, this has a negative+-- impact on the kind of code which GHC can generate. For example, if we write+-- the function:+--+-- > (!) :: Array sh e -> sh -> e+--+-- Without the 'Shape' and 'Elt' constraints on the type signature, and instead+-- recover those when pattern matching on 'Array', then GHC is unable to+-- specialise functions past this point. In this example, even if 'sh' and 'e'+-- are fixed, GHC would not be able to inline the definitions from 'ArrayElt'+-- which perform the actual data accesses.+--+--   - TLM 2018-09-13+--++-- | Yield an array's shape+--+shape :: Shape sh => Array sh e -> sh+shape (Array arr) = toElt (R.shape arr)++-- | Change the shape of an array without altering its contents. The 'size' of+-- the source and result arrays must be identical.+--+reshape :: forall sh sh' e. (Shape sh, Shape sh') => sh -> Array sh' e -> Array sh e+reshape sh (Array arr) = Array $ R.reshape (shapeR @sh) (fromElt sh) (shapeR @sh') arr++-- | Return the value of an array at the given multidimensional index+--+infixl 9 !+(!) :: forall sh e. (Shape sh, Elt e) => Array sh e -> sh -> e+(!) (Array arr) ix = toElt $ R.indexArray (arrayR @sh @e) arr (fromElt ix)++-- | Return the value of an array at given the linear (row-major) index+--+infixl 9 !!+(!!) :: forall sh e. Elt e => Array sh e -> Int -> e+(!!) (Array arr) i = toElt $ R.linearIndexArray (eltR @e) arr i++-- | 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+fromFunction sh f = unsafePerformIO $! fromFunctionM sh (return . f)++-- | Create an array using a monadic function applied at each index+--+-- @since 1.2.0.0+--+fromFunctionM :: forall sh e. (Shape sh, Elt e) => sh -> (sh -> IO e) -> IO (Array sh e)+fromFunctionM sh f = Array <$> R.fromFunctionM (arrayR @sh @e) (fromElt sh) f'+  where+    f' x = do+      y <- f (toElt x)+      return (fromElt y)++-- | Create a vector from the concatenation of the given list of vectors+--+concatVectors :: forall e. Elt e => [Vector e] -> Vector e+concatVectors = toArr . R.concatVectors (eltR @e) . map fromArr++-- | Creates a new, uninitialized Accelerate array+--+allocateArray :: forall sh e. (Shape sh, Elt e) => sh -> IO (Array sh e)+allocateArray sh = Array <$> R.allocateArray (arrayR @sh @e) (fromElt 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) :: Matrix 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 :: forall sh e. (Shape sh, Elt e) => sh -> [e] -> Array sh e+fromList sh xs = toArr $ R.fromList (arrayR @sh @e) (fromElt sh) $ map fromElt xs++-- | Convert an accelerated 'Array' to a list in row-major order+--+toList :: forall sh e. (Shape sh, Elt e) => Array sh e -> [e]+toList = map toElt . R.toList (arrayR @sh @e) . fromArr+++-- | The 'Arrays' class characterises the types which can appear in collective+-- Accelerate computations of type 'Data.Array.Accelerate.Acc'.+--+-- 'Arrays' consists of nested tuples of individual 'Array's, currently up+-- to 16-elements wide. Accelerate computations can thereby return multiple+-- results.+--+class Arrays a where+  -- | Type representation mapping, which explains how to convert from the+  -- surface type into the internal representation type, which consists+  -- only of 'Array', and '()' and '(,)' as type-level nil and snoc.+  --+  type ArraysR a :: Type+  type ArraysR a = GArraysR () (Rep a)++  arraysR :: R.ArraysR (ArraysR a)+  toArr   :: ArraysR  a -> a+  fromArr :: a -> ArraysR  a++  default arraysR+    :: (GArrays (Rep a), ArraysR a ~ GArraysR () (Rep a))+    => R.ArraysR (ArraysR a)+  arraysR = garrays @(Rep a) TupRunit++  default toArr+    :: (Generic a, GArrays (Rep a), ArraysR a ~ GArraysR () (Rep a))+    => ArraysR a -> a+  toArr = to . snd . gtoArr @(Rep a) @()++  default fromArr+    :: (Generic a, GArrays (Rep a), ArraysR a ~ GArraysR () (Rep a))+    => a -> ArraysR a+  fromArr = (`gfromArr` ()) . from++arrayR :: forall sh e. (Shape sh, Elt e) => R.ArrayR (R.Array (EltR sh) (EltR e))+arrayR = R.ArrayR (shapeR @sh) (eltR @e)++class GArrays f where+  type GArraysR t f+  garrays  :: R.ArraysR t -> R.ArraysR (GArraysR t f)+  gfromArr :: f a -> t -> GArraysR t f+  gtoArr   :: GArraysR t f -> (t, f a)++instance GArrays U1 where+  type GArraysR t U1 = t+  garrays       =  id+  gfromArr U1   =  id+  gtoArr      t = (t, U1)++instance GArrays a => GArrays (M1 i c a) where+  type GArraysR t (M1 i c a) = GArraysR t a+  garrays         = garrays @a+  gfromArr (M1 x) = gfromArr x+  gtoArr       x  = let (t, x1) = gtoArr x in (t, M1 x1)++instance Arrays a => GArrays (K1 i a) where+  type GArraysR t (K1 i a) = (t, ArraysR a)+  garrays         t = TupRpair t (arraysR @a)+  gfromArr (K1 x) t = (t, fromArr x)+  gtoArr   (t, x)   = (t, K1 (toArr x))++instance (GArrays a, GArrays b) => GArrays (a :*: b) where+  type GArraysR t (a :*: b) = GArraysR (GArraysR t a) b+  garrays            = garrays @b . garrays @a+  gfromArr (a :*: b) = gfromArr b . gfromArr a+  gtoArr t =+    let (t1, b) = gtoArr t+        (t2, a) = gtoArr t1+    in+    (t2, a :*: b)+++instance Arrays () where+  type ArraysR () = ()+  arraysR = TupRunit+  fromArr = id+  toArr   = id++instance (Shape sh, Elt e) => Arrays (Array sh e) where+  type ArraysR (Array sh e) = R.Array (EltR sh) (EltR e)+  arraysR = R.arraysRarray (shapeR @sh) (eltR @e)+  fromArr (Array arr) = arr+  toArr               = Array++runQ $ do+  let+      mkTuple :: Int -> Q Dec+      mkTuple n =+        let+            xs  = [ mkName ('x' : show i) | i <- [0 .. n-1] ]+            ts  = map varT xs+            res = tupT ts+            ctx = mapM (appT [t| Arrays |]) ts+        in+        instanceD ctx [t| Arrays $res |] []+  --+  mapM mkTuple [2..16]+
+ src/Data/Array/Accelerate/Sugar/Elt.hs view
@@ -0,0 +1,415 @@+{-# LANGUAGE AllowAmbiguousTypes  #-}+{-# LANGUAGE DataKinds            #-}+{-# LANGUAGE DefaultSignatures    #-}+{-# LANGUAGE FlexibleContexts     #-}+{-# LANGUAGE FlexibleInstances    #-}+{-# LANGUAGE ScopedTypeVariables  #-}+{-# LANGUAGE TemplateHaskell      #-}+{-# LANGUAGE TupleSections        #-}+{-# LANGUAGE TypeApplications     #-}+{-# LANGUAGE TypeFamilies         #-}+{-# LANGUAGE TypeOperators        #-}+{-# LANGUAGE UndecidableInstances #-}+{-# OPTIONS_HADDOCK hide #-}+-- |+-- Module      : Data.Array.Accelerate.Sugar.Elt+-- Copyright   : [2008..2020] The Accelerate Team+-- License     : BSD3+--+-- Maintainer  : Trevor L. McDonell <trevor.mcdonell@gmail.com>+-- Stability   : experimental+-- Portability : non-portable (GHC extensions)+--++module Data.Array.Accelerate.Sugar.Elt ( Elt(..) )+  where++import Data.Array.Accelerate.Representation.Elt+import Data.Array.Accelerate.Representation.Tag+import Data.Array.Accelerate.Representation.Type+import Data.Array.Accelerate.Type++import Data.Bits+import Data.Char+import Data.Kind+import Language.Haskell.TH                                          hiding ( Type )+import Language.Haskell.TH.Extra++import GHC.Generics+++-- | The 'Elt' class characterises the allowable array element types, and+-- hence the types which can appear in scalar Accelerate expressions of+-- type 'Data.Array.Accelerate.Exp'.+--+-- 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 (half, single, and double precision)+--  * 'Char'+--  * 'Bool'+--  * ()+--  * Shapes formed from 'Z' and (':.')+--  * Nested tuples of all of these, currently up to 16-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>+--+-- For simple types it is possible to derive 'Elt' automatically, for+-- example:+--+-- > data Point = Point Int Float+-- >   deriving (Generic, Elt)+--+-- > data Option a = None | Just a+-- >   deriving (Generic, Elt)+--+-- See the function 'Data.Array.Accelerate.match' for details on how to use+-- sum types in embedded code.+--+class Elt a where+  -- | Type representation mapping, which explains how to convert a type+  -- from the surface type into the internal representation type consisting+  -- only of simple primitive types, unit '()', and pair '(,)'.+  --+  type EltR a :: Type+  type EltR a = GEltR () (Rep a)+  --+  eltR    :: TypeR (EltR a)+  tagsR   :: [TagR (EltR a)]+  fromElt :: a -> EltR a+  toElt   :: EltR a -> a++  default eltR+      :: (GElt (Rep a), EltR a ~ GEltR () (Rep a))+      => TypeR (EltR a)+  eltR = geltR @(Rep a) TupRunit++  default tagsR+      :: (Generic a, GElt (Rep a), EltR a ~ GEltR () (Rep a))+      => [TagR (EltR a)]+  tagsR = gtagsR @(Rep a) TagRunit++  default fromElt+      :: (Generic a, GElt (Rep a), EltR a ~ GEltR () (Rep a))+      => a+      -> EltR a+  fromElt = gfromElt () . from++  default toElt+      :: (Generic a, GElt (Rep a), EltR a ~ GEltR () (Rep a))+      => EltR a+      -> a+  toElt = to . snd . gtoElt @(Rep a) @()+++class GElt f where+  type GEltR t f+  geltR    :: TypeR t -> TypeR (GEltR t f)+  gtagsR   :: TagR t -> [TagR (GEltR t f)]+  gfromElt :: t -> f a -> GEltR t f+  gtoElt   :: GEltR t f -> (t, f a)+  --+  gundef   :: t -> GEltR t f+  guntag   :: TagR t -> TagR (GEltR t f)++instance GElt U1 where+  type GEltR t U1 = t+  geltR t       = t+  gtagsR t      = [t]+  gfromElt t U1 = t+  gtoElt t      = (t, U1)+  gundef t      = t+  guntag t      = t++instance GElt a => GElt (M1 i c a) where+  type GEltR t (M1 i c a) = GEltR t a+  geltR             = geltR @a+  gtagsR            = gtagsR @a+  gfromElt t (M1 x) = gfromElt t x+  gtoElt         x  = let (t, x1) = gtoElt x in (t, M1 x1)+  gundef            = gundef @a+  guntag            = guntag @a++instance Elt a => GElt (K1 i a) where+  type GEltR t (K1 i a) = (t, EltR a)+  geltR t           = TupRpair t (eltR @a)+  gtagsR t          = TagRpair t <$> tagsR @a+  gfromElt t (K1 x) = (t, fromElt x)+  gtoElt     (t, x) = (t, K1 (toElt x))+  gundef t          = (t, undefElt (eltR @a))+  guntag t          = TagRpair t (untag (eltR @a))++instance (GElt a, GElt b) => GElt (a :*: b) where+  type GEltR t (a :*: b) = GEltR (GEltR t a) b+  geltR  = geltR @b . geltR @a+  gtagsR = concatMap (gtagsR @b) . gtagsR @a+  gfromElt t (a :*: b) = gfromElt (gfromElt t a) b+  gtoElt t =+    let (t1, b) = gtoElt t+        (t2, a) = gtoElt t1+    in+    (t2, a :*: b)+  gundef t = gundef @b (gundef @a t)+  guntag t = guntag @b (guntag @a t)++instance (GElt a, GElt b, GSumElt (a :+: b)) => GElt (a :+: b) where+  type GEltR t (a :+: b) = (TAG, GSumEltR t (a :+: b))+  geltR t      = TupRpair (TupRsingle scalarType) (gsumEltR @(a :+: b) t)+  gtagsR t     = uncurry TagRtag <$> gsumTagsR @(a :+: b) 0 t+  gfromElt     = gsumFromElt 0+  gtoElt (k,x) = gsumToElt k x+  gundef t     = (0xff, gsumUndef @(a :+: b) t)+  guntag t     = TagRpair (TagRundef scalarType) (gsumUntag @(a :+: b) t)+++class GSumElt f where+  type GSumEltR t f+  gsumEltR     :: TypeR t -> TypeR (GSumEltR t f)+  gsumTagsR    :: TAG -> TagR t -> [(TAG, TagR (GSumEltR t f))]+  gsumFromElt  :: TAG -> t -> f a -> (TAG, GSumEltR t f)+  gsumToElt    :: TAG -> GSumEltR t f -> (t, f a)+  gsumUndef    :: t -> GSumEltR t f+  gsumUntag    :: TagR t -> TagR (GSumEltR t f)++instance GSumElt U1 where+  type GSumEltR t U1 = t+  gsumEltR t         = t+  gsumTagsR n t      = [(n, t)]+  gsumFromElt n t U1 = (n, t)+  gsumToElt _ t      = (t, U1)+  gsumUndef t        = t+  gsumUntag t        = t++instance GSumElt a => GSumElt (M1 i c a) where+  type GSumEltR t (M1 i c a) = GSumEltR t a+  gsumEltR               = gsumEltR @a+  gsumTagsR              = gsumTagsR @a+  gsumFromElt n t (M1 x) = gsumFromElt n t x+  gsumToElt k x          = let (t, x') = gsumToElt k x in (t, M1 x')+  gsumUntag              = gsumUntag @a+  gsumUndef              = gsumUndef @a++instance Elt a => GSumElt (K1 i a) where+  type GSumEltR t (K1 i a) = (t, EltR a)+  gsumEltR t             = TupRpair t (eltR @a)+  gsumTagsR n t          = (n,) . TagRpair t <$> tagsR @a+  gsumFromElt n t (K1 x) = (n, (t, fromElt x))+  gsumToElt _ (t, x)     = (t, K1 (toElt x))+  gsumUntag t            = TagRpair t (untag (eltR @a))+  gsumUndef t            = (t, undefElt (eltR @a))++instance (GElt a, GElt b) => GSumElt (a :*: b) where+  type GSumEltR t (a :*: b) = GEltR t (a :*: b)+  gsumEltR                  = geltR @(a :*: b)+  gsumTagsR n t             = (n,) <$> gtagsR @(a :*: b) t+  gsumFromElt n t (a :*: b) = (n, gfromElt (gfromElt t a) b)+  gsumToElt _ t0 =+    let (t1, b) = gtoElt t0+        (t2, a) = gtoElt t1+     in+     (t2, a :*: b)+  gsumUndef       = gundef @(a :*: b)+  gsumUntag       = guntag @(a :*: b)++instance (GSumElt a, GSumElt b) => GSumElt (a :+: b) where+  type GSumEltR t (a :+: b) = GSumEltR (GSumEltR t a) b+  gsumEltR = gsumEltR @b . gsumEltR @a++  gsumFromElt n t (L1 a) = let (m,r) = gsumFromElt n t a+                            in (shiftL m 1, gsumUndef @b r)+  gsumFromElt n t (R1 b) = let (m,r) = gsumFromElt n (gsumUndef @a t) b+                            in (setBit (m `shiftL` 1) 0, r)++  gsumToElt k t0 =+    let (t1, b) = gsumToElt (shiftR k 1) t0+        (t2, a) = gsumToElt (shiftR k 1) t1+     in+     if testBit k 0+        then (t2, R1 b)+        else (t2, L1 a)++  gsumTagsR k t =+    let a = gsumTagsR @a k t+        b = gsumTagsR @b k (gsumUntag @a t)+     in+     map (\(x,y) ->         (x `shiftL` 1, gsumUntag @b y)) a +++     map (\(x,y) -> (setBit (x `shiftL` 1) 0, y)) b++  gsumUndef t = gsumUndef @b (gsumUndef @a t)+  gsumUntag t = gsumUntag @b (gsumUntag @a t)+++class GTags (f :: Type -> Type) where+  gtags :: TAG -> [(String, TAG)]++instance GTags a => GTags (D1 c a) where+  gtags = gtags @a++instance Constructor c => GTags (C1 c a) where+  gtags k = [ (conName (undefined :: D1 c a ()), k) ]++instance (GTags a, GTags b) => GTags (a :+: b) where+  gtags k =+    let as = gtags @a k+        bs = gtags @b k+     in+     map (\(x,y) -> (x,         y `shiftL` 1)   ) as +++     map (\(x,y) -> (x, setBit (y `shiftL` 1) 0)) bs+++untag :: TypeR t -> TagR t+untag TupRunit         = TagRunit+untag (TupRsingle t)   = TagRundef t+untag (TupRpair ta tb) = TagRpair (untag ta) (untag tb)+++-- Note: [Deriving Elt]+--+-- We can't use the cunning generalised newtype deriving mechanism, because+-- the generated 'eltR function does not type check. For example, it will+-- generate the following implementation for 'CShort':+--+-- > eltR+-- >   = coerce+-- >       @(TypeR (EltR Int16))+-- >       @(TypeR (EltR CShort))+-- >       (eltR :: TypeR (EltR CShort))+--+-- Which yields the error "couldn't match type 'EltR a0' with 'Int16'".+-- Since this function returns a type family type, the type signature on the+-- result is not enough to fix the type 'a'. Instead, we require the use of+-- (visible) type applications:+--+-- > eltR+-- >   = coerce+-- >       @(TypeR (EltR Int16))+-- >       @(TypeR (EltR CShort))+-- >       (eltR @(EltR CShort))+--+-- Note that this does not affect deriving instances via 'Generic'+--+-- Instances for basic types are generated at the end of this module.+--++instance Elt ()+instance Elt Bool+instance Elt Ordering+instance Elt a => Elt (Maybe a)+instance (Elt a, Elt b) => Elt (Either a b)++instance Elt Char where+  type EltR Char = Word32+  eltR    = TupRsingle scalarType+  tagsR   = [TagRsingle scalarType]+  toElt   = chr . fromIntegral+  fromElt = fromIntegral . ord++runQ $ do+  let+      -- XXX: we might want to do the digItOut trick used by FromIntegral?+      --+      integralTypes :: [Name]+      integralTypes =+        [ ''Int+        , ''Int8+        , ''Int16+        , ''Int32+        , ''Int64+        , ''Word+        , ''Word8+        , ''Word16+        , ''Word32+        , ''Word64+        ]++      floatingTypes :: [Name]+      floatingTypes =+        [ ''Half+        , ''Float+        , ''Double+        ]++      newtypes :: [Name]+      newtypes =+        [ ''CShort+        , ''CUShort+        , ''CInt+        , ''CUInt+        , ''CLong+        , ''CULong+        , ''CLLong+        , ''CULLong+        , ''CFloat+        , ''CDouble+        , ''CChar+        , ''CSChar+        , ''CUChar+        ]++      mkSimple :: Name -> Q [Dec]+      mkSimple name =+        let t = conT name+        in+        [d| instance Elt $t where+              type EltR $t = $t+              eltR    = TupRsingle scalarType+              tagsR   = [TagRsingle scalarType]+              fromElt = id+              toElt   = id+          |]++      mkTuple :: Int -> Q Dec+      mkTuple n =+        let+            xs  = [ mkName ('x' : show i) | i <- [0 .. n-1] ]+            ts  = map varT xs+            res = tupT ts+            ctx = mapM (appT [t| Elt |]) ts+        in+        instanceD ctx [t| Elt $res |] []++      -- mkVecElt :: Name -> Integer -> Q [Dec]+      -- mkVecElt name n =+      --   let t = conT name+      --       v = [t| Vec $(litT (numTyLit n)) $t |]+      --    in+      --    [d| instance Elt $v where+      --          type EltR $v = $v+      --          eltR    = TupRsingle scalarType+      --          fromElt = id+      --          toElt   = id+      --      |]++      -- ghci> $( stringE . show =<< reify ''CFloat )+      -- TyConI (NewtypeD [] Foreign.C.Types.CFloat [] Nothing (NormalC Foreign.C.Types.CFloat [(Bang NoSourceUnpackedness NoSourceStrictness,ConT GHC.Types.Float)]) [])+      --+      mkNewtype :: Name -> Q [Dec]+      mkNewtype name = do+        r    <- reify name+        base <- case r of+                  TyConI (NewtypeD _ _ _ _ (NormalC _ [(_, ConT b)]) _) -> return b+                  _                                                     -> error "unexpected case generating newtype Elt instance"+        --+        [d| instance Elt $(conT name) where+              type EltR $(conT name) = $(conT base)+              eltR = TupRsingle scalarType+              tagsR = [TagRsingle scalarType]+              fromElt $(conP (mkName (nameBase name)) [varP (mkName "x")]) = x+              toElt = $(conE (mkName (nameBase name)))+          |]+  --+  ss <- mapM mkSimple (integralTypes ++ floatingTypes)+  ns <- mapM mkNewtype newtypes+  ts <- mapM mkTuple [2..16]+  -- vs <- sequence [ mkVecElt t n | t <- integralTypes ++ floatingTypes, n <- [2,3,4,8,16] ]+  return (concat ss ++ concat ns ++ ts)+
+ src/Data/Array/Accelerate/Sugar/Foreign.hs view
@@ -0,0 +1,37 @@+{-# LANGUAGE TemplateHaskell #-}+{-# OPTIONS_HADDOCK hide #-}+-- |+-- Module      : Data.Array.Accelerate.Sugar.Foreign+-- Copyright   : [2008..2020] The Accelerate Team+-- License     : BSD3+--+-- Maintainer  : Trevor L. McDonell <trevor.mcdonell@gmail.com>+-- Stability   : experimental+-- Portability : non-portable (GHC extensions)+--++module Data.Array.Accelerate.Sugar.Foreign+  where++import Data.Array.Accelerate.Error++import Data.Typeable+import Language.Haskell.TH+++-- 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+  strForeign _ = "<foreign>"++  -- Backends which want to support compile-time embedding must be able to lift+  -- the foreign function into Template Haskell+  liftForeign :: HasCallStack => asm args -> Q (TExp (asm args))+  liftForeign _ = internalError "not supported by this backend"+
+ src/Data/Array/Accelerate/Sugar/Shape.hs view
@@ -0,0 +1,364 @@+{-# LANGUAGE AllowAmbiguousTypes  #-}+{-# LANGUAGE DeriveAnyClass       #-}+{-# LANGUAGE DeriveGeneric        #-}+{-# LANGUAGE FlexibleContexts     #-}+{-# LANGUAGE FlexibleInstances    #-}+{-# LANGUAGE ScopedTypeVariables  #-}+{-# LANGUAGE TypeApplications     #-}+{-# LANGUAGE TypeFamilies         #-}+{-# LANGUAGE TypeOperators        #-}+{-# LANGUAGE UndecidableInstances #-}+{-# OPTIONS_HADDOCK hide #-}+-- |+-- Module      : Data.Array.Accelerate.Sugar.Shape+-- Copyright   : [2008..2020] The Accelerate Team+-- License     : BSD3+--+-- Maintainer  : Trevor L. McDonell <trevor.mcdonell@gmail.com>+-- Stability   : experimental+-- Portability : non-portable (GHC extensions)+--+-- Array indices are snoc lists at both the type and value level. That is,+-- they're backwards, where the end-of-list token, 'Z', occurs first. For+-- example, the type of a rank-2 array index is @Z :. Int :. Int@, and+-- shape of a rank-2 array with 5 rows and 10 columns is @Z :. 5 :. 10@.+--+-- In Accelerate the rightmost dimension is the /fastest varying/ or+-- innermost; these values are adjacent in memory.+--++module Data.Array.Accelerate.Sugar.Shape+  where++import Data.Array.Accelerate.Sugar.Elt+import Data.Array.Accelerate.Representation.Tag+import Data.Array.Accelerate.Representation.Type+import qualified Data.Array.Accelerate.Representation.Shape         as R+import qualified Data.Array.Accelerate.Representation.Slice         as R++import Data.Kind+import GHC.Generics+++-- 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++-- | Rank-0 index+--+data Z = Z+  deriving (Show, Eq, Generic, Elt)++-- | 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 (Eq, Generic)  -- Not deriving Elt or Show++-- 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+  showsPrec p (sh :. sz) =+    showsPrec p sh . showString " :. " . showsPrec p 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 (Show, Eq, Generic, Elt)++-- | 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 (Show, Eq, Generic)++-- | 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 (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 (Show, Eq)+++-- | Number of dimensions of a /shape/ or /index/ (>= 0)+--+rank :: forall sh. Shape sh => Int+rank = R.rank (shapeR @sh)++-- | Total number of elements in an array of the given /shape/+--+size :: forall sh. Shape sh => sh -> Int+size = R.size (shapeR @sh) . fromElt++-- | The empty /shape/+--+empty :: forall sh. Shape sh => sh+empty = toElt $ R.empty (shapeR @sh)++-- | Yield the intersection of two shapes+intersect :: forall sh. Shape sh => sh -> sh -> sh+intersect x y = toElt $ R.intersect (shapeR @sh) (fromElt x) (fromElt y)++-- | Yield the union of two shapes+--+union :: forall sh. Shape sh => sh -> sh -> sh+union x y = toElt $ R.union (shapeR @sh) (fromElt x) (fromElt y)++-- | 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 :: forall sh. Shape sh+        => sh       -- ^ Total shape (extent) of the array+        -> sh       -- ^ The argument index+        -> Int      -- ^ Corresponding linear index+toIndex sh ix = R.toIndex (shapeR @sh) (fromElt sh) (fromElt ix)++-- | Inverse of 'toIndex'.+--+fromIndex :: forall sh. Shape sh+          => sh     -- ^ Total shape (extent) of the array+          -> Int    -- ^ The argument index+          -> sh     -- ^ Corresponding multi-dimensional index+fromIndex sh = toElt . R.fromIndex (shapeR @sh) (fromElt sh)++-- | Iterate through all of the indices of a shape, applying the given+-- function at each index. The index space is traversed in row-major order.+--+iter :: forall sh e. Shape sh+     => sh              -- ^ The total shape (extent) of the index space+     -> (sh -> e)       -- ^ Function to apply at each index+     -> (e -> e -> e)   -- ^ Function to combine results+     -> e               -- ^ Value to return in case of an empty iteration space+     -> e+iter sh f = R.iter (shapeR @sh) (fromElt sh) (f . toElt)++-- | Variant of 'iter' without an initial value+--+iter1 :: forall sh e. Shape sh+      => sh+      -> (sh -> e)+      -> (e -> e -> e)+      -> e+iter1 sh f = R.iter1 (shapeR @sh) (fromElt sh) (f . toElt)++-- | Convert a minpoint-maxpoint index into a zero-indexed shape+--+rangeToShape :: forall sh. Shape sh => (sh, sh) -> sh+rangeToShape (u, v) = toElt $ R.rangeToShape (shapeR @sh) (fromElt u, fromElt v)++-- | Convert a shape into a minpoint-maxpoint index+--+shapeToRange :: forall sh. Shape sh => sh -> (sh, sh)+shapeToRange ix =+  let (u, v) = R.shapeToRange (shapeR @sh) (fromElt ix)+   in (toElt u, toElt v)++-- | Convert a shape to a list of dimensions+--+shapeToList :: forall sh. Shape sh => sh -> [Int]+shapeToList = R.shapeToList (shapeR @sh) . fromElt++-- | Convert a list of dimensions into a shape. If the list does not+-- contain exactly the number of elements as specified by the type of the+-- shape: error.+--+listToShape :: forall sh. Shape sh => [Int] -> sh+listToShape = toElt . R.listToShape (shapeR @sh)++-- | Attempt to convert a list of dimensions into a shape+--+listToShape' :: forall sh. Shape sh => [Int] -> Maybe sh+listToShape' = fmap toElt . R.listToShape' (shapeR @sh)++-- | 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)+    => R.SliceIndex slix (EltR sl) co (EltR dim)+    -> dim+    -> sl+sliceShape slix = toElt . R.sliceShape slix . fromElt++-- | Enumerate all slices within a given bound. The innermost dimension+-- changes most rapidly.+--+-- Example:+--+-- > let slix = sliceIndex @(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)+           => R.SliceIndex (EltR slix) sl co (EltR dim)+           -> dim    -- Bounds+           -> [slix] -- All slices within bounds.+enumSlices slix = map toElt . R.enumSlices slix . fromElt++-- | Shapes and indices of multi-dimensional arrays+--+class (Elt sh, Elt (Any sh), FullShape sh ~ sh, CoSliceShape sh ~ sh, SliceShape sh ~ Z)+       => Shape sh where++  -- | Reified type witness for shapes+  shapeR :: R.ShapeR (EltR sh)++  -- | The slice index for slice specifier 'Any sh'+  sliceAnyIndex  :: R.SliceIndex (EltR (Any sh)) (EltR sh) () (EltR sh)++  -- | The slice index for specifying a slice with only the Z component projected+  sliceNoneIndex :: R.SliceIndex (EltR sh) () (EltR sh) (EltR 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 :: Type    -- the projected slice+  type CoSliceShape sl :: Type    -- the complement of the slice+  type FullShape    sl :: Type    -- the combined dimension+  sliceIndex :: R.SliceIndex (EltR sl)+                             (EltR (SliceShape   sl))+                             (EltR (CoSliceShape sl))+                             (EltR (FullShape    sl))++-- | 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 :: Type   -- the slice+  slicesIndex :: slix ~ DivisionSlice sl+              => R.SliceIndex (EltR slix)+                              (EltR (SliceShape   slix))+                              (EltR (CoSliceShape slix))+                              (EltR (FullShape    slix))++instance (Elt t, Elt h) => Elt (t :. h) where+  type EltR (t :. h) = (EltR t, EltR h)+  eltR           = TupRpair (eltR @t) (eltR @h)+  tagsR          = [TagRpair t h | t <- tagsR @t, h <- tagsR @h]+  fromElt (t:.h) = (fromElt t, fromElt h)+  toElt (t, h)   = toElt t :. toElt h++instance Elt (Any Z)+instance Shape sh => Elt (Any (sh :. Int)) where+  type EltR (Any (sh :. Int)) = (EltR (Any sh), ())+  eltR      = TupRpair (eltR @(Any sh)) TupRunit+  tagsR     = [TagRpair t TagRunit | t <- tagsR @(Any sh)]+  fromElt _ = (fromElt (Any :: Any sh), ())+  toElt _   = Any++instance Shape Z where+  shapeR         = R.ShapeRz+  sliceAnyIndex  = R.SliceNil+  sliceNoneIndex = R.SliceNil++instance Shape sh => Shape (sh:.Int) where+  shapeR         = R.ShapeRsnoc (shapeR @sh)+  sliceAnyIndex  = R.SliceAll   (sliceAnyIndex  @sh)+  sliceNoneIndex = R.SliceFixed (sliceNoneIndex @sh)++instance Slice Z where+  type SliceShape   Z = Z+  type CoSliceShape Z = Z+  type FullShape    Z = Z+  sliceIndex = R.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 = R.SliceAll (sliceIndex @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 = R.SliceFixed (sliceIndex @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 @sh++instance Division Z where+  type DivisionSlice Z = Z+  slicesIndex = R.SliceNil++instance Division sl => Division (sl:.All) where+  type DivisionSlice (sl:.All) = DivisionSlice sl :. All+  slicesIndex = R.SliceAll (slicesIndex @sl)++instance Division sl => Division (sl:.Split) where+  type DivisionSlice (sl:.Split) = DivisionSlice sl :. Int+  slicesIndex = R.SliceFixed (slicesIndex @sl)++instance Shape sh => Division (Any sh) where+  type DivisionSlice (Any sh) = Any sh+  slicesIndex = sliceAnyIndex @sh++instance (Shape sh, Slice sh) => Division (Divide sh) where+  type DivisionSlice (Divide sh) = sh+  slicesIndex = sliceNoneIndex @sh+
+ src/Data/Array/Accelerate/Sugar/Vec.hs view
@@ -0,0 +1,39 @@+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE MagicHash           #-}+{-# LANGUAGE ConstraintKinds     #-}+{-# LANGUAGE TypeFamilies        #-}+{-# OPTIONS_HADDOCK hide #-}+{-# OPTIONS_GHC -fno-warn-orphans #-}+-- |+-- Module      : Data.Array.Accelerate.Sugar.Vec+-- Copyright   : [2008..2020] The Accelerate Team+-- License     : BSD3+--+-- Maintainer  : Trevor L. McDonell <trevor.mcdonell@gmail.com>+-- Stability   : experimental+-- Portability : non-portable (GHC extensions)+--++module Data.Array.Accelerate.Sugar.Vec+  where++import Data.Array.Accelerate.Sugar.Elt+import Data.Array.Accelerate.Representation.Tag+import Data.Array.Accelerate.Representation.Type+import Data.Array.Accelerate.Type+import Data.Primitive.Types+import Data.Primitive.Vec++import GHC.TypeLits+import GHC.Prim+++type VecElt a = (Elt a, Prim a, IsSingle a, EltR a ~ a)++instance (KnownNat n, VecElt a) => Elt (Vec n a) where+  type EltR (Vec n a) = Vec n a+  eltR    = TupRsingle (VectorScalarType (VectorType (fromIntegral (natVal' (proxy# :: Proxy# n))) singleType))+  tagsR   = [TagRsingle (VectorScalarType (VectorType (fromIntegral (natVal' (proxy# :: Proxy# n))) singleType))]+  toElt   = id+  fromElt = id+
src/Data/Array/Accelerate/Test/NoFib.hs view
@@ -3,10 +3,10 @@ {-# OPTIONS_HADDOCK hide #-} -- | -- Module      : Data.Array.Accelerate.Test.NoFib--- Copyright   : [2009..2017] Trevor L. McDonell+-- Copyright   : [2009..2020] The Accelerate Team -- License     : BSD3 ----- Maintainer  : Trevor L. McDonell <tmcdonell@cse.unsw.edu.au>+-- Maintainer  : Trevor L. McDonell <trevor.mcdonell@gmail.com> -- Stability   : experimental -- Portability : non-portable (GHC extensions) --
src/Data/Array/Accelerate/Test/NoFib/Base.hs view
@@ -3,10 +3,10 @@ {-# LANGUAGE TypeOperators       #-} -- | -- Module      : Data.Array.Accelerate.Test.NoFib.Base--- Copyright   : [2009..2017] Trevor L. McDonell+-- Copyright   : [2009..2020] The Accelerate Team -- License     : BSD3 ----- Maintainer  : Trevor L. McDonell <tmcdonell@cse.unsw.edu.au>+-- Maintainer  : Trevor L. McDonell <trevor.mcdonell@gmail.com> -- Stability   : experimental -- Portability : non-portable (GHC extensions) --@@ -14,12 +14,16 @@ module Data.Array.Accelerate.Test.NoFib.Base   where -import Data.Array.Accelerate.Array.Sugar                            ( Arrays, Array, Shape, Elt, DIM0, DIM1, DIM2, DIM3, Z(..), (:.)(..), fromList, size )-import Data.Array.Accelerate.Smart                                  ( Acc )-import Data.Array.Accelerate.Trafo.Sharing                          ( Afunction, AfunctionR )+import Data.Array.Accelerate.Smart+import Data.Array.Accelerate.Sugar.Array+import Data.Array.Accelerate.Sugar.Elt+import Data.Array.Accelerate.Sugar.Shape+import Data.Array.Accelerate.Trafo.Sharing import Data.Array.Accelerate.Type+import Data.Primitive.Vec  import Control.Monad+import Data.Primitive.Types  import Hedgehog import qualified Hedgehog.Gen                                       as Gen@@ -90,24 +94,40 @@ f64 :: Gen Double f64 = Gen.double (Range.linearFracFrom 0 (-log_flt_max) log_flt_max) +v2 :: Prim a => Gen a -> Gen (Vec2 a)+v2 a = Vec2 <$> a <*> a++v3 :: Prim a => Gen a -> Gen (Vec3 a)+v3 a = Vec3 <$> a <*> a <*> a++v4 :: Prim a => Gen a -> Gen (Vec4 a)+v4 a = Vec4 <$> a <*> a <*> a <*> a++v8 :: Prim a => Gen a -> Gen (Vec8 a)+v8 a = Vec8 <$> a <*> a <*> a <*> a <*> a <*> a <*> a <*> a++v16 :: Prim a => Gen a -> Gen (Vec16 a)+v16 a = Vec16 <$> a <*> a <*> a <*> a <*> a <*> a <*> a <*> a+              <*> a <*> a <*> a <*> a <*> a <*> a <*> a <*> a+ log_flt_max :: RealFloat a => a log_flt_max = log flt_max  flt_max :: RealFloat a => a flt_max = x   where-    n   = floatDigits x-    b   = floatRadix x-    inf = let (u,v) = floatRange x in max u v   -- bug in half <= 0.2.2.3-    x   = encodeFloat (b^n - 1) (inf - n)+    n     = floatDigits x+    b     = floatRadix x+    (_,u) = floatRange x+    x     = encodeFloat (b^n - 1) (u - n)  flt_min :: RealFloat a => a flt_min = x   where-    n   = floatDigits x-    b   = floatRadix x-    sup = let (u,v) = floatRange x in min u v   -- bug in half <= 0.2.2.3-    x   = encodeFloat (b^n - 1) (sup - n - 1)+    n     = floatDigits x+    b     = floatRadix x+    (l,_) = floatRange x+    x     = encodeFloat (b^n - 1) (l - n - 1)  except :: Gen e -> (e -> Bool) -> Gen e except gen f  = do
src/Data/Array/Accelerate/Test/NoFib/Config.hs view
@@ -1,12 +1,13 @@-{-# LANGUAGE DeriveDataTypeable #-}-{-# LANGUAGE TemplateHaskell    #-}-{-# LANGUAGE TypeOperators      #-}+{-# LANGUAGE AllowAmbiguousTypes #-}+{-# LANGUAGE DeriveDataTypeable  #-}+{-# LANGUAGE TemplateHaskell     #-}+{-# LANGUAGE TypeOperators       #-} -- | -- Module      : Data.Array.Accelerate.Test.NoFib.Config--- Copyright   : [2009..2017] Trevor L. McDonell+-- Copyright   : [2009..2020] The Accelerate Team -- License     : BSD3 ----- Maintainer  : Trevor L. McDonell <tmcdonell@cse.unsw.edu.au>+-- Maintainer  : Trevor L. McDonell <trevor.mcdonell@gmail.com> -- Stability   : experimental -- Portability : non-portable (GHC extensions) --@@ -134,38 +135,38 @@   class IsOption a => TestConfig a where-  at :: Proxy a -> TestTree -> TestTree+  at :: TestTree -> TestTree  instance TestConfig TestHalf where-  at _ t = askOption $ \(TestHalf v)   -> if v then t else testGroup "Half" []+  at t = askOption $ \(TestHalf v)   -> if v then t else testGroup "Half" []  instance TestConfig TestFloat where-  at _ t = askOption $ \(TestFloat v)  -> if v then t else testGroup "Float" []+  at t = askOption $ \(TestFloat v)  -> if v then t else testGroup "Float" []  instance TestConfig TestDouble where-  at _ t = askOption $ \(TestDouble v) -> if v then t else testGroup "Double" []+  at t = askOption $ \(TestDouble v) -> if v then t else testGroup "Double" []  instance TestConfig TestInt8 where-  at _ t = askOption $ \(TestInt8 v)   -> if v then t else testGroup "Int8" []+  at t = askOption $ \(TestInt8 v)   -> if v then t else testGroup "Int8" []  instance TestConfig TestInt16 where-  at _ t = askOption $ \(TestInt16 v)  -> if v then t else testGroup "Int16" []+  at t = askOption $ \(TestInt16 v)  -> if v then t else testGroup "Int16" []  instance TestConfig TestInt32 where-  at _ t = askOption $ \(TestInt32 v)  -> if v then t else testGroup "Int32" []+  at t = askOption $ \(TestInt32 v)  -> if v then t else testGroup "Int32" []  instance TestConfig TestInt64 where-  at _ t = askOption $ \(TestInt64 v)  -> if v then t else testGroup "Int64" []+  at t = askOption $ \(TestInt64 v)  -> if v then t else testGroup "Int64" []  instance TestConfig TestWord8 where-  at _ t = askOption $ \(TestWord8 v)  -> if v then t else testGroup "Word8" []+  at t = askOption $ \(TestWord8 v)  -> if v then t else testGroup "Word8" []  instance TestConfig TestWord16 where-  at _ t = askOption $ \(TestWord16 v) -> if v then t else testGroup "Word16" []+  at t = askOption $ \(TestWord16 v) -> if v then t else testGroup "Word16" []  instance TestConfig TestWord32 where-  at _ t = askOption $ \(TestWord32 v) -> if v then t else testGroup "Word32" []+  at t = askOption $ \(TestWord32 v) -> if v then t else testGroup "Word32" []  instance TestConfig TestWord64 where-  at _ t = askOption $ \(TestWord64 v) -> if v then t else testGroup "Word64" []+  at t = askOption $ \(TestWord64 v) -> if v then t else testGroup "Word64" [] 
src/Data/Array/Accelerate/Test/NoFib/Imaginary.hs view
@@ -1,10 +1,10 @@ {-# LANGUAGE RankNTypes #-} -- | -- Module      : Data.Array.Accelerate.Test.NoFib.Imaginary--- Copyright   : [2009..2017] Trevor L. McDonell+-- Copyright   : [2009..2020] The Accelerate Team -- License     : BSD3 ----- Maintainer  : Trevor L. McDonell <tmcdonell@cse.unsw.edu.au>+-- Maintainer  : Trevor L. McDonell <trevor.mcdonell@gmail.com> -- Stability   : experimental -- Portability : non-portable (GHC extensions) --
src/Data/Array/Accelerate/Test/NoFib/Imaginary/DotP.hs view
@@ -3,12 +3,13 @@ {-# LANGUAGE FlexibleContexts    #-} {-# LANGUAGE RankNTypes          #-} {-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TypeApplications    #-} -- | -- Module      : Data.Array.Accelerate.Test.NoFib.Imaginary.DotP--- Copyright   : [2009..2017] Trevor L. McDonell+-- Copyright   : [2009..2020] The Accelerate Team -- License     : BSD3 ----- Maintainer  : Trevor L. McDonell <tmcdonell@cse.unsw.edu.au>+-- Maintainer  : Trevor L. McDonell <trevor.mcdonell@gmail.com> -- Stability   : experimental -- Portability : non-portable (GHC extensions) --@@ -19,12 +20,11 @@  ) where -import Data.Proxy-import Data.Typeable import Prelude                                                  as P  import Data.Array.Accelerate                                    as A-import Data.Array.Accelerate.Array.Sugar                        as S+import Data.Array.Accelerate.Sugar.Array                        as S+import Data.Array.Accelerate.Sugar.Elt                          as S import Data.Array.Accelerate.Test.NoFib.Base import Data.Array.Accelerate.Test.NoFib.Config import Data.Array.Accelerate.Test.Similar@@ -40,28 +40,28 @@ test_dotp :: RunN -> TestTree test_dotp runN =   testGroup "dot product"-    [ at (Proxy::Proxy TestInt8)   $ testElt i8-    , at (Proxy::Proxy TestInt16)  $ testElt i16-    , at (Proxy::Proxy TestInt32)  $ testElt i32-    , at (Proxy::Proxy TestInt64)  $ testElt i64-    , at (Proxy::Proxy TestWord8)  $ testElt w8-    , at (Proxy::Proxy TestWord16) $ testElt w16-    , at (Proxy::Proxy TestWord32) $ testElt w32-    , at (Proxy::Proxy TestWord64) $ testElt w64-    , at (Proxy::Proxy TestHalf)   $ testElt f16-    , at (Proxy::Proxy TestFloat)  $ testElt f32-    , at (Proxy::Proxy TestDouble) $ testElt f64+    [ at @TestInt8   $ testElt i8+    , at @TestInt16  $ testElt i16+    , at @TestInt32  $ testElt i32+    , at @TestInt64  $ testElt i64+    , at @TestWord8  $ testElt w8+    , at @TestWord16 $ testElt w16+    , at @TestWord32 $ testElt w32+    , at @TestWord64 $ testElt w64+    , at @TestHalf   $ testElt f16+    , at @TestFloat  $ testElt f32+    , at @TestDouble $ testElt f64     ]   where-    testElt :: forall a. (P.Num a, P.Ord a , A.Num a, A.Ord a , Similar a)+    testElt :: forall a. (P.Num a, P.Ord a , A.Num a, A.Ord a , Similar a, Show a)         => Gen a         -> TestTree     testElt e =-      testProperty (show (typeOf (undefined :: a))) $ test_dotp' runN e+      testProperty (show (eltR @a)) $ test_dotp' runN e   test_dotp'-    :: (P.Num e, A.Num e, Similar e)+    :: (P.Num e, A.Num e, Similar e, Show e)     => RunN     -> Gen e     -> Property@@ -77,7 +77,7 @@   = A.fold (+) 0   $ A.zipWith (*) xs ys -dotpRef :: P.Num e => Vector e -> Vector e -> e+dotpRef :: (P.Num e, Elt e) => Vector e -> Vector e -> e dotpRef xs ys   = P.sum ( P.zipWith (*) (toList xs) (toList ys) ) 
src/Data/Array/Accelerate/Test/NoFib/Imaginary/SASUM.hs view
@@ -3,12 +3,13 @@ {-# LANGUAGE FlexibleContexts    #-} {-# LANGUAGE RankNTypes          #-} {-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TypeApplications    #-} -- | -- Module      : Data.Array.Accelerate.Test.NoFib.Imaginary.SASUM--- Copyright   : [2009..2017] Trevor L. McDonell+-- Copyright   : [2009..2020] The Accelerate Team -- License     : BSD3 ----- Maintainer  : Trevor L. McDonell <tmcdonell@cse.unsw.edu.au>+-- Maintainer  : Trevor L. McDonell <trevor.mcdonell@gmail.com> -- Stability   : experimental -- Portability : non-portable (GHC extensions) --@@ -19,12 +20,11 @@  ) where -import Data.Proxy-import Data.Typeable import Prelude                                                  as P  import Data.Array.Accelerate                                    as A-import Data.Array.Accelerate.Array.Sugar                        as S+import Data.Array.Accelerate.Sugar.Array                        as S+import Data.Array.Accelerate.Sugar.Elt                          as S import Data.Array.Accelerate.Test.NoFib.Base import Data.Array.Accelerate.Test.NoFib.Config import Data.Array.Accelerate.Test.Similar@@ -40,28 +40,28 @@ test_sasum :: RunN -> TestTree test_sasum runN =   testGroup "sasum"-    [ at (Proxy::Proxy TestInt8)   $ testElt i8-    , at (Proxy::Proxy TestInt16)  $ testElt i16-    , at (Proxy::Proxy TestInt32)  $ testElt i32-    , at (Proxy::Proxy TestInt64)  $ testElt i64-    , at (Proxy::Proxy TestWord8)  $ testElt w8-    , at (Proxy::Proxy TestWord16) $ testElt w16-    , at (Proxy::Proxy TestWord32) $ testElt w32-    , at (Proxy::Proxy TestWord64) $ testElt w64-    , at (Proxy::Proxy TestHalf)   $ testElt f16-    , at (Proxy::Proxy TestFloat)  $ testElt f32-    , at (Proxy::Proxy TestDouble) $ testElt f64+    [ at @TestInt8   $ testElt i8+    , at @TestInt16  $ testElt i16+    , at @TestInt32  $ testElt i32+    , at @TestInt64  $ testElt i64+    , at @TestWord8  $ testElt w8+    , at @TestWord16 $ testElt w16+    , at @TestWord32 $ testElt w32+    , at @TestWord64 $ testElt w64+    , at @TestHalf   $ testElt f16+    , at @TestFloat  $ testElt f32+    , at @TestDouble $ testElt f64     ]   where-    testElt :: forall a. (P.Num a, P.Ord a , A.Num a, A.Ord a , Similar a)+    testElt :: forall a. (P.Num a, P.Eq a, A.Num a, A.Eq a, Similar a, Show a)         => Gen a         -> TestTree     testElt e =-      testProperty (show (typeOf (undefined :: a))) $ test_sasum' runN e+      testProperty (show (eltR @a)) $ test_sasum' runN e   test_sasum'-    :: (P.Num e, A.Num e, Similar e)+    :: (P.Num e, A.Num e, Similar e, Show e)     => RunN     -> Gen e     -> Property@@ -74,6 +74,6 @@ sasum :: A.Num e => Acc (Vector e) -> Acc (Scalar e) sasum = A.fold (+) 0 . A.map abs -sasumRef :: P.Num e => Vector e -> e+sasumRef :: (P.Num e, Elt e) => Vector e -> e sasumRef xs = P.sum [ abs x | x <- toList xs ] 
src/Data/Array/Accelerate/Test/NoFib/Imaginary/SAXPY.hs view
@@ -3,12 +3,13 @@ {-# LANGUAGE FlexibleContexts    #-} {-# LANGUAGE RankNTypes          #-} {-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TypeApplications    #-} -- | -- Module      : Data.Array.Accelerate.Test.NoFib.Imaginary.SAXPY--- Copyright   : [2009..2017] Trevor L. McDonell+-- Copyright   : [2009..2020] The Accelerate Team -- License     : BSD3 ----- Maintainer  : Trevor L. McDonell <tmcdonell@cse.unsw.edu.au>+-- Maintainer  : Trevor L. McDonell <trevor.mcdonell@gmail.com> -- Stability   : experimental -- Portability : non-portable (GHC extensions) --@@ -19,12 +20,12 @@  ) where -import Data.Proxy-import Data.Typeable import Prelude                                                  as P  import Data.Array.Accelerate                                    as A-import Data.Array.Accelerate.Array.Sugar                        as S+import Data.Array.Accelerate.Sugar.Array                        as S+import Data.Array.Accelerate.Sugar.Elt                          as S+import Data.Array.Accelerate.Sugar.Shape                        as S import Data.Array.Accelerate.Test.NoFib.Base import Data.Array.Accelerate.Test.NoFib.Config import Data.Array.Accelerate.Test.Similar@@ -40,28 +41,28 @@ test_saxpy :: RunN -> TestTree test_saxpy runN =   testGroup "saxpy"-    [ at (Proxy::Proxy TestInt8)   $ testElt i8-    , at (Proxy::Proxy TestInt16)  $ testElt i16-    , at (Proxy::Proxy TestInt32)  $ testElt i32-    , at (Proxy::Proxy TestInt64)  $ testElt i64-    , at (Proxy::Proxy TestWord8)  $ testElt w8-    , at (Proxy::Proxy TestWord16) $ testElt w16-    , at (Proxy::Proxy TestWord32) $ testElt w32-    , at (Proxy::Proxy TestWord64) $ testElt w64-    , at (Proxy::Proxy TestHalf)   $ testElt f16-    , at (Proxy::Proxy TestFloat)  $ testElt f32-    , at (Proxy::Proxy TestDouble) $ testElt f64+    [ at @TestInt8   $ testElt i8+    , at @TestInt16  $ testElt i16+    , at @TestInt32  $ testElt i32+    , at @TestInt64  $ testElt i64+    , at @TestWord8  $ testElt w8+    , at @TestWord16 $ testElt w16+    , at @TestWord32 $ testElt w32+    , at @TestWord64 $ testElt w64+    , at @TestHalf   $ testElt f16+    , at @TestFloat  $ testElt f32+    , at @TestDouble $ testElt f64     ]   where-    testElt :: forall a. (P.Num a, P.Ord a , A.Num a, A.Ord a , Similar a)+    testElt :: forall a. (P.Num a, A.Num a, Similar a, Show a)         => Gen a         -> TestTree     testElt e =-      testProperty (show (typeOf (undefined :: a))) $ test_saxpy' runN e+      testProperty (show (eltR @a)) $ test_saxpy' runN e   test_saxpy'-    :: (P.Num e, A.Num e, Similar e)+    :: (P.Num e, A.Num e, Similar e, Show e)     => RunN     -> Gen e     -> Property
src/Data/Array/Accelerate/Test/NoFib/Issues.hs view
@@ -1,10 +1,10 @@ {-# LANGUAGE RankNTypes #-} -- | -- Module      : Data.Array.Accelerate.Test.NoFib.Issues--- Copyright   : [2009..2017] Trevor L. McDonell+-- Copyright   : [2009..2020] The Accelerate Team -- License     : BSD3 ----- Maintainer  : Trevor L. McDonell <tmcdonell@cse.unsw.edu.au>+-- Maintainer  : Trevor L. McDonell <trevor.mcdonell@gmail.com> -- Stability   : experimental -- Portability : non-portable (GHC extensions) --@@ -30,8 +30,12 @@   module Data.Array.Accelerate.Test.NoFib.Issues.Issue287,   module Data.Array.Accelerate.Test.NoFib.Issues.Issue288,   module Data.Array.Accelerate.Test.NoFib.Issues.Issue362,+  module Data.Array.Accelerate.Test.NoFib.Issues.Issue364,   module Data.Array.Accelerate.Test.NoFib.Issues.Issue407,   module Data.Array.Accelerate.Test.NoFib.Issues.Issue409,+  module Data.Array.Accelerate.Test.NoFib.Issues.Issue436,+  module Data.Array.Accelerate.Test.NoFib.Issues.Issue437,+  module Data.Array.Accelerate.Test.NoFib.Issues.Issue439,  ) where @@ -55,8 +59,12 @@ import Data.Array.Accelerate.Test.NoFib.Issues.Issue287 import Data.Array.Accelerate.Test.NoFib.Issues.Issue288 import Data.Array.Accelerate.Test.NoFib.Issues.Issue362+import Data.Array.Accelerate.Test.NoFib.Issues.Issue364 import Data.Array.Accelerate.Test.NoFib.Issues.Issue407 import Data.Array.Accelerate.Test.NoFib.Issues.Issue409+import Data.Array.Accelerate.Test.NoFib.Issues.Issue436+import Data.Array.Accelerate.Test.NoFib.Issues.Issue437+import Data.Array.Accelerate.Test.NoFib.Issues.Issue439   test_issues :: RunN -> TestTree@@ -79,7 +87,11 @@     , test_issue287 runN     , test_issue288 runN     , test_issue362 runN+    , test_issue364 runN     , test_issue407 runN     , test_issue409 runN+    , test_issue436 runN+    , test_issue437 runN+    , test_issue439 runN     ] 
src/Data/Array/Accelerate/Test/NoFib/Issues/Issue102.hs view
@@ -2,10 +2,10 @@ {-# LANGUAGE TypeOperators #-} -- | -- Module      : Data.Array.Accelerate.Test.NoFib.Issues.Issue102--- Copyright   : [2009..2017] Trevor L. McDonell+-- Copyright   : [2009..2020] The Accelerate Team -- License     : BSD3 ----- Maintainer  : Trevor L. McDonell <tmcdonell@cse.unsw.edu.au>+-- Maintainer  : Trevor L. McDonell <trevor.mcdonell@gmail.com> -- Stability   : experimental -- Portability : non-portable (GHC extensions) --
src/Data/Array/Accelerate/Test/NoFib/Issues/Issue114.hs view
@@ -1,10 +1,10 @@ {-# LANGUAGE RankNTypes #-} -- | -- Module      : Data.Array.Accelerate.Test.NoFib.Issues.Issue114--- Copyright   : [2009..2017] Trevor L. McDonell+-- Copyright   : [2009..2020] The Accelerate Team -- License     : BSD3 ----- Maintainer  : Trevor L. McDonell <tmcdonell@cse.unsw.edu.au>+-- Maintainer  : Trevor L. McDonell <trevor.mcdonell@gmail.com> -- Stability   : experimental -- Portability : non-portable (GHC extensions) --
src/Data/Array/Accelerate/Test/NoFib/Issues/Issue119.hs view
@@ -1,10 +1,10 @@ {-# LANGUAGE RankNTypes #-} -- | -- Module      : Data.Array.Accelerate.Test.NoFib.Issues.Issue119--- Copyright   : [2009..2017] Trevor L. McDonell+-- Copyright   : [2009..2020] The Accelerate Team -- License     : BSD3 ----- Maintainer  : Trevor L. McDonell <tmcdonell@cse.unsw.edu.au>+-- Maintainer  : Trevor L. McDonell <trevor.mcdonell@gmail.com> -- Stability   : experimental -- Portability : non-portable (GHC extensions) --
src/Data/Array/Accelerate/Test/NoFib/Issues/Issue123.hs view
@@ -1,10 +1,10 @@ {-# LANGUAGE RankNTypes #-} -- | -- Module      : Data.Array.Accelerate.Test.NoFib.Issues.Issue123--- Copyright   : [2009..2017] Trevor L. McDonell+-- Copyright   : [2009..2020] The Accelerate Team -- License     : BSD3 ----- Maintainer  : Trevor L. McDonell <tmcdonell@cse.unsw.edu.au>+-- Maintainer  : Trevor L. McDonell <trevor.mcdonell@gmail.com> -- Stability   : experimental -- Portability : non-portable (GHC extensions) --
src/Data/Array/Accelerate/Test/NoFib/Issues/Issue137.hs view
@@ -3,10 +3,10 @@ {-# LANGUAGE TypeOperators       #-} -- | -- Module      : Data.Array.Accelerate.Test.NoFib.Issues.Issue137--- Copyright   : [2009..2017] Trevor L. McDonell+-- Copyright   : [2009..2020] The Accelerate Team -- License     : BSD3 ----- Maintainer  : Trevor L. McDonell <tmcdonell@cse.unsw.edu.au>+-- Maintainer  : Trevor L. McDonell <trevor.mcdonell@gmail.com> -- Stability   : experimental -- Portability : non-portable (GHC extensions) --@@ -25,9 +25,7 @@ import Test.Tasty import Test.Tasty.HUnit -import Prelude                                                      as P - test_issue137 :: RunN -> TestTree test_issue137 runN =   testCase "137"  $ ref1 @=? runN test1@@ -40,8 +38,8 @@ test1 =   let       sz          = 3000 :: Int-      interm_arrA = use $ A.fromList (Z :. sz) [ P.fromIntegral $ 8 - (a `mod` 17) | a <- [1..sz]]-      msA         = use $ A.fromList (Z :. sz) [ P.fromIntegral $ (a `div` 8) | a <- [1..sz]]+      interm_arrA = use $ A.fromList (Z :. sz) [ 8 - (a `mod` 17) | a <- [1..sz]]+      msA         = use $ A.fromList (Z :. sz) [ (a `div` 8) | a <- [1..sz]]       inf         = 10000 :: Exp Int       infsA       = A.generate (index1 (384 :: Exp Int)) (\_ -> lift (inf,inf))       inpA        = A.map (\v -> lift (abs v,inf) :: Exp (Int,Int)) interm_arrA@@ -53,6 +51,6 @@                             , lift (b1, A.min b2 a1)                             ))             infsA-            (\ix -> index1 (msA A.! ix))+            (\ix -> Just_ (index1 (msA A.! ix)))             inpA 
src/Data/Array/Accelerate/Test/NoFib/Issues/Issue168.hs view
@@ -1,10 +1,10 @@ {-# LANGUAGE RankNTypes #-} -- | -- Module      : Data.Array.Accelerate.Test.NoFib.Issues.Issue168--- Copyright   : [2009..2017] Trevor L. McDonell+-- Copyright   : [2009..2020] The Accelerate Team -- License     : BSD3 ----- Maintainer  : Trevor L. McDonell <tmcdonell@cse.unsw.edu.au>+-- Maintainer  : Trevor L. McDonell <trevor.mcdonell@gmail.com> -- Stability   : experimental -- Portability : non-portable (GHC extensions) --
src/Data/Array/Accelerate/Test/NoFib/Issues/Issue184.hs view
@@ -2,10 +2,10 @@ {-# LANGUAGE RankNTypes        #-} -- | -- Module      : Data.Array.Accelerate.Test.NoFib.Issues.Issue184--- Copyright   : [2009..2017] Trevor L. McDonell+-- Copyright   : [2009..2020] The Accelerate Team -- License     : BSD3 ----- Maintainer  : Trevor L. McDonell <tmcdonell@cse.unsw.edu.au>+-- Maintainer  : Trevor L. McDonell <trevor.mcdonell@gmail.com> -- Stability   : experimental -- Portability : non-portable (GHC extensions) --
src/Data/Array/Accelerate/Test/NoFib/Issues/Issue185.hs view
@@ -6,10 +6,10 @@ {-# LANGUAGE TypeOperators       #-} -- | -- Module      : Data.Array.Accelerate.Test.NoFib.Issues.Issue185--- Copyright   : [2009..2017] Trevor L. McDonell+-- Copyright   : [2009..2020] The Accelerate Team -- License     : BSD3 ----- Maintainer  : Trevor L. McDonell <tmcdonell@cse.unsw.edu.au>+-- Maintainer  : Trevor L. McDonell <trevor.mcdonell@gmail.com> -- Stability   : experimental -- Portability : non-portable (GHC extensions) --@@ -144,6 +144,6 @@     -> Acc (Vector e') scatterIf to maskV p def input = permute const def pf input'   where-    pf ix       = p (maskV ! ix) ? ( index1 (to ! ix), ignore )+    pf ix       = p (maskV ! ix) ? ( Just_ (index1 (to ! ix)), Nothing_ )     input'      = backpermute (shape to `intersect` shape input) id input 
src/Data/Array/Accelerate/Test/NoFib/Issues/Issue187.hs view
@@ -2,10 +2,10 @@ {-# LANGUAGE RankNTypes        #-} -- | -- Module      : Data.Array.Accelerate.Test.NoFib.Issues.Issue187--- Copyright   : [2009..2017] Trevor L. McDonell+-- Copyright   : [2009..2020] The Accelerate Team -- License     : BSD3 ----- Maintainer  : Trevor L. McDonell <tmcdonell@cse.unsw.edu.au>+-- Maintainer  : Trevor L. McDonell <trevor.mcdonell@gmail.com> -- Stability   : experimental -- Portability : non-portable (GHC extensions) --
src/Data/Array/Accelerate/Test/NoFib/Issues/Issue228.hs view
@@ -3,10 +3,10 @@ {-# LANGUAGE RankNTypes       #-} -- | -- Module      : Data.Array.Accelerate.Test.NoFib.Issues.Issue228--- Copyright   : [2009..2017] Trevor L. McDonell+-- Copyright   : [2009..2020] The Accelerate Team -- License     : BSD3 ----- Maintainer  : Trevor L. McDonell <tmcdonell@cse.unsw.edu.au>+-- Maintainer  : Trevor L. McDonell <trevor.mcdonell@gmail.com> -- Stability   : experimental -- Portability : non-portable (GHC extensions) --@@ -61,8 +61,8 @@ mergeExp :: Exp (Int,Int) -> Exp (Int,Int) -> Exp (Int,Int) mergeExp e1 e2 =   let-    v1 = unlift e1 :: (Exp Int,Exp Int)-    v2 = unlift e2 :: (Exp Int,Exp Int)+    t1 = unlift e1 :: (Exp Int,Exp Int)+    t2 = unlift e2 :: (Exp Int,Exp Int)   in-  lift $ merge v1 v2+  lift $ merge t1 t2 
src/Data/Array/Accelerate/Test/NoFib/Issues/Issue255.hs view
@@ -5,10 +5,10 @@ {-# LANGUAGE ViewPatterns        #-} -- | -- Module      : Data.Array.Accelerate.Test.NoFib.Issues.Issue255--- Copyright   : [2009..2017] Trevor L. McDonell+-- Copyright   : [2009..2020] The Accelerate Team -- License     : BSD3 ----- Maintainer  : Trevor L. McDonell <tmcdonell@cse.unsw.edu.au>+-- Maintainer  : Trevor L. McDonell <trevor.mcdonell@gmail.com> -- Stability   : experimental -- Portability : non-portable (GHC extensions) --@@ -28,7 +28,7 @@ import Test.Tasty import Test.Tasty.HUnit -import Data.List                                                    as P+import Data.List                                                    as P ( mapAccumL ) import Prelude                                                      as P  
src/Data/Array/Accelerate/Test/NoFib/Issues/Issue264.hs view
@@ -3,13 +3,14 @@ {-# LANGUAGE FlexibleContexts    #-} {-# LANGUAGE RankNTypes          #-} {-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TypeApplications    #-} {-# LANGUAGE TypeOperators       #-} -- | -- Module      : Data.Array.Accelerate.Test.NoFib.Issues.Issue264--- Copyright   : [2009..2017] Trevor L. McDonell+-- Copyright   : [2009..2020] The Accelerate Team -- License     : BSD3 ----- Maintainer  : Trevor L. McDonell <tmcdonell@cse.unsw.edu.au>+-- Maintainer  : Trevor L. McDonell <trevor.mcdonell@gmail.com> -- Stability   : experimental -- Portability : non-portable (GHC extensions) --@@ -22,12 +23,12 @@  ) where -import Data.Proxy-import Data.Typeable import Prelude                                                      as P  import Data.Array.Accelerate                                        as A-import Data.Array.Accelerate.Array.Sugar                            as S+import Data.Array.Accelerate.Sugar.Array                            as S+import Data.Array.Accelerate.Sugar.Elt                              as S+import Data.Array.Accelerate.Sugar.Shape                            as S import Data.Array.Accelerate.Test.NoFib.Base import Data.Array.Accelerate.Test.NoFib.Config import Data.Array.Accelerate.Test.Similar@@ -43,24 +44,24 @@ test_issue264 runN =   testGroup "264"     [ testBool-    , at (Proxy::Proxy TestInt8)   $ testElt i8-    , at (Proxy::Proxy TestInt16)  $ testElt i16-    , at (Proxy::Proxy TestInt32)  $ testElt i32-    , at (Proxy::Proxy TestInt64)  $ testElt i64-    , at (Proxy::Proxy TestWord8)  $ testElt w8-    , at (Proxy::Proxy TestWord16) $ testElt w16-    , at (Proxy::Proxy TestWord32) $ testElt w32-    , at (Proxy::Proxy TestWord64) $ testElt w64-    , at (Proxy::Proxy TestFloat)  $ testElt f32-    , at (Proxy::Proxy TestDouble) $ testElt f64+    , at @TestInt8   $ testElt i8+    , at @TestInt16  $ testElt i16+    , at @TestInt32  $ testElt i32+    , at @TestInt64  $ testElt i64+    , at @TestWord8  $ testElt w8+    , at @TestWord16 $ testElt w16+    , at @TestWord32 $ testElt w32+    , at @TestWord64 $ testElt w64+    , at @TestFloat  $ testElt f32+    , at @TestDouble $ testElt f64     ]   where     testElt-        :: forall a. (Similar a, P.Num a, A.Num a)+        :: forall a. (Similar a, Show a, P.Num a, A.Num a)         => Gen a         -> TestTree     testElt e =-      testGroup (show (typeOf (undefined :: a)))+      testGroup (show (eltR @a))         [ testProperty "neg.neg"        $ test_neg_neg runN e         ] @@ -119,7 +120,7 @@     let !go = runN (A.zipWith (\u v -> A.not (A.not (u A.|| v)))) in go xs ys === zipWithRef (\u v -> P.not (P.not (u P.|| v))) xs ys  test_neg_neg-    :: (P.Num e, A.Num e, Similar e)+    :: (P.Num e, A.Num e, Similar e, Show e)     => RunN     -> Gen e     -> Property@@ -131,11 +132,11 @@   -mapRef :: (Shape sh, Elt b) => (a -> b) -> Array sh a -> Array sh b+mapRef :: (Shape sh, Elt a, Elt b) => (a -> b) -> Array sh a -> Array sh b mapRef f xs = fromFunction (S.shape xs) (\ix -> f (xs S.! ix))  zipWithRef-    :: (Shape sh, Elt c)+    :: (Shape sh, Elt a, Elt b, Elt c)     => (a -> b -> c)     -> Array sh a     -> Array sh b
src/Data/Array/Accelerate/Test/NoFib/Issues/Issue287.hs view
@@ -4,10 +4,10 @@ {-# LANGUAGE RankNTypes          #-} -- | -- Module      : Data.Array.Accelerate.Test.NoFib.Issues.Issue287--- Copyright   : [2009..2017] Trevor L. McDonell+-- Copyright   : [2009..2020] The Accelerate Team -- License     : BSD3 ----- Maintainer  : Trevor L. McDonell <tmcdonell@cse.unsw.edu.au>+-- Maintainer  : Trevor L. McDonell <trevor.mcdonell@gmail.com> -- Stability   : experimental -- Portability : non-portable (GHC extensions) --
src/Data/Array/Accelerate/Test/NoFib/Issues/Issue288.hs view
@@ -1,10 +1,10 @@ {-# LANGUAGE RankNTypes #-} -- | -- Module      : Data.Array.Accelerate.Test.NoFib.Issues.Issue288--- Copyright   : [2009..2017] Trevor L. McDonell+-- Copyright   : [2009..2020] The Accelerate Team -- License     : BSD3 ----- Maintainer  : Trevor L. McDonell <tmcdonell@cse.unsw.edu.au>+-- Maintainer  : Trevor L. McDonell <trevor.mcdonell@gmail.com> -- Stability   : experimental -- Portability : non-portable (GHC extensions) --
src/Data/Array/Accelerate/Test/NoFib/Issues/Issue362.hs view
@@ -1,10 +1,10 @@ {-# LANGUAGE RankNTypes #-} -- | -- Module      : Data.Array.Accelerate.Test.NoFib.Issues.Issue362--- Copyright   : [2009..2017] Trevor L. McDonell+-- Copyright   : [2009..2020] The Accelerate Team -- License     : BSD3 ----- Maintainer  : Trevor L. McDonell <tmcdonell@cse.unsw.edu.au>+-- Maintainer  : Trevor L. McDonell <trevor.mcdonell@gmail.com> -- Stability   : experimental -- Portability : non-portable (GHC extensions) --
+ src/Data/Array/Accelerate/Test/NoFib/Issues/Issue364.hs view
@@ -0,0 +1,99 @@+{-# LANGUAGE ConstraintKinds     #-}+{-# LANGUAGE FlexibleContexts    #-}+{-# LANGUAGE RankNTypes          #-}+{-# LANGUAGE RebindableSyntax    #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TypeApplications    #-}+{-# LANGUAGE TypeOperators       #-}+-- |+-- Module      : Data.Array.Accelerate.Test.NoFib.Issues.Issue364+-- Copyright   : [2009..2020] The Accelerate Team+-- License     : BSD3+--+-- Maintainer  : Trevor L. McDonell <trevor.mcdonell@gmail.com>+-- Stability   : experimental+-- Portability : non-portable (GHC extensions)+--+-- https://github.com/AccelerateHS/accelerate/issues/364+--++module Data.Array.Accelerate.Test.NoFib.Issues.Issue364 (++  test_issue364++) where++import Prelude                                            ( fromInteger, show )+import qualified Prelude                                  as P++import Data.Array.Accelerate                              hiding ( fromInteger )+import Data.Array.Accelerate.Sugar.Elt                    as S+import Data.Array.Accelerate.Sugar.Shape                  as S+import Data.Array.Accelerate.Test.NoFib.Base+import Data.Array.Accelerate.Test.NoFib.Config++import Hedgehog++import Test.Tasty+import Test.Tasty.HUnit+++test_issue364 :: RunN -> TestTree+test_issue364 runN =+  testGroup "issue364"+    [ at @TestInt8   $ testElt i8+    , at @TestInt16  $ testElt i16+    , at @TestInt32  $ testElt i32+    , at @TestInt64  $ testElt i64+    -- , at @TestHalf   $ testElt f16+    , at @TestFloat  $ testElt f32+    , at @TestDouble $ testElt f64+    ]+    where+      testElt :: forall e. (Show e, Num e, Eq e, P.Num e, P.Enum e, P.Eq e)+              => Gen e+              -> TestTree+      testElt _ =+        testGroup (show (eltR @e))+          [ testCase "A" $ expectedArray @_ @e Z 64 @=? runN (scanl iappend one) (intervalArray Z 64)+          , testCase "B" $ expectedArray @_ @e Z 65 @=? runN (scanl iappend one) (intervalArray Z 65) -- failed for integral types+          ]+++-- interval of summations monoid+--+one,top :: Num e => Exp (e, e)+one = T2 (-1) (-1)+top = T2 (-2) (-2)++iappend :: (Num e, Eq e) => Exp (e,e) -> Exp (e,e) -> Exp (e,e)+iappend x y =+  if x == one             then y   else+  if y == one             then x   else+  if x == top || y == top then top+    else+      let T2 x1 x2 = x+          T2 y1 y2 = y+       in+       if x2 + 1 == y1+         then T2 x1 y2+         else top++intervalArray :: (Shape sh, Elt e, P.Num e, P.Enum e)+    => sh+    -> Int+    -> Array (sh:.Int) (e,e)+intervalArray sh n+  = fromList (sh:.n)+  . P.concat+  $ P.replicate (S.size sh) [ (i,i) | i <- [0.. (P.fromIntegral n-1)] ]++expectedArray :: (Shape sh, Elt e, P.Num e, P.Enum e)+    => sh+    -> Int+    -> Array (sh:.Int) (e,e)+expectedArray sh n+  = fromList (sh:.n+1)+  $ P.concat+  $ P.replicate (S.size sh) $ (-1,-1) : [ (0,i) | i <- [0 .. P.fromIntegral n - 1] ]+
src/Data/Array/Accelerate/Test/NoFib/Issues/Issue407.hs view
@@ -1,14 +1,16 @@+{-# LANGUAGE AllowAmbiguousTypes #-} {-# LANGUAGE ConstraintKinds     #-} {-# LANGUAGE FlexibleContexts    #-}+{-# LANGUAGE OverloadedLists     #-} {-# LANGUAGE RankNTypes          #-} {-# LANGUAGE ScopedTypeVariables #-}-{-# LANGUAGE OverloadedLists     #-}+{-# LANGUAGE TypeApplications    #-} -- | -- Module      : Data.Array.Accelerate.Test.NoFib.Issues.Issue407--- Copyright   : [2009..2017] Trevor L. McDonell+-- Copyright   : [2009..2020] The Accelerate Team -- License     : BSD3 ----- Maintainer  : Trevor L. McDonell <tmcdonell@cse.unsw.edu.au>+-- Maintainer  : Trevor L. McDonell <trevor.mcdonell@gmail.com> -- Stability   : experimental -- Portability : non-portable (GHC extensions) --@@ -22,11 +24,10 @@  ) where -import Data.Proxy-import Data.Typeable import Prelude                                                      as P  import Data.Array.Accelerate                                        as A+import Data.Array.Accelerate.Sugar.Elt                              as S import Data.Array.Accelerate.Test.NoFib.Base  import Test.Tasty@@ -36,16 +37,15 @@ test_issue407 :: RunN -> TestTree test_issue407 runN =   testGroup "407"-    [ testElt (Proxy::Proxy Float)-    , testElt (Proxy::Proxy Double)+    [ testElt @Float+    , testElt @Double     ]   where     testElt-        :: forall a. (P.Fractional a, A.RealFloat a)-        => Proxy a-        -> TestTree-    testElt _ =-      testGroup (show (typeOf (undefined :: a)))+        :: forall a. (Show a, P.Fractional a, A.RealFloat a)+        => TestTree+    testElt =+      testGroup (show (eltR @a))         [ testCase "isNaN"      $ eNaN @=? runN (A.map A.isNaN) xs         , testCase "isInfinite" $ eInf @=? runN (A.map A.isInfinite) xs         ]
src/Data/Array/Accelerate/Test/NoFib/Issues/Issue409.hs view
@@ -1,13 +1,15 @@+{-# LANGUAGE AllowAmbiguousTypes #-} {-# LANGUAGE ConstraintKinds     #-} {-# LANGUAGE FlexibleContexts    #-} {-# LANGUAGE RankNTypes          #-} {-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TypeApplications    #-} -- | -- Module      : Data.Array.Accelerate.Test.NoFib.Issues.Issue409--- Copyright   : [2009..2017] Trevor L. McDonell+-- Copyright   : [2009..2020] The Accelerate Team -- License     : BSD3 ----- Maintainer  : Trevor L. McDonell <tmcdonell@cse.unsw.edu.au>+-- Maintainer  : Trevor L. McDonell <trevor.mcdonell@gmail.com> -- Stability   : experimental -- Portability : non-portable (GHC extensions) --@@ -20,11 +22,10 @@  ) where -import Data.Proxy-import Data.Typeable import Prelude                                                      as P  import Data.Array.Accelerate                                        as A+import Data.Array.Accelerate.Sugar.Elt                              as S import Data.Array.Accelerate.Test.NoFib.Base  import Test.Tasty@@ -34,16 +35,15 @@ test_issue409 :: RunN -> TestTree test_issue409 runN =   testGroup "409"-    [ testElt (Proxy::Proxy Float)-    , testElt (Proxy::Proxy Double)+    [ testElt @Float+    , testElt @Double     ]   where     testElt-        :: forall a. (P.Floating a, P.Eq a, A.Floating a)-        => Proxy a-        -> TestTree-    testElt _ =-      testGroup (show (typeOf (undefined :: a)))+        :: forall a. (Show a, P.Floating a, P.Eq a, A.Floating a)+        => TestTree+    testElt =+      testGroup (show (eltR @a))         [ testCase "A" $ e1 @=? indexArray (runN (A.map f) t1) Z         ]       where@@ -53,7 +53,7 @@         t1 :: Scalar a         t1 = fromList Z [1] -        f :: A.Floating a => Exp a -> Exp a+        f :: Exp a -> Exp a         f x = let y = recip x                   b = (-y) * y               in
+ src/Data/Array/Accelerate/Test/NoFib/Issues/Issue436.hs view
@@ -0,0 +1,59 @@+{-# LANGUAGE RankNTypes    #-}+{-# LANGUAGE TypeOperators #-}+-- |+-- Module      : Data.Array.Accelerate.Test.NoFib.Issues.Issue436+-- Copyright   : [2009..2020] The Accelerate Team+-- License     : BSD3+--+-- Maintainer  : Trevor L. McDonell <trevor.mcdonell@gmail.com>+-- Stability   : experimental+-- Portability : non-portable (GHC extensions)+--+-- https://github.com/AccelerateHS/accelerate/issues/436+--++module Data.Array.Accelerate.Test.NoFib.Issues.Issue436 (++  test_issue436++) where++import Data.Array.Accelerate                              as A+import Data.Array.Accelerate.Test.NoFib.Base++import Test.Tasty+import Test.Tasty.HUnit+++test_issue436 :: RunN -> TestTree+test_issue436 runN =+  testGroup "436"+    [ testCase "A" $ e1 @=? runN t1+    , testCase "B" $ e2 @=? runN t2+    ]+++t1 :: Acc (Vector Bool, Scalar Int)+t1 = test 3 (bools (Z :. 5))++e1 :: (Vector Bool, Scalar Int)+e1 = ( fromList (Z :. 3) [True,False,True]+     , fromList Z [3])++t2 :: Acc (Vector Bool, Vector Int)+t2 = test 3 (bools (Z :. 5 :. 5))++e2 :: (Vector Bool, Vector Int)+e2 = ( fromList (Z :. 15) [True,False,True,False,True,False,True,False,True,False,True,False,True,False,True]+     , fromList (Z :. 5) [3,3,3,3,3]+     )++test :: (Shape sh, Elt e)+     => Int+     -> Acc (Array (sh:.Int) e)+     -> Acc (Vector e, Array sh Int)+test n xs = A.filter (const (constant True)) (A.take (constant n) xs)++bools :: Shape sh => sh -> Acc (Array sh Bool)+bools sh = use $ fromList sh (cycle [True, False])+
+ src/Data/Array/Accelerate/Test/NoFib/Issues/Issue437.hs view
@@ -0,0 +1,90 @@+{-# LANGUAGE BangPatterns             #-}+{-# LANGUAGE CPP                      #-}+{-# LANGUAGE ForeignFunctionInterface #-}+{-# LANGUAGE RankNTypes               #-}+{-# LANGUAGE TypeOperators            #-}+{-# OPTIONS_GHC -fno-warn-unused-imports #-}+-- |+-- Module      : Data.Array.Accelerate.Test.NoFib.Issues.Issue437+-- Copyright   : [2009..2020] The Accelerate Team+-- License     : BSD3+--+-- Maintainer  : Trevor L. McDonell <trevor.mcdonell@gmail.com>+-- Stability   : experimental+-- Portability : non-portable (GHC extensions)+--+-- https://github.com/AccelerateHS/accelerate/issues/437+--++module Data.Array.Accelerate.Test.NoFib.Issues.Issue437 (++  test_issue437++) where++import Data.Atomic                                        as Atomic+import Data.Array.Accelerate                              as A+import Data.Array.Accelerate.Test.NoFib.Base++import Test.Tasty+import Test.Tasty.HUnit+import Test.Tasty.ExpectedFailure++import Text.Printf+import Prelude                                            as P+++test_issue437 :: RunN -> TestTree+#ifndef ACCELERATE_DEBUG+test_issue437 _+  = expectFail+  $ testCase "437"+  $ assertFailure "This test requires building with -fdebug"+#else+test_issue437 runN+  = testCase "437"+  $ do+    a0 <- Atomic.read __total_bytes_allocated_remote+    b0 <- Atomic.read __total_bytes_copied_to_remote+    c0 <- Atomic.read __total_bytes_copied_from_remote++    let (a,_) = go xs++    -- check the final result is actually transferred back+    a @?= fromList Z [42]++    a1 <- Atomic.read __total_bytes_allocated_remote+    b1 <- Atomic.read __total_bytes_copied_to_remote+    c1 <- Atomic.read __total_bytes_copied_from_remote++    let alloc = a1-a0+        to    = b1-b0+        from  = c1-c0++    -- Either:+    --  a) this is a local memory backend; no transfer takes place+    --+    --  b) this is a remote memory backend; we should only transfer the 4 bytes+    --     to the device for the 'unit', but since the data is already on the+    --     host we can avoid the transfer back+    --+    assertBool (printf "bytes_allocated_remote=%d, bytes_copied_to_remote=%d, bytes_copied_from_remote=%d" alloc to from)+      $ (alloc P.== 0 P.&& to P.== 0 P.&& from P.== 0) P.||   -- local memory space+        (alloc P.>  0 P.&& to P.== 4 P.&& from P.== 0)        -- remote memory space+  where+    xs :: (Scalar Float, Matrix Float)+    xs = runN $ T2 (unit 42) (fill (constant $ Z:.10000:.10000) 1)++    go :: Arrays a => a -> a+    go = runN f+      where+        f :: Arrays a => Acc a -> Acc a+        f = id++-- internals+foreign import ccall "&__total_bytes_allocated_remote"    __total_bytes_allocated_remote    :: Atomic+foreign import ccall "&__total_bytes_copied_to_remote"    __total_bytes_copied_to_remote    :: Atomic+foreign import ccall "&__total_bytes_copied_from_remote"  __total_bytes_copied_from_remote  :: Atomic++#endif+
+ src/Data/Array/Accelerate/Test/NoFib/Issues/Issue439.hs view
@@ -0,0 +1,37 @@+{-# LANGUAGE RankNTypes #-}+-- |+-- Module      : Data.Array.Accelerate.Test.NoFib.Issues.Issue439+-- Copyright   : [2009..2020] The Accelerate Team+-- License     : BSD3+--+-- Maintainer  : Trevor L. McDonell <trevor.mcdonell@gmail.com>+-- Stability   : experimental+-- Portability : non-portable (GHC extensions)+--+-- https://github.com/AccelerateHS/accelerate-llvm/issues/46+--++module Data.Array.Accelerate.Test.NoFib.Issues.Issue439 (++  test_issue439++) where++import Data.Array.Accelerate                              as A+import Data.Array.Accelerate.Test.NoFib.Base++import Test.Tasty+import Test.Tasty.HUnit+++test_issue439 :: RunN -> TestTree+test_issue439 runN+  = testCase "439"+  $ e1 @=? runN t1++e1 :: Scalar Float+e1 = fromList Z [2]++t1 :: Acc (Scalar Float)+t1 = compute . A.map (* 2) . compute $ fill Z_ 1+
src/Data/Array/Accelerate/Test/NoFib/Issues/Issue93.hs view
@@ -1,10 +1,10 @@ {-# LANGUAGE RankNTypes #-} -- | -- Module      : Data.Array.Accelerate.Test.NoFib.Issues.Issue93--- Copyright   : [2009..2017] Trevor L. McDonell+-- Copyright   : [2009..2020] The Accelerate Team -- License     : BSD3 ----- Maintainer  : Trevor L. McDonell <tmcdonell@cse.unsw.edu.au>+-- Maintainer  : Trevor L. McDonell <trevor.mcdonell@gmail.com> -- Stability   : experimental -- Portability : non-portable (GHC extensions) --@@ -32,7 +32,7 @@ xs = fromList (Z :. 1 :. 1) [5]  test1 :: Acc (Array DIM2 Int)-test1 = permute (\c _ -> c) (fill (shape xs') (constant 0)) id xs'+test1 = permute (\c _ -> c) (fill (shape xs') (constant 0)) Just_ xs'   where     xs' = use xs 
src/Data/Array/Accelerate/Test/NoFib/Prelude.hs view
@@ -1,10 +1,10 @@ {-# LANGUAGE RankNTypes #-} -- | -- Module      : Data.Array.Accelerate.Test.NoFib.Prelude--- Copyright   : [2009..2017] Trevor L. McDonell+-- Copyright   : [2009..2020] The Accelerate Team -- License     : BSD3 ----- Maintainer  : Trevor L. McDonell <tmcdonell@cse.unsw.edu.au>+-- Maintainer  : Trevor L. McDonell <trevor.mcdonell@gmail.com> -- Stability   : experimental -- Portability : non-portable (GHC extensions) --@@ -15,6 +15,7 @@    module Data.Array.Accelerate.Test.NoFib.Prelude.Map,   module Data.Array.Accelerate.Test.NoFib.Prelude.ZipWith,+  module Data.Array.Accelerate.Test.NoFib.Prelude.SIMD,   module Data.Array.Accelerate.Test.NoFib.Prelude.Fold,   module Data.Array.Accelerate.Test.NoFib.Prelude.Scan,   module Data.Array.Accelerate.Test.NoFib.Prelude.Backpermute,@@ -29,6 +30,7 @@ import Data.Array.Accelerate.Test.NoFib.Base import Data.Array.Accelerate.Test.NoFib.Prelude.Map import Data.Array.Accelerate.Test.NoFib.Prelude.ZipWith+import Data.Array.Accelerate.Test.NoFib.Prelude.SIMD import Data.Array.Accelerate.Test.NoFib.Prelude.Fold import Data.Array.Accelerate.Test.NoFib.Prelude.Scan import Data.Array.Accelerate.Test.NoFib.Prelude.Backpermute@@ -42,6 +44,7 @@   testGroup "prelude"     [ test_map runN     , test_zipWith runN+    , test_simd runN     , test_fold runN     , test_foldSeg runN     , test_backpermute runN
src/Data/Array/Accelerate/Test/NoFib/Prelude/Backpermute.hs view
@@ -3,13 +3,14 @@ {-# LANGUAGE FlexibleContexts    #-} {-# LANGUAGE RankNTypes          #-} {-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TypeApplications    #-} {-# LANGUAGE TypeOperators       #-} -- | -- Module      : Data.Array.Accelerate.Test.NoFib.Prelude.Backpermute--- Copyright   : [2009..2017] Trevor L. McDonell+-- Copyright   : [2009..2020] The Accelerate Team -- License     : BSD3 ----- Maintainer  : Trevor L. McDonell <tmcdonell@cse.unsw.edu.au>+-- Maintainer  : Trevor L. McDonell <trevor.mcdonell@gmail.com> -- Stability   : experimental -- Portability : non-portable (GHC extensions) --@@ -20,12 +21,12 @@  ) where -import Data.Proxy-import Data.Typeable import Prelude                                                      as P  import Data.Array.Accelerate                                        as A-import Data.Array.Accelerate.Array.Sugar                            as S+import Data.Array.Accelerate.Sugar.Array                            as S+import Data.Array.Accelerate.Sugar.Elt                              as S+import Data.Array.Accelerate.Sugar.Shape                            as S import Data.Array.Accelerate.Test.NoFib.Base import Data.Array.Accelerate.Test.NoFib.Config import Data.Array.Accelerate.Test.Similar@@ -41,36 +42,36 @@ test_backpermute :: RunN -> TestTree test_backpermute runN =   testGroup "backpermute"-    [ at (Proxy::Proxy TestInt8)   $ testElt i8-    , at (Proxy::Proxy TestInt16)  $ testElt i16-    , at (Proxy::Proxy TestInt32)  $ testElt i32-    , at (Proxy::Proxy TestInt64)  $ testElt i64-    , at (Proxy::Proxy TestWord8)  $ testElt w8-    , at (Proxy::Proxy TestWord16) $ testElt w16-    , at (Proxy::Proxy TestWord32) $ testElt w32-    , at (Proxy::Proxy TestWord64) $ testElt w64-    , at (Proxy::Proxy TestHalf)   $ testElt f16-    , at (Proxy::Proxy TestFloat)  $ testElt f32-    , at (Proxy::Proxy TestDouble) $ testElt f64+    [ at @TestInt8   $ testElt i8+    , at @TestInt16  $ testElt i16+    , at @TestInt32  $ testElt i32+    , at @TestInt64  $ testElt i64+    , at @TestWord8  $ testElt w8+    , at @TestWord16 $ testElt w16+    , at @TestWord32 $ testElt w32+    , at @TestWord64 $ testElt w64+    , at @TestHalf   $ testElt f16+    , at @TestFloat  $ testElt f32+    , at @TestDouble $ testElt f64     ]   where     testElt-        :: forall a. (Similar a, Elt a)+        :: forall a. (Similar a, Elt a, Show a)         => Gen a         -> TestTree     testElt e =-      testGroup (show (typeOf (undefined :: a)))+      testGroup (show (eltR @a))         [ testDim dim1         , testDim dim2         , testDim dim3         ]       where         testDim-            :: forall sh. (Shape sh, Slice sh, P.Eq sh)+            :: forall sh. (Shape sh, Slice sh, Show sh, P.Eq sh)             => Gen (sh:.Int)             -> TestTree         testDim sh =-          testGroup ("DIM" P.++ show (rank (undefined::(sh:.Int))))+          testGroup ("DIM" P.++ show (rank @(sh:.Int)))             [               testProperty "take"         $ test_take runN sh e             , testProperty "drop"         $ test_drop runN sh e@@ -80,7 +81,7 @@             ]  test_take-    :: (Shape sh, Slice sh, Similar e, P.Eq sh, Elt e)+    :: (Shape sh, Slice sh, Show sh, Similar e, Show e, P.Eq sh, Elt e)     => RunN     -> Gen (sh:.Int)     -> Gen e@@ -93,7 +94,7 @@     let !go = runN (\v -> A.take (the v)) in go (scalar i) xs ~~~ takeRef i xs  test_drop-    :: (Shape sh, Slice sh, Similar e, P.Eq sh, Elt e)+    :: (Shape sh, Slice sh, Show sh, Similar e, Show e, P.Eq sh, Elt e)     => RunN     -> Gen (sh:.Int)     -> Gen e@@ -106,7 +107,7 @@     let !go = runN (\v -> A.drop (the v)) in go (scalar i) xs ~~~ dropRef i xs  test_gather-    :: (Shape sh, Shape sh', P.Eq sh', Similar e, Elt e)+    :: (Shape sh, Shape sh', Show sh, Show sh', P.Eq sh', Similar e, Show e, Elt e)     => RunN     -> Gen sh     -> Gen sh'
src/Data/Array/Accelerate/Test/NoFib/Prelude/Filter.hs view
@@ -5,13 +5,14 @@ {-# LANGUAGE MonoLocalBinds      #-} {-# LANGUAGE RankNTypes          #-} {-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TypeApplications    #-} {-# LANGUAGE TypeOperators       #-} -- | -- Module      : Data.Array.Accelerate.Test.NoFib.Prelude.Filter--- Copyright   : [2009..2017] Trevor L. McDonell+-- Copyright   : [2009..2020] The Accelerate Team -- License     : BSD3 ----- Maintainer  : Trevor L. McDonell <tmcdonell@cse.unsw.edu.au>+-- Maintainer  : Trevor L. McDonell <trevor.mcdonell@gmail.com> -- Stability   : experimental -- Portability : non-portable (GHC extensions) --@@ -22,12 +23,12 @@  ) where -import Data.Proxy-import Data.Typeable import Prelude                                                      as P  import Data.Array.Accelerate                                        as A-import Data.Array.Accelerate.Array.Sugar                            as S+import Data.Array.Accelerate.Sugar.Array                            as S+import Data.Array.Accelerate.Sugar.Elt                              as S+import Data.Array.Accelerate.Sugar.Shape                            as S import Data.Array.Accelerate.Test.NoFib.Base import Data.Array.Accelerate.Test.NoFib.Config import Data.Array.Accelerate.Test.Similar@@ -41,62 +42,62 @@ test_filter :: RunN -> TestTree test_filter runN =   testGroup "filter"-    [ at (Proxy::Proxy TestInt8)   $ testIntegralElt i8-    , at (Proxy::Proxy TestInt16)  $ testIntegralElt i16-    , at (Proxy::Proxy TestInt32)  $ testIntegralElt i32-    , at (Proxy::Proxy TestInt64)  $ testIntegralElt i64-    , at (Proxy::Proxy TestWord8)  $ testIntegralElt w8-    , at (Proxy::Proxy TestWord16) $ testIntegralElt w16-    , at (Proxy::Proxy TestWord32) $ testIntegralElt w32-    , at (Proxy::Proxy TestWord64) $ testIntegralElt w64-    , at (Proxy::Proxy TestHalf)   $ testFloatingElt f16-    , at (Proxy::Proxy TestFloat)  $ testFloatingElt f32-    , at (Proxy::Proxy TestDouble) $ testFloatingElt f64+    [ at @TestInt8   $ testIntegralElt i8+    , at @TestInt16  $ testIntegralElt i16+    , at @TestInt32  $ testIntegralElt i32+    , at @TestInt64  $ testIntegralElt i64+    , at @TestWord8  $ testIntegralElt w8+    , at @TestWord16 $ testIntegralElt w16+    , at @TestWord32 $ testIntegralElt w32+    , at @TestWord64 $ testIntegralElt w64+    , at @TestHalf   $ testFloatingElt f16+    , at @TestFloat  $ testFloatingElt f32+    , at @TestDouble $ testFloatingElt f64     ]   where     testIntegralElt-        :: forall a. (P.Integral a, A.Integral a, Similar a)+        :: forall a. (P.Integral a, A.Integral a, Similar a, Show a)         => Gen a         -> TestTree     testIntegralElt e =-      testGroup (show (typeOf (undefined :: a)))+      testGroup (show (eltR @a))         [ testDim dim1         , testDim dim2         , testDim dim3         ]       where         testDim-            :: forall sh. (Shape sh, Slice sh, P.Eq sh)+            :: forall sh. (Shape sh, Slice sh, Show sh, P.Eq sh)             => Gen (sh:.Int)             -> TestTree         testDim sh =-          testGroup ("DIM" P.++ show (rank (undefined::(sh:.Int))))+          testGroup ("DIM" P.++ show (rank @(sh:.Int)))             [ testProperty "even"     $ test_even runN sh e             ]      testFloatingElt-        :: forall a. (P.Floating a, P.Ord a, A.Floating a, A.Ord a, Similar a)+        :: forall a. (P.Floating a, P.Ord a, A.Floating a, A.Ord a, Similar a, Show a)         => Gen a         -> TestTree     testFloatingElt e =-      testGroup (show (typeOf (undefined :: a)))+      testGroup (show (eltR @a))         [ testDim dim1         , testDim dim2         , testDim dim3         ]       where         testDim-            :: forall sh. (Shape sh, Slice sh, P.Eq sh)+            :: forall sh. (Shape sh, Slice sh, Show sh, P.Eq sh)             => Gen (sh:.Int)             -> TestTree         testDim sh =-          testGroup ("DIM" P.++ show (rank (undefined::(sh:.Int))))+          testGroup ("DIM" P.++ show (rank @(sh:.Int)))             [ testProperty "positive" $ test_positive runN sh e             ]   test_even-    :: (Shape sh, Slice sh, Similar e, P.Eq sh, P.Integral e, A.Integral e)+    :: (Shape sh, Slice sh, Show sh, Similar e, Show e, P.Eq sh, P.Integral e, A.Integral e)     => RunN     -> Gen (sh:.Int)     -> Gen e@@ -108,7 +109,7 @@     let !go = runN (A.filter A.even) in go xs ~~~ filterRef P.even xs  test_positive-    :: (Shape sh, Slice sh, Similar e, P.Eq sh, P.Num e, P.Ord e, A.Num e, A.Ord e)+    :: (Shape sh, Slice sh, Show sh, Similar e, Show e, P.Eq sh, P.Num e, P.Ord e, A.Num e, A.Ord e)     => RunN     -> Gen (sh:.Int)     -> Gen e
src/Data/Array/Accelerate/Test/NoFib/Prelude/Fold.hs view
@@ -3,13 +3,14 @@ {-# LANGUAGE FlexibleContexts    #-} {-# LANGUAGE RankNTypes          #-} {-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TypeApplications    #-} {-# LANGUAGE TypeOperators       #-} -- | -- Module      : Data.Array.Accelerate.Test.NoFib.Prelude.Fold--- Copyright   : [2009..2017] Trevor L. McDonell+-- Copyright   : [2009..2020] The Accelerate Team -- License     : BSD3 ----- Maintainer  : Trevor L. McDonell <tmcdonell@cse.unsw.edu.au>+-- Maintainer  : Trevor L. McDonell <trevor.mcdonell@gmail.com> -- Stability   : experimental -- Portability : non-portable (GHC extensions) --@@ -21,12 +22,11 @@  ) where -import Data.Proxy-import Data.Typeable import Prelude                                                      as P  import Data.Array.Accelerate                                        as A-import Data.Array.Accelerate.Array.Sugar+import Data.Array.Accelerate.Sugar.Elt                              as S+import Data.Array.Accelerate.Sugar.Shape                            as S import Data.Array.Accelerate.Test.NoFib.Base import Data.Array.Accelerate.Test.NoFib.Config import Data.Array.Accelerate.Test.Similar@@ -42,37 +42,37 @@ test_fold :: RunN -> TestTree test_fold runN =   testGroup "fold"-    [ at (Proxy::Proxy TestInt8)   $ testElt i8  (Gen.int8   (Range.linearFrom 0 (-1) 1))-    , at (Proxy::Proxy TestInt16)  $ testElt i16 (Gen.int16  (Range.linearFrom 0 (-10) 10))-    , at (Proxy::Proxy TestInt32)  $ testElt i32 (Gen.int32  (Range.linearFrom 0 (-1000) 1000))-    , at (Proxy::Proxy TestInt64)  $ testElt i64 (Gen.int64  (Range.linearFrom 0 (-10000) 10000))-    , at (Proxy::Proxy TestWord8)  $ testElt w8  (Gen.word8  (Range.linear 0 1))-    , at (Proxy::Proxy TestWord16) $ testElt w16 (Gen.word16 (Range.linear 0 10))-    , at (Proxy::Proxy TestWord32) $ testElt w32 (Gen.word32 (Range.linear 0 1000))-    , at (Proxy::Proxy TestWord64) $ testElt w64 (Gen.word64 (Range.linear 0 10000))-    , at (Proxy::Proxy TestHalf)   $ testElt f16 f16-    , at (Proxy::Proxy TestFloat)  $ testElt f32 f32-    , at (Proxy::Proxy TestDouble) $ testElt f64 f64+    [ at @TestInt8   $ testElt i8  (Gen.int8   (Range.linearFrom 0 (-1) 1))+    , at @TestInt16  $ testElt i16 (Gen.int16  (Range.linearFrom 0 (-10) 10))+    , at @TestInt32  $ testElt i32 (Gen.int32  (Range.linearFrom 0 (-1000) 1000))+    , at @TestInt64  $ testElt i64 (Gen.int64  (Range.linearFrom 0 (-10000) 10000))+    , at @TestWord8  $ testElt w8  (Gen.word8  (Range.linear 0 1))+    , at @TestWord16 $ testElt w16 (Gen.word16 (Range.linear 0 10))+    , at @TestWord32 $ testElt w32 (Gen.word32 (Range.linear 0 1000))+    , at @TestWord64 $ testElt w64 (Gen.word64 (Range.linear 0 10000))+    , at @TestHalf   $ testElt f16 f16+    , at @TestFloat  $ testElt f32 f32+    , at @TestDouble $ testElt f64 f64     ]   where     testElt-        :: forall a. (P.Num a, P.Ord a , A.Num a, A.Ord a , Similar a)+        :: forall a. (P.Num a, P.Ord a , A.Num a, A.Ord a , Similar a, Show a)         => Gen a         -> Gen a         -> TestTree     testElt e small =-      testGroup (show (typeOf (undefined :: a)))+      testGroup (show (eltR @a))         [ testDim dim1         , testDim dim2         , testDim dim3         ]       where         testDim-            :: forall sh. (Shape sh, P.Eq sh)+            :: forall sh. (Shape sh, Show sh, P.Eq sh)             => Gen (sh:.Int)             -> TestTree         testDim sh =-          testGroup ("DIM" P.++ show (rank (undefined::(sh:.Int))))+          testGroup ("DIM" P.++ show (rank @(sh:.Int)))             [               testProperty "sum"              $ test_sum runN sh (return 0) e             , testProperty "non-neutral sum"  $ test_sum runN sh e e@@ -85,34 +85,34 @@ test_foldSeg :: RunN -> TestTree test_foldSeg runN =   testGroup "foldSeg"-    [ at (Proxy::Proxy TestInt8)   $ testElt i8-    , at (Proxy::Proxy TestInt16)  $ testElt i16-    , at (Proxy::Proxy TestInt32)  $ testElt i32-    , at (Proxy::Proxy TestInt64)  $ testElt i64-    , at (Proxy::Proxy TestWord8)  $ testElt w8-    , at (Proxy::Proxy TestWord16) $ testElt w16-    , at (Proxy::Proxy TestWord32) $ testElt w32-    , at (Proxy::Proxy TestWord64) $ testElt w64-    , at (Proxy::Proxy TestFloat)  $ testElt f32-    , at (Proxy::Proxy TestDouble) $ testElt f64+    [ at @TestInt8   $ testElt i8+    , at @TestInt16  $ testElt i16+    , at @TestInt32  $ testElt i32+    , at @TestInt64  $ testElt i64+    , at @TestWord8  $ testElt w8+    , at @TestWord16 $ testElt w16+    , at @TestWord32 $ testElt w32+    , at @TestWord64 $ testElt w64+    , at @TestFloat  $ testElt f32+    , at @TestDouble $ testElt f64     ]   where-    testElt :: forall a. (P.Num a, P.Ord a , A.Num a, A.Ord a , Similar a)+    testElt :: forall a. (P.Num a, P.Ord a , A.Num a, A.Ord a , Similar a, Show a)         => Gen a         -> TestTree     testElt e =-      testGroup (show (typeOf (undefined :: a)))+      testGroup (show (eltR @a))         [ testDim dim1         , testDim dim2         , testDim dim3         ]       where         testDim-            :: forall sh. (Shape sh, P.Eq sh)+            :: forall sh. (Shape sh, Show sh, P.Eq sh)             => Gen (sh:.Int)             -> TestTree         testDim sh =-          testGroup ("DIM" P.++ show (rank (undefined::(sh:.Int))))+          testGroup ("DIM" P.++ show (rank @(sh:.Int)))             [               testProperty "sum"              $ test_segmented_sum runN sh (return 0) e             , testProperty "non-neutral sum"  $ test_segmented_sum runN sh e e@@ -125,7 +125,7 @@ scalar x = fromFunction Z (const x)  test_sum-    :: (Shape sh, Similar e, P.Eq sh, P.Num e, A.Num e)+    :: (Shape sh, Show sh, Similar e, Show e, P.Eq sh, P.Num e, A.Num e)     => RunN     -> Gen (sh:.Int)     -> Gen e@@ -139,7 +139,7 @@     let !go = runN (\v -> A.fold (+) (the v)) in go (scalar x) xs ~~~ foldRef (+) x xs  test_mss-    :: (Shape sh, Similar e, P.Eq sh, P.Num e, P.Ord e, A.Num e, A.Ord e)+    :: (Shape sh, Show sh, Similar e, Show e, P.Eq sh, P.Num e, P.Ord e, A.Num e, A.Ord e)     => RunN     -> Gen (sh:.Int)     -> Gen e@@ -151,7 +151,7 @@     let !go = runN maximumSegmentSum in go xs ~~~ maximumSegmentSumRef xs  test_minimum-    :: (Shape sh, Similar e, P.Eq sh, P.Num e, P.Ord e, A.Num e, A.Ord e)+    :: (Shape sh, Show sh, Similar e, Show e, P.Eq sh, P.Ord e, A.Ord e)     => RunN     -> Gen (sh:.Int)     -> Gen e@@ -163,7 +163,7 @@     let !go = runN A.minimum in go xs ~~~ fold1Ref P.min xs  test_maximum-    :: (Shape sh, Similar e, P.Eq sh, P.Num e, P.Ord e, A.Num e, A.Ord e)+    :: (Shape sh, Show sh, Similar e, Show e, P.Eq sh, P.Ord e, A.Ord e)     => RunN     -> Gen (sh:.Int)     -> Gen e@@ -175,7 +175,7 @@     let !go = runN A.maximum in go xs ~~~ fold1Ref P.max xs  test_segmented_sum-    :: forall sh e. (Shape sh, Similar e, P.Eq sh, P.Num e, A.Num e)+    :: forall sh e. (Shape sh, Show sh, Similar e, Show e, P.Eq sh, P.Num e, A.Num e)     => RunN     -> Gen (sh:.Int)     -> Gen e@@ -187,12 +187,12 @@     sh:.n1  <- forAll dim     n2      <- forAll (Gen.int (Range.linear 0 64))     n       <- return (P.min n1 n2) -- don't generate too many segments-    seg     <- forAll (array (Z:.n) (Gen.int (Range.linear 0 (128 `quot` 2 P.^ (rank (undefined::sh))))))+    seg     <- forAll (array (Z:.n) (Gen.int (Range.linear 0 (128 `quot` 2 P.^ (rank @sh)))))     xs      <- forAll (array (sh:.P.sum (toList seg)) e)     let !go = runN (\v -> A.foldSeg (+) (the v)) in go (scalar x) xs seg ~~~ foldSegRef (+) x xs seg  test_segmented_minimum-    :: forall sh e. (Shape sh, Similar e, P.Eq sh, P.Num e, P.Ord e, A.Num e, A.Ord e)+    :: forall sh e. (Shape sh, Show sh, Similar e, Show e, P.Eq sh, P.Ord e, A.Ord e)     => RunN     -> Gen (sh:.Int)     -> Gen e@@ -202,12 +202,12 @@     sh:.n1  <- forAll dim     n2      <- forAll (Gen.int (Range.linear 0 64))     n       <- return (P.min n1 n2) -- don't generate too many segments-    seg     <- forAll (array (Z:.n) (Gen.int (Range.linear 1 (128 `quot` 2 P.^ (rank (undefined::sh))))))+    seg     <- forAll (array (Z:.n) (Gen.int (Range.linear 1 (128 `quot` 2 P.^ (rank @sh)))))     xs      <- forAll (array (sh:.P.sum (toList seg)) e)     let !go = runN (A.fold1Seg A.min) in go xs seg ~~~ fold1SegRef P.min xs seg  test_segmented_maximum-    :: forall sh e. (Shape sh, Similar e, P.Eq sh, P.Num e, P.Ord e, A.Num e, A.Ord e)+    :: forall sh e. (Shape sh, Show sh, Similar e, Show e, P.Eq sh, P.Ord e, A.Ord e)     => RunN     -> Gen (sh:.Int)     -> Gen e@@ -217,7 +217,7 @@     sh:.n1  <- forAll dim     n2      <- forAll (Gen.int (Range.linear 0 64))     n       <- return (P.min n1 n2) -- don't generate too many segments-    seg     <- forAll (array (Z:.n) (Gen.int (Range.linear 1 (128 `quot` 2 P.^ (rank (undefined::sh))))))+    seg     <- forAll (array (Z:.n) (Gen.int (Range.linear 1 (128 `quot` 2 P.^ (rank @sh)))))     xs      <- forAll (array (sh:.P.sum (toList seg)) e)     let !go = runN (A.fold1Seg A.max) in go xs seg ~~~ fold1SegRef P.max xs seg 
src/Data/Array/Accelerate/Test/NoFib/Prelude/Map.hs view
@@ -1,17 +1,17 @@ {-# LANGUAGE BangPatterns        #-}-{-# LANGUAGE CPP                 #-} {-# LANGUAGE ConstraintKinds     #-} {-# LANGUAGE FlexibleContexts    #-} {-# LANGUAGE MonoLocalBinds      #-} {-# LANGUAGE RankNTypes          #-} {-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TypeApplications    #-} {-# LANGUAGE TypeOperators       #-} -- | -- Module      : Data.Array.Accelerate.Test.NoFib.Prelude.Map--- Copyright   : [2009..2017] Trevor L. McDonell+-- Copyright   : [2009..2020] The Accelerate Team -- License     : BSD3 ----- Maintainer  : Trevor L. McDonell <tmcdonell@cse.unsw.edu.au>+-- Maintainer  : Trevor L. McDonell <trevor.mcdonell@gmail.com> -- Stability   : experimental -- Portability : non-portable (GHC extensions) --@@ -22,14 +22,14 @@  ) where -import Data.Proxy import Data.Bits                                                    as P-import Data.Typeable import Prelude                                                      as P  import Data.Array.Accelerate                                        as A import Data.Array.Accelerate.Data.Bits                              as A-import Data.Array.Accelerate.Array.Sugar                            as Sugar+import Data.Array.Accelerate.Sugar.Array                            as S+import Data.Array.Accelerate.Sugar.Elt                              as S+import Data.Array.Accelerate.Sugar.Shape                            as S import Data.Array.Accelerate.Test.NoFib.Base import Data.Array.Accelerate.Test.NoFib.Config import Data.Array.Accelerate.Test.Similar@@ -45,38 +45,39 @@ test_map :: RunN -> TestTree test_map runN =   testGroup "map"-    [ at (Proxy::Proxy TestInt8)   $ testIntegralElt i8-    , at (Proxy::Proxy TestInt16)  $ testIntegralElt i16-    , at (Proxy::Proxy TestInt32)  $ testIntegralElt i32-    , at (Proxy::Proxy TestInt64)  $ testIntegralElt i64-    , at (Proxy::Proxy TestWord8)  $ testIntegralElt w8-    , at (Proxy::Proxy TestWord16) $ testIntegralElt w16-    , at (Proxy::Proxy TestWord32) $ testIntegralElt w32-    , at (Proxy::Proxy TestWord64) $ testIntegralElt w64-    , at (Proxy::Proxy TestHalf)   $ testFloatingElt (Gen.realFloat :: Range Half -> Gen Half)-    , at (Proxy::Proxy TestFloat)  $ testFloatingElt Gen.float-    , at (Proxy::Proxy TestDouble) $ testFloatingElt Gen.double+    [ at @TestInt8   $ testIntegralElt i8+    , at @TestInt16  $ testIntegralElt i16+    , at @TestInt32  $ testIntegralElt i32+    , at @TestInt64  $ testIntegralElt i64+    , at @TestWord8  $ testIntegralElt w8+    , at @TestWord16 $ testIntegralElt w16+    , at @TestWord32 $ testIntegralElt w32+    , at @TestWord64 $ testIntegralElt w64+    , at @TestHalf   $ testFloatingElt (Gen.realFloat :: Range Half -> Gen Half)+    , at @TestFloat  $ testFloatingElt Gen.float+    , at @TestDouble $ testFloatingElt Gen.double     ]   where     testIntegralElt         :: forall a. ( P.Integral a, P.FiniteBits a                      , A.Integral a, A.FiniteBits a-                     , A.FromIntegral a Double, Similar a )+                     , A.FromIntegral a Double+                     , Similar a, Show a )         => Gen a         -> TestTree     testIntegralElt e =-      testGroup (show (typeOf (undefined :: a)))+      testGroup (show (eltR @a))         [ testDim dim0         , testDim dim1         , testDim dim2         ]       where         testDim-            :: forall sh. (Shape sh, P.Eq sh)+            :: forall sh. (Shape sh, Show sh, P.Eq sh)             => Gen sh             -> TestTree         testDim sh =-          testGroup ("DIM" P.++ show (rank (undefined::sh)))+          testGroup ("DIM" P.++ show (rank @sh))             [ -- operators on Num               testProperty "neg"                $ test_negate runN sh e             , testProperty "abs"                $ test_abs runN sh e@@ -93,22 +94,22 @@             ]      testFloatingElt-        :: forall a. (P.RealFloat a, A.Floating a, A.RealFrac a, Similar a)+        :: forall a. (P.RealFloat a, A.Floating a, A.RealFrac a, Similar a, Show a)         => (Range a -> Gen a)         -> TestTree     testFloatingElt e =-      testGroup (show (typeOf (undefined :: a)))+      testGroup (show (eltR @a))         [ testDim dim0         , testDim dim1         , testDim dim2         ]       where         testDim-            :: forall sh. (Shape sh, P.Eq sh)+            :: forall sh. (Shape sh, Show sh, P.Eq sh)             => Gen sh             -> TestTree         testDim sh =-          testGroup ("DIM" P.++ show (rank (undefined::sh)))+          testGroup ("DIM" P.++ show (rank @sh))             [ -- operators on Num               testProperty "neg"        $ test_negate runN sh (fullrange e)             , testProperty "abs"        $ test_abs runN sh (fullrange e)@@ -145,7 +146,7 @@   test_negate-    :: (Shape sh, Similar e, A.Num e, P.Num e, P.Eq sh)+    :: (Shape sh, Show sh, Similar e, Show e, A.Num e, P.Num e, P.Eq sh)     => RunN     -> Gen sh     -> Gen e@@ -157,7 +158,7 @@     let !go = runN (A.map negate) in go xs ~~~ mapRef negate xs  test_abs-    :: (Shape sh, Similar e, A.Num e, P.Num e, P.Eq sh)+    :: (Shape sh, Show sh, Similar e, Show e, A.Num e, P.Num e, P.Eq sh)     => RunN     -> Gen sh     -> Gen e@@ -169,7 +170,7 @@     let !go = runN (A.map abs) in go xs ~~~ mapRef abs xs  test_signum-    :: (Shape sh, Similar e, A.Num e, P.Num e, P.Eq sh)+    :: (Shape sh, Show sh, Similar e, Show e, A.Num e, P.Num e, P.Eq sh)     => RunN     -> Gen sh     -> Gen e@@ -181,7 +182,7 @@     let !go = runN (A.map signum) in go xs ~~~ mapRef signum xs  test_complement-    :: (Shape sh, Similar e, A.Bits e, P.Bits e, P.Eq sh)+    :: (Shape sh, Show sh, Similar e, Show e, A.Bits e, P.Bits e, P.Eq sh)     => RunN     -> Gen sh     -> Gen e@@ -193,7 +194,7 @@     let !go = runN (A.map A.complement) in go xs ~~~ mapRef P.complement xs  test_popCount-    :: (Shape sh, Similar e, A.Bits e, P.Bits e, P.Eq sh)+    :: (Shape sh, Show sh, Show e, A.Bits e, P.Bits e, P.Eq sh)     => RunN     -> Gen sh     -> Gen e@@ -205,7 +206,7 @@     let !go = runN (A.map A.popCount) in go xs ~~~ mapRef P.popCount xs  test_countLeadingZeros-    :: (Shape sh, Similar e, A.FiniteBits e, P.FiniteBits e, P.Eq sh)+    :: (Shape sh, Show sh, Show e, A.FiniteBits e, P.FiniteBits e, P.Eq sh)     => RunN     -> Gen sh     -> Gen e@@ -217,7 +218,7 @@     let !go = runN (A.map A.countLeadingZeros) in go xs ~~~ mapRef countLeadingZerosRef xs  test_countTrailingZeros-    :: (Shape sh, Similar e, A.FiniteBits e, P.FiniteBits e, P.Eq sh)+    :: (Shape sh, Show sh, Show e, A.FiniteBits e, P.FiniteBits e, P.Eq sh)     => RunN     -> Gen sh     -> Gen e@@ -229,7 +230,7 @@     let !go = runN (A.map A.countTrailingZeros) in go xs ~~~ mapRef countTrailingZerosRef xs  test_fromIntegral-    :: forall sh e. (Shape sh, Similar e, P.Eq sh, P.Integral e, A.Integral e, A.FromIntegral e Double)+    :: forall sh e. (Shape sh, Show sh, Show e, P.Eq sh, P.Integral e, A.Integral e, A.FromIntegral e Double)     => RunN     -> Gen sh     -> Gen e@@ -241,7 +242,7 @@     let !go = runN (A.map A.fromIntegral) in go xs ~~~ mapRef (P.fromIntegral :: e -> Double) xs  test_recip-    :: (Shape sh, Similar e, P.Eq sh, P.Fractional e, A.Fractional e)+    :: (Shape sh, Show sh, Similar e, Show e, P.Eq sh, P.Fractional e, A.Fractional e)     => RunN     -> Gen sh     -> Gen e@@ -253,7 +254,7 @@     let !go = runN (A.map recip) in go xs ~~~ mapRef recip xs  test_sin-    :: (Shape sh, Similar e, P.Eq sh, P.Floating e, A.Floating e)+    :: (Shape sh, Show sh, Similar e, Show e, P.Eq sh, P.Floating e, A.Floating e)     => RunN     -> Gen sh     -> Gen e@@ -265,7 +266,7 @@     let !go = runN (A.map sin) in go xs ~~~ mapRef sin xs  test_cos-    :: (Shape sh, Similar e, P.Eq sh, P.Floating e, A.Floating e)+    :: (Shape sh, Show sh, Similar e, Show e, P.Eq sh, P.Floating e, A.Floating e)     => RunN     -> Gen sh     -> Gen e@@ -277,7 +278,7 @@     let !go = runN (A.map cos) in go xs ~~~ mapRef cos xs  test_tan-    :: (Shape sh, Similar e, P.Eq sh, P.Floating e, A.Floating e)+    :: (Shape sh, Show sh, Similar e, Show e, P.Eq sh, P.Floating e, A.Floating e)     => RunN     -> Gen sh     -> Gen e@@ -289,7 +290,7 @@     let !go = runN (A.map tan) in go xs ~~~ mapRef tan xs  test_asin-    :: (Shape sh, Similar e, P.Eq sh, P.Floating e, A.Floating e)+    :: (Shape sh, Show sh, Similar e, Show e, P.Eq sh, P.Floating e, A.Floating e)     => RunN     -> Gen sh     -> Gen e@@ -301,7 +302,7 @@     let !go = runN (A.map asin) in go xs ~~~ mapRef asin xs  test_acos-    :: (Shape sh, Similar e, P.Eq sh, P.Floating e, A.Floating e)+    :: (Shape sh, Show sh, Similar e, Show e, P.Eq sh, P.Floating e, A.Floating e)     => RunN     -> Gen sh     -> Gen e@@ -313,7 +314,7 @@     let !go = runN (A.map acos) in go xs ~~~ mapRef acos xs  test_atan-    :: (Shape sh, Similar e, P.Eq sh, P.Floating e, A.Floating e)+    :: (Shape sh, Show sh, Similar e, Show e, P.Eq sh, P.Floating e, A.Floating e)     => RunN     -> Gen sh     -> Gen e@@ -325,7 +326,7 @@     let !go = runN (A.map atan) in go xs ~~~ mapRef atan xs  test_asinh-    :: (Shape sh, Similar e, P.Eq sh, P.Floating e, A.Floating e)+    :: (Shape sh, Show sh, Similar e, Show e, P.Eq sh, P.Floating e, A.Floating e)     => RunN     -> Gen sh     -> Gen e@@ -337,7 +338,7 @@     let !go = runN (A.map asinh) in go xs ~~~ mapRef asinh xs  test_acosh-    :: (Shape sh, Similar e, P.Eq sh, P.Floating e, A.Floating e)+    :: (Shape sh, Show sh, Similar e, Show e, P.Eq sh, P.Floating e, A.Floating e)     => RunN     -> Gen sh     -> Gen e@@ -349,7 +350,7 @@     let !go = runN (A.map acosh) in go xs ~~~ mapRef acosh xs  test_atanh-    :: (Shape sh, Similar e, P.Eq sh, P.Floating e, A.Floating e)+    :: (Shape sh, Show sh, Similar e, Show e, P.Eq sh, P.Floating e, A.Floating e)     => RunN     -> Gen sh     -> Gen e@@ -361,7 +362,7 @@     let !go = runN (A.map atanh) in go xs ~~~ mapRef atanh xs  test_exp-    :: (Shape sh, Similar e, P.Eq sh, P.Floating e, A.Floating e)+    :: (Shape sh, Show sh, Similar e, Show e, P.Eq sh, P.Floating e, A.Floating e)     => RunN     -> Gen sh     -> Gen e@@ -373,7 +374,7 @@     let !go = runN (A.map exp) in go xs ~~~ mapRef exp xs  test_sqrt-    :: (Shape sh, Similar e, P.Eq sh, P.Floating e, A.Floating e)+    :: (Shape sh, Show sh, Similar e, Show e, P.Eq sh, P.Floating e, A.Floating e)     => RunN     -> Gen sh     -> Gen e@@ -385,7 +386,7 @@     let !go = runN (A.map sqrt) in go xs ~~~ mapRef sqrt xs  test_log-    :: (Shape sh, Similar e, P.Eq sh, P.Floating e, A.Floating e)+    :: (Shape sh, Show sh, Similar e, Show e, P.Eq sh, P.Floating e, A.Floating e)     => RunN     -> Gen sh     -> Gen e@@ -397,7 +398,7 @@     let !go = runN (A.map log) in go xs ~~~ mapRef log xs  test_truncate-    :: forall sh e. (Shape sh, Similar e, P.Eq sh, P.RealFrac e, A.RealFrac e)+    :: forall sh e. (Shape sh, Show sh, Show e, P.Eq sh, P.RealFrac e, A.RealFrac e)     => RunN     -> Gen sh     -> Gen e@@ -409,7 +410,7 @@     let !go = runN (A.map A.truncate) in go xs ~~~ mapRef (P.truncate :: e -> Int) xs  test_round-    :: forall sh e. (Shape sh, Similar e, P.Eq sh, P.RealFrac e, A.RealFrac e)+    :: forall sh e. (Shape sh, Show sh, Show e, P.Eq sh, P.RealFrac e, A.RealFrac e)     => RunN     -> Gen sh     -> Gen e@@ -421,7 +422,7 @@     let !go = runN (A.map A.round) in go xs ~~~ mapRef (P.round :: e -> Int) xs  test_floor-    :: forall sh e. (Shape sh, Similar e, P.Eq sh, P.RealFrac e, A.RealFrac e)+    :: forall sh e. (Shape sh, Show sh, Show e, P.Eq sh, P.RealFrac e, A.RealFrac e)     => RunN     -> Gen sh     -> Gen e@@ -433,7 +434,7 @@     let !go = runN (A.map A.floor) in go xs ~~~ mapRef (P.floor :: e -> Int) xs  test_ceiling-    :: forall sh e. (Shape sh, Similar e, P.Eq sh, P.RealFrac e, A.RealFrac e)+    :: forall sh e. (Shape sh, Show sh, Show e, P.Eq sh, P.RealFrac e, A.RealFrac e)     => RunN     -> Gen sh     -> Gen e@@ -448,34 +449,12 @@ -- Reference Implementation -- ------------------------ -mapRef :: (Shape sh, Elt b) => (a -> b) -> Array sh a -> Array sh b-mapRef f xs = fromFunction (arrayShape xs) (\ix -> f (xs Sugar.! ix))+mapRef :: (Shape sh, Elt a, Elt b) => (a -> b) -> Array sh a -> Array sh b+mapRef f xs = fromFunction (arrayShape xs) (\ix -> f (xs S.! ix))  countLeadingZerosRef :: P.FiniteBits a => a -> Int-#if __GLASGOW_HASKELL__ >= 710 countLeadingZerosRef = P.countLeadingZeros-#else-countLeadingZerosRef = clz-  where-    clz x = (w-1) - go (w-1)-      where-        go i | i < 0         = i  -- no bit set-             | P.testBit x i = i-             | otherwise     = go (i-1)-        w = P.finiteBitSize x-#endif  countTrailingZerosRef :: P.FiniteBits a => a -> Int-#if __GLASGOW_HASKELL__ >= 710 countTrailingZerosRef = P.countTrailingZeros-#else-countTrailingZerosRef = ctz-  where-    ctz x = go 0-      where-        go i | i >= w        = i-             | P.testBit x i = i-             | otherwise     = go (i+1)-        w = P.finiteBitSize x-#endif 
src/Data/Array/Accelerate/Test/NoFib/Prelude/Permute.hs view
@@ -3,13 +3,14 @@ {-# LANGUAGE FlexibleContexts    #-} {-# LANGUAGE RankNTypes          #-} {-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TypeApplications    #-} {-# LANGUAGE TypeOperators       #-} -- | -- Module      : Data.Array.Accelerate.Test.NoFib.Prelude.Permute--- Copyright   : [2009..2017] Trevor L. McDonell+-- Copyright   : [2009..2020] The Accelerate Team -- License     : BSD3 ----- Maintainer  : Trevor L. McDonell <tmcdonell@cse.unsw.edu.au>+-- Maintainer  : Trevor L. McDonell <trevor.mcdonell@gmail.com> -- Stability   : experimental -- Portability : non-portable (GHC extensions) --@@ -20,19 +21,15 @@  ) where -import Control.Monad-import Data.Proxy-import Data.Typeable-import System.IO.Unsafe-import Prelude                                                      as P-import qualified Data.Set                                           as Set- import Data.Array.Accelerate                                        as A-import Data.Array.Accelerate.Array.Sugar                            as S import Data.Array.Accelerate.Array.Data+import Data.Array.Accelerate.Sugar.Array                            as S+import Data.Array.Accelerate.Sugar.Elt                              as S+import Data.Array.Accelerate.Sugar.Shape                            as S import Data.Array.Accelerate.Test.NoFib.Base import Data.Array.Accelerate.Test.NoFib.Config import Data.Array.Accelerate.Test.Similar+import qualified Data.Array.Accelerate.Representation.Array         as R  import Hedgehog import qualified Hedgehog.Gen                                       as Gen@@ -41,40 +38,45 @@ import Test.Tasty import Test.Tasty.Hedgehog +import Control.Monad+import System.IO.Unsafe+import Prelude                                                      as P+import qualified Data.Set                                           as Set + test_permute :: RunN -> TestTree test_permute runN =   testGroup "permute"-    [ at (Proxy::Proxy TestInt8)   $ testElt i8-    , at (Proxy::Proxy TestInt16)  $ testElt i16-    , at (Proxy::Proxy TestInt32)  $ testElt i32-    , at (Proxy::Proxy TestInt64)  $ testElt i64-    , at (Proxy::Proxy TestWord8)  $ testElt w8-    , at (Proxy::Proxy TestWord16) $ testElt w16-    , at (Proxy::Proxy TestWord32) $ testElt w32-    , at (Proxy::Proxy TestWord64) $ testElt w64-    , at (Proxy::Proxy TestHalf)   $ testElt f16-    , at (Proxy::Proxy TestFloat)  $ testElt f32-    , at (Proxy::Proxy TestDouble) $ testElt f64+    [ at @TestInt8   $ testElt i8+    , at @TestInt16  $ testElt i16+    , at @TestInt32  $ testElt i32+    , at @TestInt64  $ testElt i64+    , at @TestWord8  $ testElt w8+    , at @TestWord16 $ testElt w16+    , at @TestWord32 $ testElt w32+    , at @TestWord64 $ testElt w64+    , at @TestHalf   $ testElt f16+    , at @TestFloat  $ testElt f32+    , at @TestDouble $ testElt f64     ]   where     testElt-        :: forall a. (Similar a, P.Num a, A.Num a)+        :: forall a. (Similar a, P.Num a, A.Num a, Show a)         => Gen a         -> TestTree     testElt e =-      testGroup (show (typeOf (undefined :: a)))+      testGroup (show (eltR @a))         [ testDim dim1         , testDim dim2         , testDim dim3         ]       where         testDim-            :: forall sh. (Shape sh, Slice sh, P.Eq sh)+            :: forall sh. (Shape sh, Show sh)             => Gen (sh:.Int)             -> TestTree         testDim sh =-          testGroup ("DIM" P.++ show (rank (undefined::(sh:.Int))))+          testGroup ("DIM" P.++ show (rank @(sh:.Int)))             [               testProperty "scatter->DIM1"      $ test_scatter runN sh dim1 e             , testProperty "scatter->DIM2"      $ test_scatter runN sh dim2 e@@ -86,7 +88,7 @@   test_scatter-    :: forall sh sh' e. (Shape sh, Shape sh', P.Eq sh', Similar e, Elt e)+    :: forall sh sh' e. (Shape sh, Shape sh', Show sh, Show sh', P.Eq sh', Similar e, Elt e, Show e)     => RunN     -> Gen sh     -> Gen sh'@@ -109,8 +111,8 @@               ts <- shfl (Set.insert t seen) (i+1)               --               case Set.member t seen of-                True  -> return (S.ignore          : ts)-                False -> return (S.fromIndex sh' t : ts)+                True  -> return (Nothing                  : ts)+                False -> return (Just (S.fromIndex sh' t) : ts)     --     def <- forAll (array sh' e)     new <- forAll (array sh  e)@@ -121,7 +123,7 @@   test_accumulate-    :: (Shape sh, Shape sh', P.Eq sh', Similar e, P.Num e, A.Num e)+    :: (Shape sh, Shape sh', Show sh, Show sh', P.Eq sh', Similar e, P.Num e, A.Num e, Show e)     => RunN     -> Gen sh     -> Gen sh'@@ -136,23 +138,24 @@         def = S.fromFunction sh' (const 0)     --     xs  <- forAll (array sh e)-    ix  <- forAll (array sh (Gen.choice [ return S.ignore-                                        , S.fromIndex sh' <$> Gen.int (Range.linear 0 (n'-1))+    ix  <- forAll (array sh (Gen.choice [ return Nothing+                                        , Just . S.fromIndex sh' <$> Gen.int (Range.linear 0 (n'-1))                                         ]))     let !go = runN $ \i d v -> A.permute (+) d (i A.!) v     go ix def xs ~~~ permuteRef (+) def (ix S.!) xs   permuteRef-    :: (Shape sh, Shape sh', P.Eq sh', Elt e)+    :: forall sh sh' e. (Shape sh, Shape sh', P.Eq sh', Elt e)     => (e -> e -> e)     -> Array sh' e-    -> (sh -> sh')+    -> (sh -> Maybe sh')     -> Array sh e     -> Array sh' e-permuteRef f def@(Array _ aold) p arr@(Array _ anew) =+permuteRef f def@(Array (R.Array _ aold)) p arr@(Array (R.Array _ anew)) =   unsafePerformIO $ do     let+        tp  = S.eltR @e         sh  = S.shape arr         sh' = S.shape def         n   = S.size sh@@ -161,13 +164,13 @@           | i P.>= n  = return ()           | otherwise = do               let ix  = S.fromIndex sh i-                  ix' = p ix-              ---              unless (ix' P.== S.ignore) $ do-                let i'  = S.toIndex sh' ix'-                x  <- toElt <$> unsafeReadArrayData anew i-                x' <- toElt <$> unsafeReadArrayData aold i'-                unsafeWriteArrayData aold i' (fromElt (f x x'))+              case p ix of+                Nothing  -> return ()+                Just ix' -> do+                  let i'  = S.toIndex sh' ix'+                  x  <- toElt <$> readArrayData tp anew i+                  x' <- toElt <$> readArrayData tp aold i'+                  writeArrayData tp aold i' (fromElt (f x x'))               --               go (i+1)     --
+ src/Data/Array/Accelerate/Test/NoFib/Prelude/SIMD.hs view
@@ -0,0 +1,236 @@+{-# LANGUAGE BangPatterns        #-}+{-# LANGUAGE FlexibleContexts    #-}+{-# LANGUAGE GADTs               #-}+{-# LANGUAGE RankNTypes          #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TypeApplications    #-}+-- |+-- Module      : Data.Array.Accelerate.Test.NoFib.Prelude.SIMD+-- Copyright   : [2009..2020] The Accelerate Team+-- License     : BSD3+--+-- Maintainer  : Trevor L. McDonell <trevor.mcdonell@gmail.com>+-- Stability   : experimental+-- Portability : non-portable (GHC extensions)+--++module Data.Array.Accelerate.Test.NoFib.Prelude.SIMD (++  test_simd,++) where++import Control.Lens                                                 ( view, _1, _2, _3, _4 )+import Prelude                                                      as P++import Data.Array.Accelerate                                        as A+import Data.Array.Accelerate.Sugar.Array                            as S+import Data.Array.Accelerate.Sugar.Elt                              as S+import Data.Array.Accelerate.Sugar.Shape                            as S+import Data.Array.Accelerate.Test.NoFib.Base+import Data.Array.Accelerate.Test.NoFib.Config+import Data.Primitive.Vec+import Data.Primitive.Types++import Hedgehog+import qualified Hedgehog.Gen                                       as Gen++import Test.Tasty+import Test.Tasty.Hedgehog+++test_simd :: RunN -> TestTree+test_simd runN =+  testGroup "simd"+    [ at @TestInt8   $ testElt i8+    , at @TestInt16  $ testElt i16+    , at @TestInt32  $ testElt i32+    , at @TestInt64  $ testElt i64+    , at @TestWord8  $ testElt w8+    , at @TestWord16 $ testElt w16+    , at @TestWord32 $ testElt w32+    , at @TestWord64 $ testElt w64+    , at @TestHalf   $ testElt f16+    , at @TestFloat  $ testElt f32+    , at @TestDouble $ testElt f64+    ]+  where+    testElt :: forall e. (VecElt e, P.Eq e, Show e)+            => Gen e+            -> TestTree+    testElt e =+      testGroup (show (eltR @e))+        [ testExtract e+        , testInject  e+        ]++    testExtract :: forall e. (VecElt e, P.Eq e, Show e)+                => Gen e+                -> TestTree+    testExtract e =+      testGroup "extract"+        [ testProperty "V2" $ test_extract_v2 runN dim1 e+        , testProperty "V3" $ test_extract_v3 runN dim1 e+        , testProperty "V4" $ test_extract_v4 runN dim1 e+        ]++    testInject :: forall e. (VecElt e, P.Eq e, Show e)+               => Gen e+               -> TestTree+    testInject e =+      testGroup "inject"+        [ testProperty "V2" $ test_inject_v2 runN dim1 e+        , testProperty "V3" $ test_inject_v3 runN dim1 e+        , testProperty "V4" $ test_inject_v4 runN dim1 e+        ]+++test_extract_v2+    :: (Shape sh, Show sh, Show e, VecElt e, P.Eq e, P.Eq sh)+    => RunN+    -> Gen sh+    -> Gen e+    -> Property+test_extract_v2 runN dim e =+  property $ do+    sh      <- forAll dim+    xs      <- forAll (array sh (v2 e))+    (_l,_m) <- P.snd <$> forAllWith P.fst (Gen.element [("_1",(_1,_1)), ("_2",(_2,_2))])+    let !go = runN (A.map (view _m . unpackVec2')) in go xs === mapRef (view _l . unpackVec2) xs++test_extract_v3+    :: (Shape sh, Show sh, Show e, VecElt e, P.Eq e, P.Eq sh)+    => RunN+    -> Gen sh+    -> Gen e+    -> Property+test_extract_v3 runN dim e =+  property $ do+    sh      <- forAll dim+    xs      <- forAll (array sh (v3 e))+    (_l,_m) <- P.snd <$> forAllWith P.fst (Gen.element [("_1",(_1,_1)), ("_2",(_2,_2)), ("_3",(_3,_3))])+    let !go = runN (A.map (view _m . unpackVec3')) in go xs === mapRef (view _l . unpackVec3) xs++test_extract_v4+    :: (Shape sh, Show sh, Show e, VecElt e, P.Eq e, P.Eq sh)+    => RunN+    -> Gen sh+    -> Gen e+    -> Property+test_extract_v4 runN dim e =+  property $ do+    sh      <- forAll dim+    xs      <- forAll (array sh (v4 e))+    (_l,_m) <- P.snd <$> forAllWith P.fst (Gen.element [("_1",(_1,_1)), ("_2",(_2,_2)), ("_3",(_3,_3)), ("_4",(_4,_4))])+    let !go = runN (A.map (view _m . unpackVec4')) in go xs === mapRef (view _l . unpackVec4) xs++test_inject_v2+    :: (Shape sh, Show sh, Show e, VecElt e, P.Eq e, P.Eq sh)+    => RunN+    -> Gen sh+    -> Gen e+    -> Property+test_inject_v2 runN dim e =+  property $ do+    sh1 <- forAll dim+    sh2 <- forAll dim+    xs  <- forAll (array sh1 e)+    ys  <- forAll (array sh2 e)+    let !go = runN (A.zipWith A.V2) in go xs ys === zipWithRef Vec2 xs ys++test_inject_v3+    :: (Shape sh, Show sh, Show e, VecElt e, P.Eq e, P.Eq sh)+    => RunN+    -> Gen sh+    -> Gen e+    -> Property+test_inject_v3 runN dim e =+  property $ do+    sh1 <- forAll dim+    sh2 <- forAll dim+    sh3 <- forAll dim+    xs  <- forAll (array sh1 e)+    ys  <- forAll (array sh2 e)+    zs  <- forAll (array sh3 e)+    let !go = runN (A.zipWith3 A.V3) in go xs ys zs === zipWith3Ref Vec3 xs ys zs++test_inject_v4+    :: (Shape sh, Show sh, Show e, VecElt e, P.Eq e, P.Eq sh)+    => RunN+    -> Gen sh+    -> Gen e+    -> Property+test_inject_v4 runN dim e =+  property $ do+    sh1 <- forAll dim+    sh2 <- forAll dim+    sh3 <- forAll dim+    sh4 <- forAll dim+    xs  <- forAll (array sh1 e)+    ys  <- forAll (array sh2 e)+    zs  <- forAll (array sh3 e)+    ws  <- forAll (array sh4 e)+    let !go = runN (A.zipWith4 A.V4) in go xs ys zs ws === zipWith4Ref Vec4 xs ys zs ws+++unpackVec2 :: Prim e => Vec2 e -> (e, e)+unpackVec2 (Vec2 a b) = (a, b)++unpackVec3 :: Prim e => Vec3 e -> (e, e, e)+unpackVec3 (Vec3 a b c) = (a, b, c)++unpackVec4 :: Prim e => Vec4 e -> (e, e, e, e)+unpackVec4 (Vec4 a b c d) = (a, b, c, d)++unpackVec2' :: VecElt e => Exp (Vec2 e) -> (Exp e, Exp e)+unpackVec2' (A.V2 a b) = (a, b)++unpackVec3' :: VecElt e => Exp (Vec3 e) -> (Exp e, Exp e, Exp e)+unpackVec3' (A.V3 a b c) = (a, b, c)++unpackVec4' :: VecElt e => Exp (Vec4 e) -> (Exp e, Exp e, Exp e, Exp e)+unpackVec4' (A.V4 a b c d) = (a, b, c, d)+++-- Reference Implementation+-- ------------------------++mapRef :: (Shape sh, Elt a, Elt b) => (a -> b) -> Array sh a -> Array sh b+mapRef f xs = fromFunction (arrayShape xs) (\ix -> f (xs S.! ix))++zipWithRef+    :: (Shape sh, Elt a, Elt b, Elt c)+    => (a -> b -> c)+    -> Array sh a+    -> Array sh b+    -> Array sh c+zipWithRef f xs ys =+  fromFunction+    (S.shape xs `S.intersect` S.shape ys)+    (\ix -> f (xs S.! ix) (ys S.! ix))++zipWith3Ref+    :: (Shape sh, Elt a, Elt b, Elt c, Elt d)+    => (a -> b -> c -> d)+    -> Array sh a+    -> Array sh b+    -> Array sh c+    -> Array sh d+zipWith3Ref f xs ys zs =+  fromFunction+    (S.shape xs `S.intersect` S.shape ys `S.intersect` S.shape zs)+    (\ix -> f (xs S.! ix) (ys S.! ix) (zs S.! ix))++zipWith4Ref+    :: (Shape sh, Elt a, Elt b, Elt c, Elt d, Elt e)+    => (a -> b -> c -> d -> e)+    -> Array sh a+    -> Array sh b+    -> Array sh c+    -> Array sh d+    -> Array sh e+zipWith4Ref f xs ys zs ws =+  fromFunction+    (S.shape xs `S.intersect` S.shape ys `S.intersect` S.shape zs `S.intersect` S.shape ws)+    (\ix -> f (xs S.! ix) (ys S.! ix) (zs S.! ix) (ws S.! ix))+
src/Data/Array/Accelerate/Test/NoFib/Prelude/Scan.hs view
@@ -3,13 +3,14 @@ {-# LANGUAGE FlexibleContexts    #-} {-# LANGUAGE RankNTypes          #-} {-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TypeApplications    #-} {-# LANGUAGE TypeOperators       #-} -- | -- Module      : Data.Array.Accelerate.Test.NoFib.Prelude.Scan--- Copyright   : [2009..2017] Trevor L. McDonell+-- Copyright   : [2009..2020] The Accelerate Team -- License     : BSD3 ----- Maintainer  : Trevor L. McDonell <tmcdonell@cse.unsw.edu.au>+-- Maintainer  : Trevor L. McDonell <trevor.mcdonell@gmail.com> -- Stability   : experimental -- Portability : non-portable (GHC extensions) --@@ -26,12 +27,11 @@  ) where -import Data.Proxy-import Data.Typeable import Prelude                                                      as P  import Data.Array.Accelerate                                        as A-import Data.Array.Accelerate.Array.Sugar                            as S+import Data.Array.Accelerate.Sugar.Elt                              as S+import Data.Array.Accelerate.Sugar.Shape                            as S import Data.Array.Accelerate.Test.NoFib.Base import Data.Array.Accelerate.Test.NoFib.Config import Data.Array.Accelerate.Test.Similar@@ -47,36 +47,36 @@ test_scanl :: RunN -> TestTree test_scanl runN =   testGroup "scanl"-    [ at (Proxy::Proxy TestInt8)   $ testElt i8-    , at (Proxy::Proxy TestInt16)  $ testElt i16-    , at (Proxy::Proxy TestInt32)  $ testElt i32-    , at (Proxy::Proxy TestInt64)  $ testElt i64-    , at (Proxy::Proxy TestWord8)  $ testElt w8-    , at (Proxy::Proxy TestWord16) $ testElt w16-    , at (Proxy::Proxy TestWord32) $ testElt w32-    , at (Proxy::Proxy TestWord64) $ testElt w64-    , at (Proxy::Proxy TestHalf)   $ testElt f16-    , at (Proxy::Proxy TestFloat)  $ testElt f32-    , at (Proxy::Proxy TestDouble) $ testElt f64+    [ at @TestInt8   $ testElt i8+    , at @TestInt16  $ testElt i16+    , at @TestInt32  $ testElt i32+    , at @TestInt64  $ testElt i64+    , at @TestWord8  $ testElt w8+    , at @TestWord16 $ testElt w16+    , at @TestWord32 $ testElt w32+    , at @TestWord64 $ testElt w64+    , at @TestHalf   $ testElt f16+    , at @TestFloat  $ testElt f32+    , at @TestDouble $ testElt f64     ]   where     testElt-        :: forall a. (P.Num a, P.Ord a , A.Num a, A.Ord a , Similar a)+        :: forall a. (P.Num a, P.Eq a, A.Num a, A.Eq a, Similar a, Show a)         => Gen a         -> TestTree     testElt e =-      testGroup (show (typeOf (undefined :: a)))+      testGroup (show (eltR @a))         [ testDim dim1         , testDim dim2         , testDim dim3         ]       where         testDim-            :: forall sh. (Shape sh, P.Eq sh)+            :: forall sh. (Shape sh, Show sh, P.Eq sh)             => Gen (sh:.Int)             -> TestTree         testDim sh =-          testGroup ("DIM" P.++ show (rank (undefined::(sh:.Int))))+          testGroup ("DIM" P.++ show (rank @(sh:.Int)))             [ testProperty "sum"              $ test_scanl_sum runN sh (return 0) e             , testProperty "non-neutral sum"  $ test_scanl_sum runN sh e e             , testProperty "non-commutative"  $ test_scanl_interval runN sh e@@ -85,34 +85,34 @@ test_scanl1 :: RunN -> TestTree test_scanl1 runN =   testGroup "scanl1"-    [ at (Proxy::Proxy TestInt8)   $ testElt i8-    , at (Proxy::Proxy TestInt16)  $ testElt i16-    , at (Proxy::Proxy TestInt32)  $ testElt i32-    , at (Proxy::Proxy TestInt64)  $ testElt i64-    , at (Proxy::Proxy TestWord8)  $ testElt w8-    , at (Proxy::Proxy TestWord16) $ testElt w16-    , at (Proxy::Proxy TestWord32) $ testElt w32-    , at (Proxy::Proxy TestWord64) $ testElt w64-    , at (Proxy::Proxy TestFloat)  $ testElt f32-    , at (Proxy::Proxy TestDouble) $ testElt f64+    [ at @TestInt8   $ testElt i8+    , at @TestInt16  $ testElt i16+    , at @TestInt32  $ testElt i32+    , at @TestInt64  $ testElt i64+    , at @TestWord8  $ testElt w8+    , at @TestWord16 $ testElt w16+    , at @TestWord32 $ testElt w32+    , at @TestWord64 $ testElt w64+    , at @TestFloat  $ testElt f32+    , at @TestDouble $ testElt f64     ]   where-    testElt :: forall a. (P.Num a, P.Ord a , A.Num a, A.Ord a , Similar a)+    testElt :: forall a. (P.Num a, P.Eq a, A.Num a, A.Eq a, Similar a, Show a)         => Gen a         -> TestTree     testElt e =-      testGroup (show (typeOf (undefined :: a)))+      testGroup (show (eltR @a))         [ testDim dim1         , testDim dim2         , testDim dim3         ]       where         testDim-            :: forall sh. (Shape sh, P.Eq sh)+            :: forall sh. (Shape sh, Show sh, P.Eq sh)             => Gen (sh:.Int)             -> TestTree         testDim sh =-          testGroup ("DIM" P.++ show (rank (undefined::(sh:.Int))))+          testGroup ("DIM" P.++ show (rank @(sh:.Int)))             [ testProperty "sum"              $ test_scanl1_sum runN sh e             , testProperty "non-commutative"  $ test_scanl1_interval runN sh e             ]@@ -120,34 +120,34 @@ test_scanl' :: RunN -> TestTree test_scanl' runN =   testGroup "scanl'"-    [ at (Proxy::Proxy TestInt8)   $ testElt i8-    , at (Proxy::Proxy TestInt16)  $ testElt i16-    , at (Proxy::Proxy TestInt32)  $ testElt i32-    , at (Proxy::Proxy TestInt64)  $ testElt i64-    , at (Proxy::Proxy TestWord8)  $ testElt w8-    , at (Proxy::Proxy TestWord16) $ testElt w16-    , at (Proxy::Proxy TestWord32) $ testElt w32-    , at (Proxy::Proxy TestWord64) $ testElt w64-    , at (Proxy::Proxy TestFloat)  $ testElt f32-    , at (Proxy::Proxy TestDouble) $ testElt f64+    [ at @TestInt8   $ testElt i8+    , at @TestInt16  $ testElt i16+    , at @TestInt32  $ testElt i32+    , at @TestInt64  $ testElt i64+    , at @TestWord8  $ testElt w8+    , at @TestWord16 $ testElt w16+    , at @TestWord32 $ testElt w32+    , at @TestWord64 $ testElt w64+    , at @TestFloat  $ testElt f32+    , at @TestDouble $ testElt f64     ]   where-    testElt :: forall a. (P.Num a, P.Ord a , A.Num a, A.Ord a , Similar a)+    testElt :: forall a. (P.Num a, P.Eq a, A.Num a, A.Eq a, Similar a, Show a)         => Gen a         -> TestTree     testElt e =-      testGroup (show (typeOf (undefined :: a)))+      testGroup (show (eltR @a))         [ testDim dim1         , testDim dim2         , testDim dim3         ]       where         testDim-            :: forall sh. (Shape sh, P.Eq sh)+            :: forall sh. (Shape sh, Show sh, P.Eq sh)             => Gen (sh:.Int)             -> TestTree         testDim sh =-          testGroup ("DIM" P.++ show (rank (undefined::(sh:.Int))))+          testGroup ("DIM" P.++ show (rank @(sh:.Int)))             [ testProperty "sum"              $ test_scanl'_sum runN sh (return 0) e             , testProperty "non-neutral sum"  $ test_scanl'_sum runN sh e e             , testProperty "non-commutative"  $ test_scanl'_interval runN sh e@@ -156,34 +156,34 @@ test_scanr :: RunN -> TestTree test_scanr runN =   testGroup "scanr"-    [ at (Proxy::Proxy TestInt8)   $ testElt i8-    , at (Proxy::Proxy TestInt16)  $ testElt i16-    , at (Proxy::Proxy TestInt32)  $ testElt i32-    , at (Proxy::Proxy TestInt64)  $ testElt i64-    , at (Proxy::Proxy TestWord8)  $ testElt w8-    , at (Proxy::Proxy TestWord16) $ testElt w16-    , at (Proxy::Proxy TestWord32) $ testElt w32-    , at (Proxy::Proxy TestWord64) $ testElt w64-    , at (Proxy::Proxy TestFloat)  $ testElt f32-    , at (Proxy::Proxy TestDouble) $ testElt f64+    [ at @TestInt8   $ testElt i8+    , at @TestInt16  $ testElt i16+    , at @TestInt32  $ testElt i32+    , at @TestInt64  $ testElt i64+    , at @TestWord8  $ testElt w8+    , at @TestWord16 $ testElt w16+    , at @TestWord32 $ testElt w32+    , at @TestWord64 $ testElt w64+    , at @TestFloat  $ testElt f32+    , at @TestDouble $ testElt f64     ]   where-    testElt :: forall a. (P.Num a, P.Ord a , A.Num a, A.Ord a , Similar a)+    testElt :: forall a. (P.Num a, P.Eq a, A.Num a, A.Eq a, Similar a, Show a)         => Gen a         -> TestTree     testElt e =-      testGroup (show (typeOf (undefined :: a)))+      testGroup (show (eltR @a))         [ testDim dim1         , testDim dim2         , testDim dim3         ]       where         testDim-            :: forall sh. (Shape sh, P.Eq sh)+            :: forall sh. (Shape sh, Show sh, P.Eq sh)             => Gen (sh:.Int)             -> TestTree         testDim sh =-          testGroup ("DIM" P.++ show (rank (undefined::(sh:.Int))))+          testGroup ("DIM" P.++ show (rank @(sh:.Int)))             [ testProperty "sum"              $ test_scanr_sum runN sh (return 0) e             , testProperty "non-neutral sum"  $ test_scanr_sum runN sh e e             , testProperty "non-commutative"  $ test_scanr_interval runN sh e@@ -192,34 +192,34 @@ test_scanr1 :: RunN -> TestTree test_scanr1 runN =   testGroup "scanr1"-    [ at (Proxy::Proxy TestInt8)   $ testElt i8-    , at (Proxy::Proxy TestInt16)  $ testElt i16-    , at (Proxy::Proxy TestInt32)  $ testElt i32-    , at (Proxy::Proxy TestInt64)  $ testElt i64-    , at (Proxy::Proxy TestWord8)  $ testElt w8-    , at (Proxy::Proxy TestWord16) $ testElt w16-    , at (Proxy::Proxy TestWord32) $ testElt w32-    , at (Proxy::Proxy TestWord64) $ testElt w64-    , at (Proxy::Proxy TestFloat)  $ testElt f32-    , at (Proxy::Proxy TestDouble) $ testElt f64+    [ at @TestInt8   $ testElt i8+    , at @TestInt16  $ testElt i16+    , at @TestInt32  $ testElt i32+    , at @TestInt64  $ testElt i64+    , at @TestWord8  $ testElt w8+    , at @TestWord16 $ testElt w16+    , at @TestWord32 $ testElt w32+    , at @TestWord64 $ testElt w64+    , at @TestFloat  $ testElt f32+    , at @TestDouble $ testElt f64     ]   where-    testElt :: forall a. (P.Num a, P.Ord a , A.Num a, A.Ord a , Similar a)+    testElt :: forall a. (P.Num a, P.Eq a, A.Num a, A.Eq a, Similar a, Show a)         => Gen a         -> TestTree     testElt e =-      testGroup (show (typeOf (undefined :: a)))+      testGroup (show (eltR @a))         [ testDim dim1         , testDim dim2         , testDim dim3         ]       where         testDim-            :: forall sh. (Shape sh, P.Eq sh)+            :: forall sh. (Shape sh, Show sh, P.Eq sh)             => Gen (sh:.Int)             -> TestTree         testDim sh =-          testGroup ("DIM" P.++ show (rank (undefined::(sh:.Int))))+          testGroup ("DIM" P.++ show (rank @(sh:.Int)))             [ testProperty "sum"              $ test_scanr1_sum runN sh e             , testProperty "non-commutative"  $ test_scanr1_interval runN sh e             ]@@ -227,34 +227,34 @@ test_scanr' :: RunN -> TestTree test_scanr' runN =   testGroup "scanr'"-    [ at (Proxy::Proxy TestInt8)   $ testElt i8-    , at (Proxy::Proxy TestInt16)  $ testElt i16-    , at (Proxy::Proxy TestInt32)  $ testElt i32-    , at (Proxy::Proxy TestInt64)  $ testElt i64-    , at (Proxy::Proxy TestWord8)  $ testElt w8-    , at (Proxy::Proxy TestWord16) $ testElt w16-    , at (Proxy::Proxy TestWord32) $ testElt w32-    , at (Proxy::Proxy TestWord64) $ testElt w64-    , at (Proxy::Proxy TestFloat)  $ testElt f32-    , at (Proxy::Proxy TestDouble) $ testElt f64+    [ at @TestInt8   $ testElt i8+    , at @TestInt16  $ testElt i16+    , at @TestInt32  $ testElt i32+    , at @TestInt64  $ testElt i64+    , at @TestWord8  $ testElt w8+    , at @TestWord16 $ testElt w16+    , at @TestWord32 $ testElt w32+    , at @TestWord64 $ testElt w64+    , at @TestFloat  $ testElt f32+    , at @TestDouble $ testElt f64     ]   where-    testElt :: forall a. (P.Num a, P.Ord a , A.Num a, A.Ord a , Similar a)+    testElt :: forall a. (P.Num a, P.Eq a, A.Num a, A.Eq a, Similar a, Show a)         => Gen a         -> TestTree     testElt e =-      testGroup (show (typeOf (undefined :: a)))+      testGroup (show (eltR @a))         [ testDim dim1         , testDim dim2         , testDim dim3         ]       where         testDim-            :: forall sh. (Shape sh, P.Eq sh)+            :: forall sh. (Shape sh, Show sh, P.Eq sh)             => Gen (sh:.Int)             -> TestTree         testDim sh =-          testGroup ("DIM" P.++ show (rank (undefined::(sh:.Int))))+          testGroup ("DIM" P.++ show (rank @(sh:.Int)))             [ testProperty "sum"              $ test_scanr'_sum runN sh (return 0) e             , testProperty "non-neutral sum"  $ test_scanr'_sum runN sh e e             , testProperty "non-commutative"  $ test_scanr'_interval runN sh e@@ -263,34 +263,34 @@ test_scanlSeg :: RunN -> TestTree test_scanlSeg runN =   testGroup "scanlSeg"-    [ at (Proxy::Proxy TestInt8)   $ testElt i8-    , at (Proxy::Proxy TestInt16)  $ testElt i16-    , at (Proxy::Proxy TestInt32)  $ testElt i32-    , at (Proxy::Proxy TestInt64)  $ testElt i64-    , at (Proxy::Proxy TestWord8)  $ testElt w8-    , at (Proxy::Proxy TestWord16) $ testElt w16-    , at (Proxy::Proxy TestWord32) $ testElt w32-    , at (Proxy::Proxy TestWord64) $ testElt w64-    , at (Proxy::Proxy TestFloat)  $ testElt f32-    , at (Proxy::Proxy TestDouble) $ testElt f64+    [ at @TestInt8   $ testElt i8+    , at @TestInt16  $ testElt i16+    , at @TestInt32  $ testElt i32+    , at @TestInt64  $ testElt i64+    , at @TestWord8  $ testElt w8+    , at @TestWord16 $ testElt w16+    , at @TestWord32 $ testElt w32+    , at @TestWord64 $ testElt w64+    , at @TestFloat  $ testElt f32+    , at @TestDouble $ testElt f64     ]   where-    testElt :: forall a. (P.Num a, P.Ord a , A.Num a, A.Ord a , Similar a)+    testElt :: forall a. (P.Num a, A.Num a, Similar a, Show a)         => Gen a         -> TestTree     testElt e =-      testGroup (show (typeOf (undefined :: a)))+      testGroup (show (eltR @a))         [ testDim dim1         , testDim dim2         , testDim dim3         ]       where         testDim-            :: forall sh. (Shape sh, Slice sh, P.Eq sh)+            :: forall sh. (Shape sh, Slice sh, Show sh, P.Eq sh)             => Gen (sh:.Int)             -> TestTree         testDim sh =-          testGroup ("DIM" P.++ show (rank (undefined::(sh:.Int))))+          testGroup ("DIM" P.++ show (rank @(sh:.Int)))             [ testProperty "sum"              $ test_scanlSeg_sum runN sh (return 0) e             , testProperty "non-neutral sum"  $ test_scanlSeg_sum runN sh e e             ]@@ -298,68 +298,68 @@ test_scanl1Seg :: RunN -> TestTree test_scanl1Seg runN =   testGroup "scanl1Seg"-    [ at (Proxy::Proxy TestInt8)   $ testElt i8-    , at (Proxy::Proxy TestInt16)  $ testElt i16-    , at (Proxy::Proxy TestInt32)  $ testElt i32-    , at (Proxy::Proxy TestInt64)  $ testElt i64-    , at (Proxy::Proxy TestWord8)  $ testElt w8-    , at (Proxy::Proxy TestWord16) $ testElt w16-    , at (Proxy::Proxy TestWord32) $ testElt w32-    , at (Proxy::Proxy TestWord64) $ testElt w64-    , at (Proxy::Proxy TestFloat)  $ testElt f32-    , at (Proxy::Proxy TestDouble) $ testElt f64+    [ at @TestInt8   $ testElt i8+    , at @TestInt16  $ testElt i16+    , at @TestInt32  $ testElt i32+    , at @TestInt64  $ testElt i64+    , at @TestWord8  $ testElt w8+    , at @TestWord16 $ testElt w16+    , at @TestWord32 $ testElt w32+    , at @TestWord64 $ testElt w64+    , at @TestFloat  $ testElt f32+    , at @TestDouble $ testElt f64     ]   where-    testElt :: forall a. (P.Num a, P.Ord a , A.Num a, A.Ord a , Similar a)+    testElt :: forall a. (P.Num a, A.Num a, Similar a, Show a)         => Gen a         -> TestTree     testElt e =-      testGroup (show (typeOf (undefined :: a)))+      testGroup (show (eltR @a))         [ testDim dim1         , testDim dim2         , testDim dim3         ]       where         testDim-            :: forall sh. (Shape sh, Slice sh, P.Eq sh)+            :: forall sh. (Shape sh, Slice sh, Show sh, P.Eq sh)             => Gen (sh:.Int)             -> TestTree         testDim sh =-          testGroup ("DIM" P.++ show (rank (undefined::(sh:.Int))))+          testGroup ("DIM" P.++ show (rank @(sh:.Int)))             [ testProperty "sum"  $ test_scanl1Seg_sum runN sh e             ]  test_scanl'Seg :: RunN -> TestTree test_scanl'Seg runN =   testGroup "scanl'Seg"-    [ at (Proxy::Proxy TestInt8)   $ testElt i8-    , at (Proxy::Proxy TestInt16)  $ testElt i16-    , at (Proxy::Proxy TestInt32)  $ testElt i32-    , at (Proxy::Proxy TestInt64)  $ testElt i64-    , at (Proxy::Proxy TestWord8)  $ testElt w8-    , at (Proxy::Proxy TestWord16) $ testElt w16-    , at (Proxy::Proxy TestWord32) $ testElt w32-    , at (Proxy::Proxy TestWord64) $ testElt w64-    , at (Proxy::Proxy TestFloat)  $ testElt f32-    , at (Proxy::Proxy TestDouble) $ testElt f64+    [ at @TestInt8   $ testElt i8+    , at @TestInt16  $ testElt i16+    , at @TestInt32  $ testElt i32+    , at @TestInt64  $ testElt i64+    , at @TestWord8  $ testElt w8+    , at @TestWord16 $ testElt w16+    , at @TestWord32 $ testElt w32+    , at @TestWord64 $ testElt w64+    , at @TestFloat  $ testElt f32+    , at @TestDouble $ testElt f64     ]   where-    testElt :: forall a. (P.Num a, P.Ord a , A.Num a, A.Ord a , Similar a)+    testElt :: forall a. (P.Num a, A.Num a, Similar a, Show a)         => Gen a         -> TestTree     testElt e =-      testGroup (show (typeOf (undefined :: a)))+      testGroup (show (eltR @a))         [ testDim dim1         , testDim dim2         , testDim dim3         ]       where         testDim-            :: forall sh. (Shape sh, Slice sh, P.Eq sh)+            :: forall sh. (Shape sh, Slice sh, Show sh, P.Eq sh)             => Gen (sh:.Int)             -> TestTree         testDim sh =-          testGroup ("DIM" P.++ show (rank (undefined::(sh:.Int))))+          testGroup ("DIM" P.++ show (rank @(sh:.Int)))             [ testProperty "sum"              $ test_scanl'Seg_sum runN sh (return 0) e             , testProperty "non-neutral sum"  $ test_scanl'Seg_sum runN sh e e             ]@@ -367,34 +367,34 @@ test_scanrSeg :: RunN -> TestTree test_scanrSeg runN =   testGroup "scanrSeg"-    [ at (Proxy::Proxy TestInt8)   $ testElt i8-    , at (Proxy::Proxy TestInt16)  $ testElt i16-    , at (Proxy::Proxy TestInt32)  $ testElt i32-    , at (Proxy::Proxy TestInt64)  $ testElt i64-    , at (Proxy::Proxy TestWord8)  $ testElt w8-    , at (Proxy::Proxy TestWord16) $ testElt w16-    , at (Proxy::Proxy TestWord32) $ testElt w32-    , at (Proxy::Proxy TestWord64) $ testElt w64-    , at (Proxy::Proxy TestFloat)  $ testElt f32-    , at (Proxy::Proxy TestDouble) $ testElt f64+    [ at @TestInt8   $ testElt i8+    , at @TestInt16  $ testElt i16+    , at @TestInt32  $ testElt i32+    , at @TestInt64  $ testElt i64+    , at @TestWord8  $ testElt w8+    , at @TestWord16 $ testElt w16+    , at @TestWord32 $ testElt w32+    , at @TestWord64 $ testElt w64+    , at @TestFloat  $ testElt f32+    , at @TestDouble $ testElt f64     ]   where-    testElt :: forall a. (P.Num a, P.Ord a , A.Num a, A.Ord a , Similar a)+    testElt :: forall a. (P.Num a, A.Num a, Similar a, Show a)         => Gen a         -> TestTree     testElt e =-      testGroup (show (typeOf (undefined :: a)))+      testGroup (show (eltR @a))         [ testDim dim1         , testDim dim2         , testDim dim3         ]       where         testDim-            :: forall sh. (Shape sh, Slice sh, P.Eq sh)+            :: forall sh. (Shape sh, Slice sh, Show sh, P.Eq sh)             => Gen (sh:.Int)             -> TestTree         testDim sh =-          testGroup ("DIM" P.++ show (rank (undefined::(sh:.Int))))+          testGroup ("DIM" P.++ show (rank @(sh:.Int)))             [ testProperty "sum"              $ test_scanrSeg_sum runN sh (return 0) e             , testProperty "non-neutral sum"  $ test_scanrSeg_sum runN sh e e             ]@@ -402,68 +402,68 @@ test_scanr1Seg :: RunN -> TestTree test_scanr1Seg runN =   testGroup "scanr1Seg"-    [ at (Proxy::Proxy TestInt8)   $ testElt i8-    , at (Proxy::Proxy TestInt16)  $ testElt i16-    , at (Proxy::Proxy TestInt32)  $ testElt i32-    , at (Proxy::Proxy TestInt64)  $ testElt i64-    , at (Proxy::Proxy TestWord8)  $ testElt w8-    , at (Proxy::Proxy TestWord16) $ testElt w16-    , at (Proxy::Proxy TestWord32) $ testElt w32-    , at (Proxy::Proxy TestWord64) $ testElt w64-    , at (Proxy::Proxy TestFloat)  $ testElt f32-    , at (Proxy::Proxy TestDouble) $ testElt f64+    [ at @TestInt8   $ testElt i8+    , at @TestInt16  $ testElt i16+    , at @TestInt32  $ testElt i32+    , at @TestInt64  $ testElt i64+    , at @TestWord8  $ testElt w8+    , at @TestWord16 $ testElt w16+    , at @TestWord32 $ testElt w32+    , at @TestWord64 $ testElt w64+    , at @TestFloat  $ testElt f32+    , at @TestDouble $ testElt f64     ]   where-    testElt :: forall a. (P.Num a, P.Ord a , A.Num a, A.Ord a , Similar a)+    testElt :: forall a. (P.Num a, A.Num a, Similar a, Show a)         => Gen a         -> TestTree     testElt e =-      testGroup (show (typeOf (undefined :: a)))+      testGroup (show (eltR @a))         [ testDim dim1         , testDim dim2         , testDim dim3         ]       where         testDim-            :: forall sh. (Shape sh, Slice sh, P.Eq sh)+            :: forall sh. (Shape sh, Slice sh, Show sh, P.Eq sh)             => Gen (sh:.Int)             -> TestTree         testDim sh =-          testGroup ("DIM" P.++ show (rank (undefined::(sh:.Int))))+          testGroup ("DIM" P.++ show (rank @(sh:.Int)))             [ testProperty "sum"  $ test_scanr1Seg_sum runN sh e             ]  test_scanr'Seg :: RunN -> TestTree test_scanr'Seg runN =   testGroup "scanr'Seg"-    [ at (Proxy::Proxy TestInt8)   $ testElt i8-    , at (Proxy::Proxy TestInt16)  $ testElt i16-    , at (Proxy::Proxy TestInt32)  $ testElt i32-    , at (Proxy::Proxy TestInt64)  $ testElt i64-    , at (Proxy::Proxy TestWord8)  $ testElt w8-    , at (Proxy::Proxy TestWord16) $ testElt w16-    , at (Proxy::Proxy TestWord32) $ testElt w32-    , at (Proxy::Proxy TestWord64) $ testElt w64-    , at (Proxy::Proxy TestFloat)  $ testElt f32-    , at (Proxy::Proxy TestDouble) $ testElt f64+    [ at @TestInt8   $ testElt i8+    , at @TestInt16  $ testElt i16+    , at @TestInt32  $ testElt i32+    , at @TestInt64  $ testElt i64+    , at @TestWord8  $ testElt w8+    , at @TestWord16 $ testElt w16+    , at @TestWord32 $ testElt w32+    , at @TestWord64 $ testElt w64+    , at @TestFloat  $ testElt f32+    , at @TestDouble $ testElt f64     ]   where-    testElt :: forall a. (P.Num a, P.Ord a , A.Num a, A.Ord a , Similar a)+    testElt :: forall a. (P.Num a, A.Num a, Similar a, Show a)         => Gen a         -> TestTree     testElt e =-      testGroup (show (typeOf (undefined :: a)))+      testGroup (show (eltR @a))         [ testDim dim1         , testDim dim2         , testDim dim3         ]       where         testDim-            :: forall sh. (Shape sh, Slice sh, P.Eq sh)+            :: forall sh. (Shape sh, Slice sh, Show sh, P.Eq sh)             => Gen (sh:.Int)             -> TestTree         testDim sh =-          testGroup ("DIM" P.++ show (rank (undefined::(sh:.Int))))+          testGroup ("DIM" P.++ show (rank @(sh:.Int)))             [ testProperty "sum"              $ test_scanr'Seg_sum runN sh (return 0) e             , testProperty "non-neutral sum"  $ test_scanr'Seg_sum runN sh e e             ]@@ -473,7 +473,7 @@ scalar x = fromFunction Z (const x)  test_scanl_sum-    :: (Shape sh, Similar e, P.Eq sh, P.Num e, A.Num e)+    :: (Shape sh, Show sh, Similar e, P.Eq sh, P.Num e, A.Num e, Show e)     => RunN     -> Gen (sh:.Int)     -> Gen e@@ -487,7 +487,7 @@     let !go = runN (\v -> A.scanl (+) (the v)) in go (scalar x) arr ~~~ scanlRef (+) x arr  test_scanl1_sum-    :: (Shape sh, Similar e, P.Eq sh, P.Num e, A.Num e)+    :: (Shape sh, Show sh, Similar e, P.Eq sh, P.Num e, A.Num e, Show e)     => RunN     -> Gen (sh:.Int)     -> Gen e@@ -499,7 +499,7 @@     let !go = runN (A.scanl1 (+)) in go arr ~~~ scanl1Ref (+) arr  test_scanl'_sum-    :: (Shape sh, Similar e, P.Eq sh, P.Num e, A.Num e)+    :: (Shape sh, Show sh, Similar e, P.Eq sh, P.Num e, A.Num e, Show e)     => RunN     -> Gen (sh:.Int)     -> Gen e@@ -513,7 +513,7 @@     let !go = runN (\v -> A.scanl' (+) (the v)) in go (scalar x) arr ~~~ scanl'Ref (+) x arr  test_scanr_sum-    :: (Shape sh, Similar e, P.Eq sh, P.Num e, A.Num e)+    :: (Shape sh, Show sh, Similar e, P.Eq sh, P.Num e, A.Num e, Show e)     => RunN     -> Gen (sh:.Int)     -> Gen e@@ -526,7 +526,7 @@     let !go = runN (\v -> A.scanr (+) (the v)) in go (scalar x) arr ~~~ scanrRef (+) x arr  test_scanr1_sum-    :: (Shape sh, Similar e, P.Eq sh, P.Num e, A.Num e)+    :: (Shape sh, Show sh, Similar e, P.Eq sh, P.Num e, A.Num e, Show e)     => RunN     -> Gen (sh:.Int)     -> Gen e@@ -538,7 +538,7 @@     let !go = runN (A.scanr1 (+)) in go arr ~~~ scanr1Ref (+) arr  test_scanr'_sum-    :: (Shape sh, Similar e, P.Eq sh, P.Num e, A.Num e)+    :: (Shape sh, Show sh, Similar e, P.Eq sh, P.Num e, A.Num e, Show e)     => RunN     -> Gen (sh:.Int)     -> Gen e@@ -552,7 +552,7 @@     let !go = runN (\v -> A.scanr' (+) (the v)) in go (scalar x) arr ~~~ scanr'Ref (+) x arr  test_scanl_interval-    :: (Shape sh, Similar e, P.Eq sh, P.Eq e, P.Num e, A.Eq e, A.Num e)+    :: (Shape sh, Show sh, Similar e, P.Eq sh, P.Eq e, P.Num e, A.Eq e, A.Num e, Show e)     => RunN     -> Gen (sh:.Int)     -> Gen e@@ -564,7 +564,7 @@     let !go = runN (A.scanl iappend (constant one)) in go arr ~~~ scanlRef iappendRef one arr  test_scanl1_interval-    :: (Shape sh, Similar e, P.Eq sh, P.Eq e, P.Num e, A.Eq e, A.Num e)+    :: (Shape sh, Show sh, Similar e, P.Eq sh, P.Eq e, P.Num e, A.Eq e, A.Num e, Show e)     => RunN     -> Gen (sh:.Int)     -> Gen e@@ -576,7 +576,7 @@     let !go = runN (A.scanl1 iappend) in go arr ~~~ scanl1Ref iappendRef arr  test_scanl'_interval-    :: (Shape sh, Similar e, P.Eq sh, P.Eq e, P.Num e, A.Eq e, A.Num e)+    :: (Shape sh, Show sh, Similar e, P.Eq sh, P.Eq e, P.Num e, A.Eq e, A.Num e, Show e)     => RunN     -> Gen (sh:.Int)     -> Gen e@@ -588,7 +588,7 @@     let !go = runN (A.scanl' iappend (constant one)) in go arr ~~~ scanl'Ref iappendRef one arr  test_scanr_interval-    :: (Shape sh, Similar e, P.Eq sh, P.Eq e, P.Num e, A.Eq e, A.Num e)+    :: (Shape sh, Show sh, Similar e, P.Eq sh, P.Eq e, P.Num e, A.Eq e, A.Num e, Show e)     => RunN     -> Gen (sh:.Int)     -> Gen e@@ -600,7 +600,7 @@     let !go = runN (A.scanr iappend (constant one)) in go arr ~~~ scanrRef iappendRef one arr  test_scanr1_interval-    :: (Shape sh, Similar e, P.Eq sh, P.Eq e, P.Num e, A.Eq e, A.Num e)+    :: (Shape sh, Show sh, Similar e, P.Eq sh, P.Eq e, P.Num e, A.Eq e, A.Num e, Show e)     => RunN     -> Gen (sh:.Int)     -> Gen e@@ -612,7 +612,7 @@     let !go = runN (A.scanr1 iappend) in go arr ~~~ scanr1Ref iappendRef arr  test_scanr'_interval-    :: (Shape sh, Similar e, P.Eq sh, P.Eq e, P.Num e, A.Eq e, A.Num e)+    :: (Shape sh, Show sh, Similar e, P.Eq sh, P.Eq e, P.Num e, A.Eq e, A.Num e, Show e)     => RunN     -> Gen (sh:.Int)     -> Gen e@@ -624,7 +624,7 @@     let !go = runN (A.scanr' iappend (constant one)) in go arr ~~~ scanr'Ref iappendRef one arr  test_scanlSeg_sum-    :: forall sh e. (Shape sh, Slice sh, Similar e, P.Eq sh, P.Num e, A.Num e)+    :: forall sh e. (Shape sh, Slice sh, Show sh, Similar e, P.Eq sh, P.Num e, A.Num e, Show e)     => RunN     -> Gen (sh:.Int)     -> Gen e@@ -636,12 +636,12 @@     sh:.n1  <- forAll dim     n2      <- forAll (Gen.int (Range.linear 0 64))     n       <- return (P.min n1 n2) -- don't generate too many segments-    seg     <- forAll (array (Z:.n) (Gen.int (Range.linear 0 (128 `quot` 2 P.^ (rank (undefined::sh))))))+    seg     <- forAll (array (Z:.n) (Gen.int (Range.linear 0 (128 `quot` 2 P.^ (rank @sh)))))     arr     <- forAll (array (sh:.P.sum (toList seg)) e)     let !go = runN (\v -> A.scanlSeg (+) (the v)) in go (scalar x) arr seg ~~~ scanlSegRef (+) x arr seg  test_scanl1Seg_sum-    :: forall sh e. (Shape sh, Slice sh, Similar e, P.Eq sh, P.Num e, A.Num e)+    :: forall sh e. (Shape sh, Slice sh, Show sh, Similar e, P.Eq sh, P.Num e, A.Num e, Show e)     => RunN     -> Gen (sh:.Int)     -> Gen e@@ -651,12 +651,12 @@     sh:.n1  <- forAll (dim `except` \v -> S.size v P.== 0)     n2      <- forAll (Gen.int (Range.linear 1 64))     n       <- return (P.min n1 n2) -- don't generate too many segments-    seg     <- forAll (array (Z:.n) (Gen.int (Range.linear 1 (128 `quot` 2 P.^ (rank (undefined::sh))))))+    seg     <- forAll (array (Z:.n) (Gen.int (Range.linear 1 (128 `quot` 2 P.^ (rank @sh)))))     arr     <- forAll (array (sh:.P.sum (toList seg)) e)     let !go = runN (A.scanl1Seg (+)) in go arr seg ~~~ scanl1SegRef (+) arr seg  test_scanl'Seg_sum-    :: forall sh e. (Shape sh, Slice sh, Similar e, P.Eq sh, P.Num e, A.Num e)+    :: forall sh e. (Shape sh, Slice sh, Show sh, Similar e, P.Eq sh, P.Num e, A.Num e, Show e)     => RunN     -> Gen (sh:.Int)     -> Gen e@@ -668,12 +668,12 @@     sh:.n1  <- forAll dim     n2      <- forAll (Gen.int (Range.linear 0 64))     n       <- return (P.min n1 n2) -- don't generate too many segments-    seg     <- forAll (array (Z:.n) (Gen.int (Range.linear 0 (128 `quot` 2 P.^ (rank (undefined::sh))))))+    seg     <- forAll (array (Z:.n) (Gen.int (Range.linear 0 (128 `quot` 2 P.^ (rank @sh)))))     arr     <- forAll (array (sh:.P.sum (toList seg)) e)     let !go = runN (\v -> A.scanl'Seg (+) (the v)) in go (scalar x) arr seg ~~~ scanl'SegRef (+) x arr seg  test_scanrSeg_sum-    :: forall sh e. (Shape sh, Slice sh, Similar e, P.Eq sh, P.Num e, A.Num e)+    :: forall sh e. (Shape sh, Slice sh, Show sh, Similar e, P.Eq sh, P.Num e, A.Num e, Show e)     => RunN     -> Gen (sh:.Int)     -> Gen e@@ -685,12 +685,12 @@     sh:.n1  <- forAll dim     n2      <- forAll (Gen.int (Range.linear 0 64))     n       <- return (P.min n1 n2) -- don't generate too many segments-    seg     <- forAll (array (Z:.n) (Gen.int (Range.linear 0 (128 `quot` 2 P.^ (rank (undefined::sh))))))+    seg     <- forAll (array (Z:.n) (Gen.int (Range.linear 0 (128 `quot` 2 P.^ (rank @sh)))))     arr     <- forAll (array (sh:.P.sum (toList seg)) e)     let !go = runN (\v -> A.scanrSeg (+) (the v)) in go (scalar x) arr seg ~~~ scanrSegRef (+) x arr seg  test_scanr1Seg_sum-    :: forall sh e. (Shape sh, Slice sh, Similar e, P.Eq sh, P.Num e, A.Num e)+    :: forall sh e. (Shape sh, Slice sh, Show sh, Similar e, P.Eq sh, P.Num e, A.Num e, Show e)     => RunN     -> Gen (sh:.Int)     -> Gen e@@ -700,12 +700,12 @@     sh:.n1  <- forAll (dim `except` \v -> S.size v P.== 0)     n2      <- forAll (Gen.int (Range.linear 1 64))     n       <- return (P.min n1 n2) -- don't generate too many segments-    seg     <- forAll (array (Z:.n) (Gen.int (Range.linear 1 (128 `quot` 2 P.^ (rank (undefined::sh))))))+    seg     <- forAll (array (Z:.n) (Gen.int (Range.linear 1 (128 `quot` 2 P.^ (rank @sh)))))     arr     <- forAll (array (sh:.P.sum (toList seg)) e)     let !go = runN (A.scanr1Seg (+)) in go arr seg ~~~ scanr1SegRef (+) arr seg  test_scanr'Seg_sum-    :: forall sh e. (Shape sh, Slice sh, Similar e, P.Eq sh, P.Num e, A.Num e)+    :: forall sh e. (Shape sh, Slice sh, Show sh, Similar e, P.Eq sh, P.Num e, A.Num e, Show e)     => RunN     -> Gen (sh:.Int)     -> Gen e@@ -717,7 +717,7 @@     sh:.n1  <- forAll dim     n2      <- forAll (Gen.int (Range.linear 0 64))     n       <- return (P.min n1 n2) -- don't generate too many segments-    seg     <- forAll (array (Z:.n) (Gen.int (Range.linear 0 (128 `quot` 2 P.^ (rank (undefined::sh))))))+    seg     <- forAll (array (Z:.n) (Gen.int (Range.linear 0 (128 `quot` 2 P.^ (rank @sh)))))     arr     <- forAll (array (sh:.P.sum (toList seg)) e)     let !go = runN (\v -> A.scanr'Seg (+) (the v)) in go (scalar x) arr seg ~~~ scanr'SegRef (+) x arr seg @@ -749,7 +749,7 @@     x2 + 1 A.== y1 ? ( lift (x1,y2) , constant top )   ))) -intervalArray :: (Shape sh, Elt e, P.Num e) => sh -> Int -> proxy e -> Array (sh:.Int) (e,e)+intervalArray :: (Shape sh, Elt e, P.Num e) => sh -> Int -> Gen e -> Array (sh:.Int) (e,e) intervalArray sh n _ = fromFunction (sh:.n) (\(_:.i) -> let x = P.fromIntegral i in (x,x))  @@ -840,7 +840,7 @@   let       sz :. n   = arrayShape arr       seg'      = toList seg-      n'        = P.sum $ P.map (\x -> P.fromIntegral x + 1) seg'+      n'        = P.sum $ P.map (+1) seg'       arr'      = [ P.scanl f z sec | sub <- splitEvery n (toList arr)                                     , sec <- splitPlaces seg' sub ]   in@@ -856,7 +856,7 @@   let       sz :. n   = arrayShape arr       seg'      = toList seg-      n'        = P.fromIntegral (P.sum seg')+      n'        = P.sum seg'       arr'      = [ P.scanl1 f sec | sub <- splitEvery n (toList arr)                                    , sec <- splitPlaces seg' sub ]   in@@ -890,7 +890,7 @@   let       sz :. n   = arrayShape arr       seg'      = toList seg-      n'        = P.sum $ P.map (\x -> P.fromIntegral x + 1) seg'+      n'        = P.sum $ P.map (+1) seg'       arr'      = [ P.scanr f z sec | sub <- splitEvery n (toList arr)                                     , sec <- splitPlaces seg' sub ]   in@@ -905,7 +905,7 @@ scanr1SegRef f arr seg =   let sz :. n   = arrayShape arr       seg'      = toList seg-      n'        = P.fromIntegral (P.sum seg')+      n'        = P.sum seg'       arr'      = [ P.scanr1 f sec | sub <- splitEvery n (toList arr)                                    , sec <- splitPlaces seg' sub ]   in
src/Data/Array/Accelerate/Test/NoFib/Prelude/Stencil.hs view
@@ -6,13 +6,14 @@ {-# LANGUAGE PatternGuards       #-} {-# LANGUAGE RankNTypes          #-} {-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TypeApplications    #-} {-# LANGUAGE TypeOperators       #-} -- | -- Module      : Data.Array.Accelerate.Test.NoFib.Prelude.Stencil--- Copyright   : [2009..2017] Trevor L. McDonell+-- Copyright   : [2009..2020] The Accelerate Team -- License     : BSD3 ----- Maintainer  : Trevor L. McDonell <tmcdonell@cse.unsw.edu.au>+-- Maintainer  : Trevor L. McDonell <trevor.mcdonell@gmail.com> -- Stability   : experimental -- Portability : non-portable (GHC extensions) --@@ -23,12 +24,13 @@  ) where -import Data.Proxy import Data.Typeable import Prelude                                                      as P  import Data.Array.Accelerate                                        as A-import Data.Array.Accelerate.Array.Sugar                            as S+import Data.Array.Accelerate.Sugar.Elt                              as S+import Data.Array.Accelerate.Sugar.Array                            as S+import Data.Array.Accelerate.Representation.Type import Data.Array.Accelerate.Analysis.Match import Data.Array.Accelerate.Type import Data.Array.Accelerate.Test.NoFib.Base@@ -46,25 +48,25 @@ test_stencil :: RunN -> TestTree test_stencil runN =   testGroup "stencil"-    [ at (Proxy::Proxy TestInt8)   $ testElt i8-    , at (Proxy::Proxy TestInt16)  $ testElt i16-    , at (Proxy::Proxy TestInt32)  $ testElt i32-    , at (Proxy::Proxy TestInt64)  $ testElt i64-    , at (Proxy::Proxy TestWord8)  $ testElt w8-    , at (Proxy::Proxy TestWord16) $ testElt w16-    , at (Proxy::Proxy TestWord32) $ testElt w32-    , at (Proxy::Proxy TestWord64) $ testElt w64-    , at (Proxy::Proxy TestHalf)   $ testElt f16-    , at (Proxy::Proxy TestFloat)  $ testElt f32-    , at (Proxy::Proxy TestDouble) $ testElt f64+    [ at @TestInt8   $ testElt i8+    , at @TestInt16  $ testElt i16+    , at @TestInt32  $ testElt i32+    , at @TestInt64  $ testElt i64+    , at @TestWord8  $ testElt w8+    , at @TestWord16 $ testElt w16+    , at @TestWord32 $ testElt w32+    , at @TestWord64 $ testElt w64+    , at @TestHalf   $ testElt f16+    , at @TestFloat  $ testElt f32+    , at @TestDouble $ testElt f64     ]   where     testElt-        :: forall a. (P.Num a, A.Num a, Similar a)+        :: forall a. (P.Num a, A.Num a, Similar a, Show a)         => Gen a         -> TestTree     testElt e =-      testGroup (show (typeOf (undefined :: a)))+      testGroup (show (eltR @a))         [ testDim1         , testDim2         , testDim3@@ -96,7 +98,7 @@   test_stencil3-    :: (P.Num e, A.Num e, Similar e)+    :: (P.Num e, A.Num e, Similar e, Show e)     => RunN     -> Gen e     -> Property@@ -115,7 +117,7 @@     go xs ~~~ stencil3Ref r b xs  test_stencil5-    :: (P.Num e, A.Num e, Similar e)+    :: (P.Num e, A.Num e, Similar e, Show e)     => RunN     -> Gen e     -> Property@@ -134,7 +136,7 @@     go xs ~~~ stencil5Ref r b xs  test_stencil7-    :: (P.Num e, A.Num e, Similar e)+    :: (P.Num e, A.Num e, Similar e, Show e)     => RunN     -> Gen e     -> Property@@ -153,7 +155,7 @@     go xs ~~~ stencil7Ref r b xs  test_stencil9-    :: (P.Num e, A.Num e, Similar e)+    :: (P.Num e, A.Num e, Similar e, Show e)     => RunN     -> Gen e     -> Property@@ -173,7 +175,7 @@   test_stencil3x3-    :: (P.Num e, A.Num e, Similar e)+    :: (P.Num e, A.Num e, Similar e, Show e)     => RunN     -> Gen e     -> Property@@ -194,7 +196,7 @@     go xs ~~~ stencil3x3Ref r b xs  test_stencil5x5-    :: (P.Num e, A.Num e, Similar e)+    :: (P.Num e, A.Num e, Similar e, Show e)     => RunN     -> Gen e     -> Property@@ -215,7 +217,7 @@     go xs ~~~ stencil5x5Ref r b xs  test_stencil7x7-    :: (P.Num e, A.Num e, Similar e)+    :: (P.Num e, A.Num e, Similar e, Show e)     => RunN     -> Gen e     -> Property@@ -236,7 +238,7 @@     go xs ~~~ stencil7x7Ref r b xs  test_stencil9x9-    :: (P.Num e, A.Num e, Similar e)+    :: (P.Num e, A.Num e, Similar e, Show e)     => RunN     -> Gen e     -> Property@@ -257,7 +259,7 @@     go xs ~~~ stencil9x9Ref r b xs  test_stencil3x3x3-    :: (P.Num e, A.Num e, Similar e)+    :: (P.Num e, A.Num e, Similar e, Show e)     => RunN     -> Gen e     -> Property@@ -302,10 +304,7 @@   | Constant e   deriving (P.Eq, Show) -boundary-    :: Elt e-    => Gen e-    -> Gen (SimpleBoundary e)+boundary :: Gen e -> Gen (SimpleBoundary e) boundary e =   Gen.choice     [ Constant <$> e@@ -413,9 +412,9 @@   P9 i5 a5 r5 <- pattern9   P9 i6 a6 r6 <- pattern9   P9 i7 a7 r7 <- pattern9-  P9 i8 a8 r8 <- pattern9+  P9 j8 a8 r8 <- pattern9   return $-    P9x9 [i0,i1,i2,i3,i4,i5,i6,i7,i8]+    P9x9 [i0,i1,i2,i3,i4,i5,i6,i7,j8]          (\(x0,x1,x2,x3,x4,x5,x6,x7,x8) -> P.sum [a0 x0, a1 x1, a2 x2, a3 x3, a4 x4, a5 x5, a6 x6, a7 x7, a8 x8])          (\(x0,x1,x2,x3,x4,x5,x6,x7,x8) -> P.sum [r0 x0, r1 x1, r2 x2, r3 x3, r4 x4, r5 x5, r6 x6, r7 x7, r8 x8]) @@ -628,14 +627,14 @@  bound :: forall sh e. Shape sh => SimpleBoundary e -> sh -> sh -> Either e sh bound bnd sh0 ix0 =-  case go (eltType sh0) (fromElt sh0) (fromElt ix0) of+  case go (eltR @sh) (fromElt sh0) (fromElt ix0) of     Left e    -> Left e     Right ix' -> Right (toElt ix')   where-    go :: TupleType t -> t -> t -> Either e t-    go TypeRunit           ()      ()      = Right ()-    go (TypeRpair tsh tsz) (sh,sz) (ih,iz) = go tsh sh ih `addDim` go tsz sz iz-    go (TypeRscalar t)     sh      i+    go :: TypeR t -> t -> t -> Either e t+    go TupRunit           ()      ()      = Right ()+    go (TupRpair tsh tsz) (sh,sz) (ih,iz) = go tsh sh ih `addDim` go tsz sz iz+    go (TupRsingle t)     sh      i       | Just Refl <- matchScalarType t (scalarType :: ScalarType Int)       = if i P.< 0           then case bnd of
src/Data/Array/Accelerate/Test/NoFib/Prelude/ZipWith.hs view
@@ -4,13 +4,14 @@ {-# LANGUAGE MonoLocalBinds      #-} {-# LANGUAGE RankNTypes          #-} {-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TypeApplications    #-} {-# LANGUAGE TypeOperators       #-} -- | -- Module      : Data.Array.Accelerate.Test.NoFib.Prelude.ZipWith--- Copyright   : [2009..2017] Trevor L. McDonell+-- Copyright   : [2009..2020] The Accelerate Team -- License     : BSD3 ----- Maintainer  : Trevor L. McDonell <tmcdonell@cse.unsw.edu.au>+-- Maintainer  : Trevor L. McDonell <trevor.mcdonell@gmail.com> -- Stability   : experimental -- Portability : non-portable (GHC extensions) --@@ -22,17 +23,17 @@ ) where  import Data.Bits                                                    as P-import Data.Proxy-import Data.Typeable import Prelude                                                      as P  import Data.Array.Accelerate                                        as A import Data.Array.Accelerate.Data.Bits                              as A-import Data.Array.Accelerate.Array.Sugar                            as S import Data.Array.Accelerate.Smart                                  ( ($$) )+import Data.Array.Accelerate.Sugar.Elt import Data.Array.Accelerate.Test.NoFib.Base import Data.Array.Accelerate.Test.NoFib.Config import Data.Array.Accelerate.Test.Similar+import qualified Data.Array.Accelerate.Sugar.Array                  as S+import qualified Data.Array.Accelerate.Sugar.Shape                  as S  import Hedgehog import qualified Hedgehog.Gen                                       as Gen@@ -45,38 +46,38 @@ test_zipWith :: RunN -> TestTree test_zipWith runN =   testGroup "zipWith"-    [ at (Proxy::Proxy TestInt8)   $ testIntegralElt i8-    , at (Proxy::Proxy TestInt16)  $ testIntegralElt i16-    , at (Proxy::Proxy TestInt32)  $ testIntegralElt i32-    , at (Proxy::Proxy TestInt64)  $ testIntegralElt i64-    , at (Proxy::Proxy TestWord8)  $ testIntegralElt w8-    , at (Proxy::Proxy TestWord16) $ testIntegralElt w16-    , at (Proxy::Proxy TestWord32) $ testIntegralElt w32-    , at (Proxy::Proxy TestWord64) $ testIntegralElt w64-    , at (Proxy::Proxy TestHalf)   $ testFloatingElt (Gen.realFloat :: Range Half -> Gen Half)-    , at (Proxy::Proxy TestFloat)  $ testFloatingElt Gen.float-    , at (Proxy::Proxy TestDouble) $ testFloatingElt Gen.double+    [ at @TestInt8   $ testIntegralElt i8+    , at @TestInt16  $ testIntegralElt i16+    , at @TestInt32  $ testIntegralElt i32+    , at @TestInt64  $ testIntegralElt i64+    , at @TestWord8  $ testIntegralElt w8+    , at @TestWord16 $ testIntegralElt w16+    , at @TestWord32 $ testIntegralElt w32+    , at @TestWord64 $ testIntegralElt w64+    , at @TestHalf   $ testFloatingElt (Gen.realFloat :: Range Half -> Gen Half)+    , at @TestFloat  $ testFloatingElt Gen.float+    , at @TestDouble $ testFloatingElt Gen.double     ]   where     testIntegralElt         :: forall a. ( P.Integral a, P.FiniteBits a                      , A.Integral a, A.FiniteBits a-                     , Similar a )+                     , Similar a, Show a )         => Gen a         -> TestTree     testIntegralElt e =-      testGroup (show (typeOf (undefined :: a)))+      testGroup (show (eltR @a))         [ testDim dim0         , testDim dim1         , testDim dim2         ]       where         testDim-            :: forall sh. (Shape sh, P.Eq sh)+            :: forall sh. (Shape sh, Show sh, P.Eq sh, Show sh)             => Gen sh             -> TestTree         testDim sh =-          testGroup ("DIM" P.++ show (rank (undefined::sh)))+          testGroup ("DIM" P.++ show (S.rank @sh))             [ -- operators on Num               testProperty "(+)"          $ test_plus runN sh e             , testProperty "(-)"          $ test_minus runN sh e@@ -111,22 +112,22 @@             ]      testFloatingElt-        :: forall a. (P.RealFloat a, A.RealFloat a, Similar a)+        :: forall a. (P.RealFloat a, A.RealFloat a, Similar a, Show a)         => (Range a -> Gen a)         -> TestTree     testFloatingElt e =-      testGroup (show (typeOf (undefined :: a)))+      testGroup (show (eltR @a))         [ testDim dim0         , testDim dim1         , testDim dim2         ]       where         testDim-            :: forall sh. (Shape sh, P.Eq sh)+            :: forall sh. (Shape sh, Show sh, P.Eq sh)             => Gen sh             -> TestTree         testDim sh =-          testGroup ("DIM" P.++ show (rank (undefined::sh)))+          testGroup ("DIM" P.++ show (S.rank @sh))             [ -- operators on Num               testProperty "(+)"          $ test_plus runN sh (full e)             , testProperty "(-)"          $ test_minus runN sh (full e)@@ -157,7 +158,7 @@ zero x = x P.== 0  test_plus-    :: (Shape sh, Similar e, P.Eq sh, P.Num e, A.Num e)+    :: (Shape sh, Show sh, Similar e, Show e, P.Eq sh, P.Num e, A.Num e)     => RunN     -> Gen sh     -> Gen e@@ -171,7 +172,7 @@     let !go = runN (A.zipWith (+)) in go xs ys ~~~ zipWithRef (+) xs ys  test_minus-    :: (Shape sh, Similar e, P.Eq sh, P.Num e, A.Num e)+    :: (Shape sh, Show sh, Similar e, Show e, P.Eq sh, P.Num e, A.Num e)     => RunN     -> Gen sh     -> Gen e@@ -185,7 +186,7 @@     let !go = runN (A.zipWith (-)) in go xs ys ~~~ zipWithRef (-) xs ys  test_mult-    :: (Shape sh, Similar e, P.Eq sh, P.Num e, A.Num e)+    :: (Shape sh, Show sh, Similar e, Show e, P.Eq sh, P.Num e, A.Num e)     => RunN     -> Gen sh     -> Gen e@@ -199,7 +200,7 @@     let !go = runN (A.zipWith (*)) in go xs ys ~~~ zipWithRef (*) xs ys  test_quot-    :: (Shape sh, Similar e, P.Eq sh, P.Integral e, A.Integral e)+    :: (Shape sh, Show sh, Similar e, Show e, P.Eq sh, P.Integral e, A.Integral e)     => RunN     -> Gen sh     -> Gen e@@ -213,7 +214,7 @@     let !go = runN (A.zipWith quot) in go xs ys ~~~ zipWithRef quot xs ys  test_rem-    :: (Shape sh, Similar e, P.Eq sh, P.Integral e, A.Integral e)+    :: (Shape sh, Show sh, Similar e, Show e, P.Eq sh, P.Integral e, A.Integral e)     => RunN     -> Gen sh     -> Gen e@@ -227,7 +228,7 @@     let !go = runN (A.zipWith rem) in go xs ys ~~~ zipWithRef rem xs ys  test_quotRem-    :: (Shape sh, Similar e, P.Eq sh, P.Integral e, A.Integral e)+    :: (Shape sh, Show sh, Similar e, Show e, P.Eq sh, P.Integral e, A.Integral e)     => RunN     -> Gen sh     -> Gen e@@ -241,7 +242,7 @@     let !go = runN (A.zipWith (lift $$ quotRem)) in go xs ys ~~~ zipWithRef quotRem xs ys  test_idiv-    :: (Shape sh, Similar e, P.Eq sh, P.Integral e, A.Integral e)+    :: (Shape sh, Show sh, Similar e, Show e, P.Eq sh, P.Integral e, A.Integral e)     => RunN     -> Gen sh     -> Gen e@@ -255,7 +256,7 @@     let !go = runN (A.zipWith div) in go xs ys ~~~ zipWithRef div xs ys  test_fdiv-    :: (Shape sh, Similar e, P.Eq sh, P.Eq e, P.Fractional e, A.Fractional e)+    :: (Shape sh, Show sh, Similar e, Show e, P.Eq sh, P.Eq e, P.Fractional e, A.Fractional e)     => RunN     -> Gen sh     -> Gen e@@ -269,7 +270,7 @@     let !go = runN (A.zipWith (/)) in go xs ys ~~~ zipWithRef (/) xs ys  test_pow-    :: (Shape sh, Similar e, P.Eq sh, P.Floating e, A.Floating e)+    :: (Shape sh, Show sh, Similar e, Show e, P.Eq sh, P.Floating e, A.Floating e)     => RunN     -> Gen sh     -> Gen e@@ -283,7 +284,7 @@     let !go = runN (A.zipWith (**)) in go xs ys ~~~ zipWithRef (**) xs ys  test_logBase-    :: (Shape sh, Similar e, P.Eq sh, P.Floating e, A.Floating e)+    :: (Shape sh, Show sh, Similar e, Show e, P.Eq sh, P.Floating e, A.Floating e)     => RunN     -> Gen sh     -> Gen e@@ -297,7 +298,7 @@     let !go = runN (A.zipWith logBase) in go xs ys ~~~ zipWithRef logBase xs ys  test_atan2-    :: (Shape sh, Similar e, P.Eq sh, P.RealFloat e, A.RealFloat e)+    :: (Shape sh, Show sh, Similar e, Show e, P.Eq sh, P.RealFloat e, A.RealFloat e)     => RunN     -> Gen sh     -> Gen e@@ -311,7 +312,7 @@     let !go = runN (A.zipWith A.atan2) in go xs ys ~~~ zipWithRef P.atan2 xs ys  test_mod-    :: (Shape sh, Similar e, P.Eq sh, P.Integral e, A.Integral e)+    :: (Shape sh, Show sh, Similar e, Show e, P.Eq sh, P.Integral e, A.Integral e)     => RunN     -> Gen sh     -> Gen e@@ -325,7 +326,7 @@     let !go = runN (A.zipWith mod) in go xs ys ~~~ zipWithRef mod xs ys  test_divMod-    :: (Shape sh, Similar e, P.Eq sh, P.Integral e, A.Integral e)+    :: (Shape sh, Show sh, Similar e, Show e, P.Eq sh, P.Integral e, A.Integral e)     => RunN     -> Gen sh     -> Gen e@@ -339,7 +340,7 @@     let !go = runN (A.zipWith (lift $$ divMod)) in go xs ys ~~~ zipWithRef divMod xs ys  test_band-    :: (Shape sh, Similar e, P.Eq sh, P.Bits e, A.Bits e)+    :: (Shape sh, Show sh, Similar e, Show e, P.Eq sh, P.Bits e, A.Bits e)     => RunN     -> Gen sh     -> Gen e@@ -353,7 +354,7 @@     let !go = runN (A.zipWith (A..&.)) in go xs ys ~~~ zipWithRef (P..&.) xs ys  test_bor-    :: (Shape sh, Similar e, P.Eq sh, P.Bits e, A.Bits e)+    :: (Shape sh, Show sh, Similar e, Show e, P.Eq sh, P.Bits e, A.Bits e)     => RunN     -> Gen sh     -> Gen e@@ -367,7 +368,7 @@     let !go = runN (A.zipWith (A..|.)) in go xs ys ~~~ zipWithRef (P..|.) xs ys  test_xor-    :: (Shape sh, Similar e, P.Eq sh, P.Bits e, A.Bits e)+    :: (Shape sh, Show sh, Similar e, Show e, P.Eq sh, P.Bits e, A.Bits e)     => RunN     -> Gen sh     -> Gen e@@ -381,7 +382,7 @@     let !go = runN (A.zipWith A.xor) in go xs ys ~~~ zipWithRef P.xor xs ys  test_shift-    :: forall sh e. (Shape sh, Similar e, P.Eq sh, P.FiniteBits e, A.FiniteBits e)+    :: forall sh e. (Shape sh, Show sh, Similar e, Show e, P.Eq sh, P.FiniteBits e, A.FiniteBits e)     => RunN     -> Gen sh     -> Gen e@@ -396,7 +397,7 @@     let !go = runN (A.zipWith A.shift) in go xs ys ~~~ zipWithRef P.shift xs ys  test_shiftL-    :: forall sh e. (Shape sh, Similar e, P.Eq sh, P.FiniteBits e, A.FiniteBits e)+    :: forall sh e. (Shape sh, Show sh, Similar e, Show e, P.Eq sh, P.FiniteBits e, A.FiniteBits e)     => RunN     -> Gen sh     -> Gen e@@ -411,7 +412,7 @@     let !go = runN (A.zipWith A.shiftL) in go xs ys ~~~ zipWithRef P.shiftL xs ys  test_shiftR-    :: forall sh e. (Shape sh, Similar e, P.Eq sh, P.FiniteBits e, A.FiniteBits e)+    :: forall sh e. (Shape sh, Show sh, Similar e, Show e, P.Eq sh, P.FiniteBits e, A.FiniteBits e)     => RunN     -> Gen sh     -> Gen e@@ -426,7 +427,7 @@     let !go = runN (A.zipWith A.shiftR) in go xs ys ~~~ zipWithRef P.shiftR xs ys  test_rotate-    :: forall sh e. (Shape sh, Similar e, P.Eq sh, P.FiniteBits e, A.FiniteBits e)+    :: forall sh e. (Shape sh, Show sh, Similar e, Show e, P.Eq sh, P.FiniteBits e, A.FiniteBits e)     => RunN     -> Gen sh     -> Gen e@@ -441,7 +442,7 @@     let !go = runN (A.zipWith A.rotate) in go xs ys ~~~ zipWithRef P.rotate xs ys  test_rotateL-    :: forall sh e. (Shape sh, Similar e, P.Eq sh, P.FiniteBits e, A.FiniteBits e)+    :: forall sh e. (Shape sh, Show sh, Similar e, Show e, P.Eq sh, P.FiniteBits e, A.FiniteBits e)     => RunN     -> Gen sh     -> Gen e@@ -456,7 +457,7 @@     let !go = runN (A.zipWith A.rotateL) in go xs ys ~~~ zipWithRef P.rotateL xs ys  test_rotateR-    :: forall sh e. (Shape sh, Similar e, P.Eq sh, P.FiniteBits e, A.FiniteBits e)+    :: forall sh e. (Shape sh, Show sh, Similar e, Show e, P.Eq sh, P.FiniteBits e, A.FiniteBits e)     => RunN     -> Gen sh     -> Gen e@@ -471,7 +472,7 @@     let !go = runN (A.zipWith A.rotateR) in go xs ys ~~~ zipWithRef P.rotateR xs ys  test_lt-    :: (Shape sh, Similar e, P.Eq sh, P.Ord e, A.Ord e)+    :: (Shape sh, Show sh, Show e, P.Eq sh, P.Ord e, A.Ord e)     => RunN     -> Gen sh     -> Gen e@@ -485,7 +486,7 @@     let !go = runN (A.zipWith (A.<)) in go xs ys ~~~ zipWithRef (P.<) xs ys  test_gt-    :: (Shape sh, Similar e, P.Eq sh, P.Ord e, A.Ord e)+    :: (Shape sh, Show sh, Show e, P.Eq sh, P.Ord e, A.Ord e)     => RunN     -> Gen sh     -> Gen e@@ -499,7 +500,7 @@     let !go = runN (A.zipWith (A.>)) in go xs ys ~~~ zipWithRef (P.>) xs ys  test_lte-    :: (Shape sh, Similar e, P.Eq sh, P.Ord e, A.Ord e)+    :: (Shape sh, Show sh, Show e, P.Eq sh, P.Ord e, A.Ord e)     => RunN     -> Gen sh     -> Gen e@@ -513,7 +514,7 @@     let !go = runN (A.zipWith (A.<=)) in go xs ys ~~~ zipWithRef (P.<=) xs ys  test_gte-    :: (Shape sh, Similar e, P.Eq sh, P.Ord e, A.Ord e)+    :: (Shape sh, Show sh, Show e, P.Eq sh, P.Ord e, A.Ord e)     => RunN     -> Gen sh     -> Gen e@@ -527,7 +528,7 @@     let !go = runN (A.zipWith (A.>=)) in go xs ys ~~~ zipWithRef (P.>=) xs ys  test_eq-    :: (Shape sh, Similar e, P.Eq sh, P.Ord e, A.Ord e)+    :: (Shape sh, Show sh, Show e, P.Eq sh, P.Ord e, A.Ord e)     => RunN     -> Gen sh     -> Gen e@@ -541,7 +542,7 @@     let !go = runN (A.zipWith (A.==)) in go xs ys ~~~ zipWithRef (P.==) xs ys  test_neq-    :: (Shape sh, Similar e, P.Eq sh, P.Ord e, A.Ord e)+    :: (Shape sh, Show sh, Show e, P.Eq sh, P.Ord e, A.Ord e)     => RunN     -> Gen sh     -> Gen e@@ -555,7 +556,7 @@     let !go = runN (A.zipWith (A./=)) in go xs ys ~~~ zipWithRef (P./=) xs ys  test_min-    :: (Shape sh, Similar e, P.Eq sh, P.Ord e, A.Ord e)+    :: (Shape sh, Show sh, Similar e, Show e, P.Eq sh, P.Ord e, A.Ord e)     => RunN     -> Gen sh     -> Gen e@@ -569,7 +570,7 @@     let !go = runN (A.zipWith (A.min)) in go xs ys ~~~ zipWithRef (P.min) xs ys  test_max-    :: (Shape sh, Similar e, P.Eq sh, P.Ord e, A.Ord e)+    :: (Shape sh, Show sh, Similar e, Show e, P.Eq sh, P.Ord e, A.Ord e)     => RunN     -> Gen sh     -> Gen e@@ -587,7 +588,7 @@ -- ------------------------  zipWithRef-    :: (Shape sh, Elt c)+    :: (Shape sh, Elt a, Elt b, Elt c)     => (a -> b -> c)     -> Array sh a     -> Array sh b
src/Data/Array/Accelerate/Test/NoFib/Sharing.hs view
@@ -5,10 +5,10 @@ {-# LANGUAGE TypeOperators       #-} -- | -- Module      : Data.Array.Accelerate.Test.NoFib.Sharing--- Copyright   : [2009..2017] Trevor L. McDonell+-- Copyright   : [2009..2020] The Accelerate Team -- License     : BSD3 ----- Maintainer  : Trevor L. McDonell <tmcdonell@cse.unsw.edu.au>+-- Maintainer  : Trevor L. McDonell <trevor.mcdonell@gmail.com> -- Stability   : experimental -- Portability : non-portable (GHC extensions) --@@ -60,18 +60,18 @@       , testCase "unused"               $ sharingExp test_unused_iteration       ]     , testGroup "nested data-parallelism"-      [ expectFail $ testCase "mvm"     $ sharingAcc test_nested_data_praallelism+      [ expectFail $ testCase "mvm"     $ sharingAcc test_nested_data_parallelism       ]     ]   where     sharingAcc :: Arrays a => Acc a -> Assertion     sharingAcc acc =-      catch (rnf (convertAcc True True True True acc) `seq` return ())+      catch (rnf (convertAcc acc) `seq` return ())             (\(e :: SomeException) -> assertFailure (show e))      sharingExp :: Elt e => Exp e -> Assertion     sharingExp exp =-      catch (rnf (convertExp True exp) `seq` return ())+      catch (rnf (convertExp exp) `seq` return ())             (\(e :: SomeException) -> assertFailure (show e))  @@ -312,8 +312,8 @@ -- This program contains nested data-parallelism and thus sharing recovery -- will fail. ---test_nested_data_praallelism :: Acc (Vector Float)-test_nested_data_praallelism =+test_nested_data_parallelism :: Acc (Vector Float)+test_nested_data_parallelism =   mvm (use $ fromList (Z:.10:.10) [0..]) (use $ fromList (Z:.10) [0..])   where     dotp :: A.Num e => Acc (Vector e) -> Acc (Vector e) -> Acc (Scalar e)
src/Data/Array/Accelerate/Test/NoFib/Spectral.hs view
@@ -1,10 +1,10 @@ {-# LANGUAGE RankNTypes #-} -- | -- Module      : Data.Array.Accelerate.Test.NoFib.Spectral--- Copyright   : [2009..2017] Trevor L. McDonell+-- Copyright   : [2009..2020] The Accelerate Team -- License     : BSD3 ----- Maintainer  : Trevor L. McDonell <tmcdonell@cse.unsw.edu.au>+-- Maintainer  : Trevor L. McDonell <trevor.mcdonell@gmail.com> -- Stability   : experimental -- Portability : non-portable (GHC extensions) --
src/Data/Array/Accelerate/Test/NoFib/Spectral/BlackScholes.hs view
@@ -3,14 +3,15 @@ {-# LANGUAGE FlexibleContexts    #-} {-# LANGUAGE RankNTypes          #-} {-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TypeApplications    #-} {-# LANGUAGE TypeOperators       #-} {-# LANGUAGE ViewPatterns        #-} -- | -- Module      : Data.Array.Accelerate.Test.NoFib.Spectral.BlackScholes--- Copyright   : [2009..2017] Trevor L. McDonell+-- Copyright   : [2009..2020] The Accelerate Team -- License     : BSD3 ----- Maintainer  : Trevor L. McDonell <tmcdonell@cse.unsw.edu.au>+-- Maintainer  : Trevor L. McDonell <trevor.mcdonell@gmail.com> -- Stability   : experimental -- Portability : non-portable (GHC extensions) --@@ -21,12 +22,11 @@  ) where -import Data.Proxy-import Data.Typeable import Prelude                                                      as P  import Data.Array.Accelerate                                        as A-import Data.Array.Accelerate.Array.Sugar                            as S+import Data.Array.Accelerate.Sugar.Elt                              as S+import Data.Array.Accelerate.Sugar.Array                            as S import Data.Array.Accelerate.Test.NoFib.Base import Data.Array.Accelerate.Test.NoFib.Config import Data.Array.Accelerate.Test.Similar@@ -42,21 +42,21 @@ test_blackscholes :: RunN -> TestTree test_blackscholes runN =   testGroup "blackscholes"-    [ at (Proxy::Proxy TestHalf)   $ testElt (Gen.realFloat :: Range Half -> Gen Half)-    , at (Proxy::Proxy TestFloat)  $ testElt Gen.float-    , at (Proxy::Proxy TestDouble) $ testElt Gen.double+    [ at @TestHalf   $ testElt (Gen.realFloat :: Range Half -> Gen Half)+    , at @TestFloat  $ testElt Gen.float+    , at @TestDouble $ testElt Gen.double     ]   where     testElt-        :: forall a. (P.Floating a, P.Ord a, A.Floating a, A.Ord a , Similar a)+        :: forall a. (P.Floating a, P.Ord a, A.Floating a, A.Ord a , Similar a, Show a)         => (Range a -> Gen a)         -> TestTree     testElt e =-      testProperty (show (typeOf (undefined :: a))) $ test_blackscholes' runN e+      testProperty (show (eltR @a)) $ test_blackscholes' runN e   test_blackscholes'-    :: (P.Floating a, P.Ord a, A.Floating a, A.Ord a, Similar a)+    :: (P.Floating a, P.Ord a, A.Floating a, A.Ord a, Similar a, Show a)     => RunN     -> (Range a -> Gen a)     -> Property
src/Data/Array/Accelerate/Test/NoFib/Spectral/RadixSort.hs view
@@ -4,13 +4,14 @@ {-# LANGUAGE MonoLocalBinds      #-} {-# LANGUAGE RankNTypes          #-} {-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TypeApplications    #-} {-# LANGUAGE TypeOperators       #-} -- | -- Module      : Data.Array.Accelerate.Test.NoFib.Spectral.RadixSort--- Copyright   : [2009..2017] Trevor L. McDonell+-- Copyright   : [2009..2020] The Accelerate Team -- License     : BSD3 ----- Maintainer  : Trevor L. McDonell <tmcdonell@cse.unsw.edu.au>+-- Maintainer  : Trevor L. McDonell <trevor.mcdonell@gmail.com> -- Stability   : experimental -- Portability : non-portable (GHC extensions) --@@ -21,16 +22,14 @@  ) where -import Data.Proxy-import Data.Typeable import Data.Function-import Data.List+import Data.List                                                    ( sortBy ) import Prelude                                                      as P import qualified Data.Bits                                          as P  import Data.Array.Accelerate                                        as A import Data.Array.Accelerate.Data.Bits                              as A-import Data.Array.Accelerate.Array.Sugar                            as S ( shape )+import Data.Array.Accelerate.Sugar.Elt import Data.Array.Accelerate.Test.NoFib.Base import Data.Array.Accelerate.Test.NoFib.Config import Data.Array.Accelerate.Test.Similar@@ -46,30 +45,30 @@ test_radixsort :: RunN -> TestTree test_radixsort runN =   testGroup "radixsort"-    [ at (Proxy::Proxy TestInt8)   $ testElt i8-    , at (Proxy::Proxy TestInt16)  $ testElt i16-    , at (Proxy::Proxy TestInt32)  $ testElt i32-    , at (Proxy::Proxy TestInt64)  $ testElt i64-    , at (Proxy::Proxy TestWord8)  $ testElt w8-    , at (Proxy::Proxy TestWord16) $ testElt w16-    , at (Proxy::Proxy TestWord32) $ testElt w32-    , at (Proxy::Proxy TestWord64) $ testElt w64-    -- , at (Proxy::Proxy TestFloat)  $ testElt f32-    -- , at (Proxy::Proxy TestDouble) $ testElt f64+    [ at @TestInt8   $ testElt i8+    , at @TestInt16  $ testElt i16+    , at @TestInt32  $ testElt i32+    , at @TestInt64  $ testElt i64+    , at @TestWord8  $ testElt w8+    , at @TestWord16 $ testElt w16+    , at @TestWord32 $ testElt w32+    , at @TestWord64 $ testElt w64+    -- , at @TestFloat  $ testElt f32+    -- , at @TestDouble $ testElt f64     ]   where-    testElt :: forall a. (Similar a, P.Ord a, Radix a)+    testElt :: forall a. (Similar a, P.Ord a, Radix a, Show a)         => Gen a         -> TestTree     testElt e =-      testGroup (show (typeOf (undefined :: a)))+      testGroup (show (eltR @a))         [ testProperty "ascending"    $ test_sort_ascending runN e         , testProperty "descending"   $ test_sort_descending runN e         , testProperty "key-value"    $ test_sort_keyval runN e f32         ]  test_sort_ascending-    :: (P.Ord e, Radix e, Similar e)+    :: (P.Ord e, Radix e, Similar e, Show e)     => RunN     -> Gen e     -> Property@@ -80,7 +79,7 @@     let !go = runN radixsort in go xs ~~~ sortRef P.compare xs  test_sort_descending-    :: (P.Ord e, Radix e, Similar e)+    :: (P.Ord e, Radix e, Similar e, Show e)     => RunN     -> Gen e     -> Property@@ -91,7 +90,7 @@     let !go = runN (radixsortBy complement) in go xs ~~~ sortRef (flip P.compare) xs  test_sort_keyval-    :: (P.Ord k, Radix k, Similar k, Elt v, Similar v)+    :: (P.Ord k, Radix k, Similar k, Show k, Elt v, Similar v, Show v)     => RunN     -> Gen k     -> Gen v@@ -177,12 +176,12 @@                         iup     = A.map (size v - 1 -) . prescanr (+) 0 $ flags                         index   = A.zipWith deal flags (A.zip idown iup)                     in-                    permute const v (\ix -> index1 (index!ix)) v+                    permute const v (\ix -> Just_ (index1 (index!ix))) v   -- This is rather slow. Speeding up the reference implementation by using, say, -- vector-algorithms, does not significantly change the runtime. -- sortRef :: Elt a => (a -> a -> Ordering) -> Vector a -> Vector a-sortRef cmp xs = fromList (S.shape xs) (sortBy cmp (toList xs))+sortRef cmp xs = fromList (arrayShape xs) (sortBy cmp (toList xs)) 
src/Data/Array/Accelerate/Test/NoFib/Spectral/SMVM.hs view
@@ -3,13 +3,14 @@ {-# LANGUAGE FlexibleContexts    #-} {-# LANGUAGE RankNTypes          #-} {-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TypeApplications    #-} {-# LANGUAGE TypeOperators       #-} -- | -- Module      : Data.Array.Accelerate.Test.NoFib.Spectral.SMVM--- Copyright   : [2009..2017] Trevor L. McDonell+-- Copyright   : [2009..2020] The Accelerate Team -- License     : BSD3 ----- Maintainer  : Trevor L. McDonell <tmcdonell@cse.unsw.edu.au>+-- Maintainer  : Trevor L. McDonell <trevor.mcdonell@gmail.com> -- Stability   : experimental -- Portability : non-portable (GHC extensions) --@@ -20,12 +21,10 @@  ) where -import Data.Proxy-import Data.Typeable import Prelude                                                      as P  import Data.Array.Accelerate                                        as A-import Data.Array.Accelerate.Array.Sugar                            as S+import Data.Array.Accelerate.Sugar.Elt import Data.Array.Accelerate.Test.NoFib.Base import Data.Array.Accelerate.Test.NoFib.Config import Data.Array.Accelerate.Test.Similar@@ -41,19 +40,19 @@ test_smvm :: RunN -> TestTree test_smvm runN =   testGroup "smvm"-    [ at (Proxy::Proxy TestHalf)   $ testElt f16-    , at (Proxy::Proxy TestFloat)  $ testElt f32-    , at (Proxy::Proxy TestDouble) $ testElt f64+    [ at @TestHalf   $ testElt f16+    , at @TestFloat  $ testElt f32+    , at @TestDouble $ testElt f64     ]   where-    testElt :: forall a. (P.Num a, P.Ord a , A.Num a, A.Ord a , Similar a)+    testElt :: forall a. (P.Num a, A.Num a, Similar a, Show a)         => Gen a         -> TestTree     testElt e =-      testProperty (show (typeOf (undefined :: a))) $ test_smvm' runN e+      testProperty (show (eltR @a)) $ test_smvm' runN e  -test_smvm' :: (A.Num e, P.Num e, Similar e) => RunN -> Gen e -> Property+test_smvm' :: (A.Num e, P.Num e, Similar e, Show e) => RunN -> Gen e -> Property test_smvm' runN e =   property $ do     (smat, cols) <- forAll (sparseMatrix e)@@ -67,7 +66,7 @@   rows  <- Gen.int (Range.linear 1 256)   cols  <- Gen.int (Range.linear 1 256)   seg   <- array (Z:.rows) (Gen.int (Range.linear 0 cols))-  let nnz = P.sum (S.toList seg)+  let nnz = P.sum (toList seg)   smat  <- array (Z:.nnz) ((,) <$> Gen.int (Range.linear 0 (cols-1)) <*> e)   return ((seg,smat), cols) @@ -87,7 +86,7 @@  smvmRef :: (Elt a, P.Num a) => SparseMatrix a -> Vector a -> Vector a smvmRef (segd, smat) vec =-  fromList (S.shape segd)+  fromList (arrayShape segd)            [ P.sum [ val * indexArray vec (Z :. i) | (i,val) <- row ]                    | row <- splitPlaces (toList segd) (toList smat) ] 
src/Data/Array/Accelerate/Test/Similar.hs view
@@ -6,10 +6,10 @@ {-# OPTIONS_HADDOCK hide #-} -- | -- Module      : Data.Array.Accelerate.Test.Similar--- Copyright   : [2017] Trevor L. McDonell+-- Copyright   : [2009..2020] The Accelerate Team -- License     : BSD3 ----- Maintainer  : Trevor L. McDonell <tmcdonell@cse.unsw.edu.au>+-- Maintainer  : Trevor L. McDonell <trevor.mcdonell@gmail.com> -- Stability   : experimental -- Portability : non-portable (GHC extensions) --@@ -17,8 +17,10 @@ module Data.Array.Accelerate.Test.Similar   where -import Data.Array.Accelerate.Array.Sugar import Data.Array.Accelerate.Data.Complex+import Data.Array.Accelerate.Sugar.Array+import Data.Array.Accelerate.Sugar.Elt+import Data.Array.Accelerate.Sugar.Shape import Data.Array.Accelerate.Type  import Hedgehog@@ -167,7 +169,7 @@   (x:xs) ~= (y:ys) = x ~= y && xs ~= ys   _      ~= _      = False -instance (Similar e, Eq sh, Shape sh) => Similar (Array sh e) where+instance (Similar e, Eq sh, Shape sh, Elt e) => Similar (Array sh e) where   a1 ~= a2 = shape a1 == shape a2 && go 0     where       n     = size (shape a1)
src/Data/Array/Accelerate/Trafo.hs view
@@ -1,17 +1,11 @@-{-# LANGUAGE CPP                  #-}-{-# LANGUAGE FlexibleContexts     #-}-{-# LANGUAGE FlexibleInstances    #-}-{-# LANGUAGE MonoLocalBinds       #-}-{-# LANGUAGE RecordWildCards      #-}-{-# LANGUAGE UndecidableInstances #-}-{-# OPTIONS_GHC -fno-warn-orphans #-}+{-# LANGUAGE CPP #-} {-# OPTIONS_HADDOCK hide #-} -- | -- Module      : Data.Array.Accelerate.Trafo--- Copyright   : [2012..2017] Manuel M T Chakravarty, Gabriele Keller, Trevor L. McDonell+-- Copyright   : [2012..2020] The Accelerate Team -- License     : BSD3 ----- Maintainer  : Trevor L. McDonell <tmcdonell@cse.unsw.edu.au>+-- Maintainer  : Trevor L. McDonell <trevor.mcdonell@gmail.com> -- Stability   : experimental -- Portability : non-portable (GHC extensions) --@@ -19,156 +13,92 @@ module Data.Array.Accelerate.Trafo (    -- * HOAS -> de Bruijn conversion-  Phase(..), phases,-   -- ** Array computations   convertAcc, convertAccWith,    -- ** Array functions-  Afunction, AfunctionR,+  Afunction, ArraysFunctionR,   convertAfun, convertAfunWith,    -- ** Sequence computations   -- convertSeq, convertSeqWith, -  -- * Fusion-  module Data.Array.Accelerate.Trafo.Fusion,--  -- * Substitution-  module Data.Array.Accelerate.Trafo.Substitution,--  -- * Term equality-  Match(..), (:~:)(..),--  -- ** Auxiliary-  matchDelayedOpenAcc, encodeDelayedOpenAcc, hashDelayedOpenAcc,+  -- ** Scalar expressions+  Function, EltFunctionR,+  convertExp, convertFun,  ) where -import Control.DeepSeq-import Data.Typeable-+import Data.Array.Accelerate.Sugar.Array                ( ArraysR )+import Data.Array.Accelerate.Sugar.Elt                  ( EltR ) import Data.Array.Accelerate.Smart-import Data.Array.Accelerate.Pretty                     ( ) -- show instances-import Data.Array.Accelerate.Array.Sugar                ( Arrays, Elt )-import Data.Array.Accelerate.Trafo.Base-import Data.Array.Accelerate.Trafo.Fusion               hiding ( convertAcc, convertAfun ) -- to export types-import Data.Array.Accelerate.Trafo.Sharing              ( Function, FunctionR, Afunction, AfunctionR )-import Data.Array.Accelerate.Trafo.Substitution+import Data.Array.Accelerate.Trafo.Config+import Data.Array.Accelerate.Trafo.Delayed+import Data.Array.Accelerate.Trafo.Sharing              ( Afunction, ArraysFunctionR, Function, EltFunctionR ) import qualified Data.Array.Accelerate.AST              as AST import qualified Data.Array.Accelerate.Trafo.Fusion     as Fusion-import qualified Data.Array.Accelerate.Trafo.Rewrite    as Rewrite+import qualified Data.Array.Accelerate.Trafo.LetSplit   as LetSplit 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 +import Control.DeepSeq+ #ifdef ACCELERATE_DEBUG import Text.Printf import System.IO.Unsafe-import Data.Array.Accelerate.Debug                      hiding ( when )-import qualified Data.Array.Accelerate.Debug            as Debug+import Data.Array.Accelerate.Debug.Flags                hiding ( when )+import Data.Array.Accelerate.Debug.Timed #endif  --- Configuration--- ---------------data Phase = Phase-  {-    -- | Recover sharing of array computations?-    recoverAccSharing           :: Bool--    -- | 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--    -- | Fuse array computations? This also implies simplifying scalar-    --   expressions. NOTE: currently always enabled.-  , enableAccFusion             :: Bool--    -- | Convert segment length arrays into segment offset arrays?-  , convertOffsetOfSegment      :: Bool--    --   Vectorise maps and zipwiths in sequence computations to-    --   enable chunked execution?-  -- , vectoriseSequences          :: Bool-  }----- | The default method of converting from HOAS to de Bruijn; incorporating---   sharing recovery and fusion optimisation.----phases :: Phase-phases =  Phase-  { recoverAccSharing      = True-  , recoverExpSharing      = True-  , recoverSeqSharing      = True-  , floatOutAccFromExp     = True-  , enableAccFusion        = True-  , convertOffsetOfSegment = False-  -- , vectoriseSequences     = True-  }--when :: (a -> a) -> Bool -> a -> a-when f True  = f-when _ False = id-- -- HOAS -> de Bruijn conversion -- ----------------------------  -- | Convert a closed array expression to de Bruijn form while also --   incorporating sharing observation and array fusion. ---convertAcc :: Arrays arrs => Acc arrs -> DelayedAcc arrs-convertAcc = convertAccWith phases+convertAcc :: Acc arrs -> DelayedAcc (ArraysR arrs)+convertAcc = convertAccWith defaultOptions -convertAccWith :: Arrays arrs => Phase -> Acc arrs -> DelayedAcc arrs-convertAccWith Phase{..} acc-  = phase "array-fusion"           (Fusion.convertAcc enableAccFusion)+convertAccWith :: Config -> Acc arrs -> DelayedAcc (ArraysR arrs)+convertAccWith config+  = phase "array-fusion"           (Fusion.convertAccWith config)+  . phase "array-split-lets"       LetSplit.convertAcc   -- 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+  . phase "sharing-recovery"       (Sharing.convertAccWith config)   -- | Convert a unary function over array computations, incorporating sharing --   observation and array fusion ---convertAfun :: Afunction f => f -> DelayedAfun (AfunctionR f)-convertAfun = convertAfunWith phases+convertAfun :: Afunction f => f -> DelayedAfun (ArraysFunctionR f)+convertAfun = convertAfunWith defaultOptions -convertAfunWith :: Afunction f => Phase -> f -> DelayedAfun (AfunctionR f)-convertAfunWith Phase{..} acc-  = phase "array-fusion"           (Fusion.convertAfun enableAccFusion)+convertAfunWith :: Afunction f => Config -> f -> DelayedAfun (ArraysFunctionR f)+convertAfunWith config+  = phase "array-fusion"           (Fusion.convertAfunWith config)+  . phase "array-split-lets"       LetSplit.convertAfun   -- 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+  . phase "sharing-recovery"       (Sharing.convertAfunWith config)   -- | Convert a closed scalar expression, incorporating sharing observation and --   optimisation. ---convertExp :: Elt e => Exp e -> AST.Exp () e+convertExp :: Exp e -> AST.Exp () (EltR e) convertExp-  = phase "exp-simplify"      Rewrite.simplify-  . phase "sharing-recovery" (Sharing.convertExp (recoverExpSharing phases))+  = phase "exp-simplify"     Rewrite.simplifyExp+  . phase "sharing-recovery" Sharing.convertExp   -- | Convert closed scalar functions, incorporating sharing observation and --   optimisation. ---convertFun :: Function f => f -> AST.Fun () (FunctionR f)+convertFun :: Function f => f -> AST.Fun () (EltFunctionR f) convertFun-  = phase "exp-simplify"      Rewrite.simplify-  . phase "sharing-recovery" (Sharing.convertFun (recoverExpSharing phases))+  = phase "exp-simplify"     Rewrite.simplifyFun+  . phase "sharing-recovery" Sharing.convertFun  {-- -- | Convert a closed sequence computation, incorporating sharing observation and@@ -181,50 +111,19 @@ 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 "rewrite-segment-offset" Rewrite.convertSegmentsSeq `when` convertOffsetOfSegment   $ phase "sharing-recovery"       (Sharing.convertSeq recoverAccSharing recoverExpSharing recoverSeqSharing floatOutAccFromExp)   $ s --} --- Pretty printing--- --------------- -instance Arrays arrs => Show (Acc arrs) where-  show = withSimplStats . show . convertAcc--instance Afunction (Acc a -> f) => Show (Acc a -> f) where-  show = withSimplStats . show . convertAfun--instance Elt e => Show (Exp e) where-  show = withSimplStats . show . convertExp--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-+-- when :: (a -> a) -> Bool -> a -> a+-- when f True  = f+-- when _ False = id  -- Debugging -- --------- --- Attach simplifier statistics to the tail of the given string. Since the--- statistics rely on fully evaluating the expression this is difficult to do--- generally (without an additional deepseq), but easy enough for our show--- instances.------ For now, we just reset the statistics at the beginning of a conversion, and--- leave it to a backend to choose an appropriate moment to dump the summary.----withSimplStats :: String -> String-#ifdef ACCELERATE_DEBUG-withSimplStats x = unsafePerformIO $ do-  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. --@@ -236,6 +135,6 @@     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+phase _ f = f #endif 
src/Data/Array/Accelerate/Trafo/Algebra.hs view
@@ -1,6 +1,6 @@-{-# LANGUAGE CPP                 #-} {-# LANGUAGE GADTs               #-} {-# LANGUAGE LambdaCase          #-}+{-# LANGUAGE OverloadedStrings   #-} {-# LANGUAGE PatternGuards       #-} {-# LANGUAGE RankNTypes          #-} {-# LANGUAGE ScopedTypeVariables #-}@@ -10,10 +10,10 @@ {-# LANGUAGE ViewPatterns        #-} -- | -- Module      : Data.Array.Accelerate.Trafo.Algebra--- Copyright   : [2012..2017] Manuel M T Chakravarty, Gabriele Keller, Trevor L. McDonell+-- Copyright   : [2012..2020] The Accelerate Team -- License     : BSD3 ----- Maintainer  : Trevor L. McDonell <tmcdonell@cse.unsw.edu.au>+-- Maintainer  : Trevor L. McDonell <trevor.mcdonell@gmail.com> -- Stability   : experimental -- Portability : non-portable (GHC extensions) --@@ -27,70 +27,55 @@  ) where -import Data.Bits-import Data.Char-import Data.Monoid-import GHC.Float                                        ( float2Double, double2Float )-import Text.PrettyPrint.ANSI.Leijen-import Prelude                                          hiding ( exp )-import qualified Prelude                                as P---- friends import Data.Array.Accelerate.AST+import Data.Array.Accelerate.AST.Var import Data.Array.Accelerate.Analysis.Match-import Data.Array.Accelerate.Array.Sugar                hiding ( Any )-import Data.Array.Accelerate.Pretty.Print               ( prettyPrim )-import Data.Array.Accelerate.Product-import Data.Array.Accelerate.Trafo.Base+import Data.Array.Accelerate.Pretty.Print                           ( primOperator, isInfix, opName )+import Data.Array.Accelerate.Trafo.Environment import Data.Array.Accelerate.Type -import qualified Data.Array.Accelerate.Debug            as Stats+import qualified Data.Array.Accelerate.Debug.Stats                  as Stats +import Data.Bits+import Data.Monoid+import Data.Text                                                    ( Text )+import Data.Text.Prettyprint.Doc+import Data.Text.Prettyprint.Doc.Render.Text+import GHC.Float                                                    ( float2Double, double2Float )+import Prelude                                                      hiding ( exp )+import qualified Prelude                                            as P + -- Propagate constant expressions, which are either constant valued expressions -- or constant let bindings. Be careful not to follow self-cycles. -- propagate-    :: forall acc env aenv exp. Kit acc-    => Gamma acc env env aenv-    -> PreOpenExp acc env aenv exp+    :: forall env aenv exp.+       Gamma env env aenv+    -> OpenExp env aenv exp     -> Maybe exp propagate env = cvtE   where-    cvtE :: PreOpenExp acc env aenv e -> Maybe e+    cvtE :: OpenExp env aenv e -> Maybe e     cvtE exp = case exp of-      Const c                                   -> Just (toElt c)+      Const _ c                                 -> Just c       PrimConst c                               -> Just (evalPrimConst c)-      Prj ix (Var v) | Tuple t <- prjExp v env  -> cvtT ix t-      Prj ix e       | Just c  <- cvtE e        -> cvtP ix (fromTuple c)-      Var ix+      Evar (Var _  ix)         | e             <- prjExp ix env-        , Nothing       <- match exp e          -> cvtE e-      ---      IndexHead (cvtE -> Just (_  :. z))        -> Just z-      IndexTail (cvtE -> Just (sh :. _))        -> Just sh+        , Nothing       <- matchOpenExp exp e   -> cvtE e+      Nil                                       -> Just ()+      Pair e1 e2                                -> (,) <$> cvtE e1 <*> cvtE e2       _                                         -> Nothing -    cvtP :: TupleIdx t e -> t -> Maybe e-    cvtP ZeroTupIdx       (_, v)   = Just v-    cvtP (SuccTupIdx idx) (tup, _) = cvtP idx tup -    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 -- evalPrimApp-    :: forall acc env aenv a r. (Kit acc, Elt a, Elt r)-    => Gamma acc env env aenv+    :: forall env aenv a r.+       Gamma env env aenv     -> PrimFun (a -> r)-    -> PreOpenExp acc env aenv a-    -> (Any, PreOpenExp acc env aenv r)+    -> OpenExp env aenv a+    -> (Any, OpenExp 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@@ -160,9 +145,6 @@       PrimLAnd                  -> evalLAnd x env       PrimLOr                   -> evalLOr x env       PrimLNot                  -> evalLNot x env-      PrimOrd                   -> evalOrd x env-      PrimChr                   -> evalChr x env-      PrimBoolToInt             -> evalBoolToInt x env       PrimFromIntegral ta tb    -> evalFromIntegral ta tb x env       PrimToFloating ta tb      -> evalToFloating ta tb x env @@ -172,11 +154,11 @@ -- to the left of the operator. Returning Nothing indicates no change is made. -- commutes-    :: forall acc env aenv a r. Kit acc-    => PrimFun (a -> r)-    -> PreOpenExp acc env aenv a-    -> Gamma acc env env aenv-    -> Maybe (PreOpenExp acc env aenv a)+    :: forall env aenv a r.+       PrimFun (a -> r)+    -> OpenExp env aenv a+    -> Gamma env env aenv+    -> Maybe (OpenExp env aenv a) commutes f x env = case f of   PrimAdd _     -> swizzle x   PrimMul _     -> swizzle x@@ -189,12 +171,12 @@   PrimMin _     -> swizzle x   _             -> Nothing   where-    swizzle :: PreOpenExp acc env aenv (b,b) -> Maybe (PreOpenExp acc env aenv (b,b))-    swizzle (Tuple (NilTup `SnocTup` a `SnocTup` b))+    swizzle :: OpenExp env aenv (b,b) -> Maybe (OpenExp env aenv (b,b))+    swizzle (Pair a b)       | Nothing         <- propagate env a       , Just _          <- propagate env b       = Stats.ruleFired (pprFun "commutes" f)-      $ Just $ Tuple (NilTup `SnocTup` b `SnocTup` a)+      $ Just $ Pair b a  --    TLM: changing the ordering here when neither term can be reduced can be --         disadvantageous: for example in (x &&* y), the user might have put a@@ -226,8 +208,8 @@ associates     :: (Elt a, Elt r)     => PrimFun (a -> r)-    -> PreOpenExp acc env aenv a-    -> Maybe (PreOpenExp acc env aenv r)+    -> OpenExp env aenv a+    -> Maybe (OpenExp env aenv r) associates fun exp = case fun of   PrimAdd _     -> swizzle fun exp [PrimAdd ty, PrimSub ty]   PrimSub _     -> swizzle fun exp [PrimAdd ty, PrimSub ty]@@ -239,7 +221,7 @@     ty  = undefined     ops = [ PrimMul ty, PrimFDiv ty, PrimAdd ty, PrimSub ty, PrimBAnd ty, PrimBOr ty, PrimBXor ty ] -    swizzle :: (Elt a, Elt r) => PrimFun (a -> r) -> PreOpenExp acc env aenv a -> [PrimFun (a -> r)] -> Maybe (PreOpenExp acc env aenv r)+    swizzle :: (Elt a, Elt r) => PrimFun (a -> r) -> OpenExp env aenv a -> [PrimFun (a -> r)] -> Maybe (OpenExp env aenv r)     swizzle f x lvl       | Just Refl       <- matches f ops       , Just (a,bc)     <- untup2 x@@ -266,58 +248,90 @@ -- Helper functions -- ---------------- -type a :-> b = forall acc env aenv. Kit acc => PreOpenExp acc env aenv a -> Gamma acc env env aenv -> Maybe (PreOpenExp acc env aenv b)+type a :-> b = forall env aenv. OpenExp env aenv a -> Gamma env env aenv -> Maybe (OpenExp env aenv b) -eval1 :: Elt b => (a -> b) -> a :-> b-eval1 f x env-  | Just a <- propagate env x   = Stats.substitution "constant fold" . Just $ Const (fromElt (f a))+eval1 :: SingleType b -> (a -> b) -> a :-> b+eval1 tp f x env+  | Just a <- propagate env x   = Stats.substitution "constant fold" . Just $ Const (SingleScalarType tp) (f a)   | otherwise                   = Nothing -eval2 :: Elt c => (a -> b -> c) -> (a,b) :-> c-eval2 f (untup2 -> Just (x,y)) env+eval2 :: SingleType c -> (a -> b -> c) -> (a,b) :-> c+eval2 tp f (untup2 -> Just (x,y)) env   | Just a <- propagate env x   , Just b <- propagate env y   = Stats.substitution "constant fold"-  $ Just $ Const (fromElt (f a b))+  $ Just $ Const (SingleScalarType tp) (f a b)+eval2 _ _ _ _+  = Nothing -eval2 _ _ _+fromBool :: Bool -> PrimBool+fromBool False = 0+fromBool True  = 1++toBool :: PrimBool -> Bool+toBool 0 = False+toBool _ = True++bool1 :: (a -> Bool) -> a :-> PrimBool+bool1 f x env+  | Just a <- propagate env x+  = Stats.substitution "constant fold"+  . Just $ Const scalarTypeWord8 (fromBool (f a))+bool1 _ _ _   = 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)+bool2 :: (a -> b -> Bool) -> (a,b) :-> PrimBool+bool2 f (untup2 -> Just (x,y)) env+  | Just a <- propagate env x+  , Just b <- propagate env y+  = Stats.substitution "constant fold"+  $ Just $ Const scalarTypeWord8 (fromBool (f a b))+bool2 _ _ _+  = Nothing -untup2 :: PreOpenExp acc env aenv (a, b) -> Maybe (PreOpenExp acc env aenv a, PreOpenExp acc env aenv b)+tup2 :: (OpenExp env aenv a, OpenExp env aenv b) -> OpenExp env aenv (a, b)+tup2 (a,b) = Pair a b++untup2 :: OpenExp env aenv (a, b) -> Maybe (OpenExp env aenv a, OpenExp env aenv b) untup2 exp-  | Tuple (NilTup `SnocTup` a `SnocTup` b) <- exp = Just (a, b)-  | otherwise                                     = Nothing+  | Pair a b <- exp = Just (a, b)+  | otherwise       = Nothing  -pprFun :: String -> PrimFun f -> String-pprFun rule f = show $ text rule <+> snd (prettyPrim f)+pprFun :: Text -> PrimFun f -> Text+pprFun rule f+  = renderStrict+  . layoutCompact+  $ pretty rule <+> f'+  where+    op = primOperator f+    f' = if isInfix op+           then parens (opName op)+           else opName op   -- Methods of Num -- -------------- -evalAdd :: Elt a => NumType a -> (a,a) :-> a-evalAdd (IntegralNumType ty) | IntegralDict <- integralDict ty = evalAdd'-evalAdd (FloatingNumType ty) | FloatingDict <- floatingDict ty = evalAdd'+evalAdd :: NumType a -> (a,a) :-> a+evalAdd ty@(IntegralNumType ty') | IntegralDict <- integralDict ty' = evalAdd' ty+evalAdd ty@(FloatingNumType ty') | FloatingDict <- floatingDict ty' = evalAdd' ty -evalAdd' :: (Elt a, Eq a, Num a) => (a,a) :-> a-evalAdd' (untup2 -> Just (x,y)) env+evalAdd' :: (Eq a, Num a) => NumType a -> (a,a) :-> a+evalAdd' _  (untup2 -> Just (x,y)) env   | Just a      <- propagate env x   , a == 0   = Stats.ruleFired "x+0" $ Just y -evalAdd' arg env-  = eval2 (+) arg env+evalAdd' ty arg env+  = eval2 (NumSingleType ty) (+) arg env  -evalSub :: Elt a => NumType a -> (a,a) :-> a+evalSub :: NumType a -> (a,a) :-> a evalSub ty@(IntegralNumType ty') | IntegralDict <- integralDict ty' = evalSub' ty evalSub ty@(FloatingNumType ty') | FloatingDict <- floatingDict ty' = evalSub' ty -evalSub' :: forall a. (Elt a, Eq a, Num a) => NumType a -> (a,a) :-> a+evalSub' :: forall a. (Eq a, Num a) => NumType a -> (a,a) :-> a evalSub' ty (untup2 -> Just (x,y)) env   | Just b      <- propagate env y   , b == 0@@ -326,22 +340,25 @@   | Nothing     <- propagate env x   , Just b      <- propagate env y   = Stats.ruleFired "-y+x"-  $ Just . snd $ evalPrimApp env (PrimAdd ty) (Tuple $ NilTup `SnocTup` Const (fromElt (-b)) `SnocTup` x)+  $ Just . snd $ evalPrimApp env (PrimAdd ty) (Const tp (-b) `Pair` x)+  -- (Tuple $ NilTup `SnocTup` Const (fromElt (-b)) `SnocTup` x) -  | Just Refl   <- match x y+  | Just Refl   <- matchOpenExp x y   = Stats.ruleFired "x-x"-  $ Just $ Const (fromElt (0::a))+  $ Just $ Const tp 0+  where+    tp = SingleScalarType $ NumSingleType ty -evalSub' _ arg env-  = eval2 (-) arg env+evalSub' ty arg env+  = eval2 (NumSingleType ty) (-) arg env  -evalMul :: Elt a => NumType a -> (a,a) :-> a-evalMul (IntegralNumType ty) | IntegralDict <- integralDict ty = evalMul'-evalMul (FloatingNumType ty) | FloatingDict <- floatingDict ty = evalMul'+evalMul :: NumType a -> (a,a) :-> a+evalMul ty@(IntegralNumType ty') | IntegralDict <- integralDict ty' = evalMul' ty+evalMul ty@(FloatingNumType ty') | FloatingDict <- floatingDict ty' = evalMul' ty -evalMul' :: (Elt a, Eq a, Num a) => (a,a) :-> a-evalMul' (untup2 -> Just (x,y)) env+evalMul' :: (Eq a, Num a) => NumType a -> (a,a) :-> a+evalMul' _  (untup2 -> Just (x,y)) env   | Just a      <- propagate env x   , Nothing     <- propagate env y   = case a of@@ -349,21 +366,21 @@       1         -> Stats.ruleFired "x*1" $ Just y       _         -> Nothing -evalMul' arg env-  = eval2 (*) arg env+evalMul' ty arg env+  = eval2 (NumSingleType ty) (*) arg env -evalNeg :: Elt a => NumType a -> a :-> a+evalNeg :: NumType a -> a :-> a 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+evalNeg (IntegralNumType ty) x env | IntegralDict <- integralDict ty = eval1 (NumSingleType $ IntegralNumType ty) negate x env+evalNeg (FloatingNumType ty) x env | FloatingDict <- floatingDict ty = eval1 (NumSingleType $ FloatingNumType ty) negate x env -evalAbs :: Elt a => NumType a -> a :-> a-evalAbs (IntegralNumType ty) | IntegralDict <- integralDict ty = eval1 abs-evalAbs (FloatingNumType ty) | FloatingDict <- floatingDict ty = eval1 abs+evalAbs :: NumType a -> a :-> a+evalAbs (IntegralNumType ty) | IntegralDict <- integralDict ty = eval1 (NumSingleType $ IntegralNumType ty) abs+evalAbs (FloatingNumType ty) | FloatingDict <- floatingDict ty = eval1 (NumSingleType $ FloatingNumType ty) abs -evalSig :: Elt a => NumType a -> a :-> a-evalSig (IntegralNumType ty) | IntegralDict <- integralDict ty = eval1 signum-evalSig (FloatingNumType ty) | FloatingDict <- floatingDict ty = eval1 signum+evalSig :: NumType a -> a :-> a+evalSig (IntegralNumType ty) | IntegralDict <- integralDict ty = eval1 (NumSingleType $ IntegralNumType ty) signum+evalSig (FloatingNumType ty) | FloatingDict <- floatingDict ty = eval1 (NumSingleType $ FloatingNumType ty) signum   -- Methods of Integral & Bits@@ -387,17 +404,19 @@  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+  | IntegralDict <- integralDict ty+  , Just (x, y)  <- untup2 exp+  , Just b       <- propagate env y   = case b of       0 -> Nothing-      1 -> Stats.ruleFired "quotRem x 1" $ Just (tup2 (x, Const (fromElt (0::a))))+      1 -> Stats.ruleFired "quotRem x 1" $ Just (tup2 (x, Const tp 0))       _ -> 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))+                               in  tup2 (Const tp u, Const tp v)+  where+    tp = SingleScalarType $ NumSingleType $ IntegralNumType ty evalQuotRem _ _ _   = Nothing @@ -420,356 +439,289 @@  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+  | IntegralDict <- integralDict ty+  , Just (x, y)  <- untup2 exp+  , Just b       <- propagate env y   = case b of       0 -> Nothing-      1 -> Stats.ruleFired "divMod x 1" $ Just (tup2 (x, Const (fromElt (0::a))))+      1 -> Stats.ruleFired "divMod x 1" $ Just (tup2 (x, Const tp 0))       _ -> 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))+                               in  tup2 (Const tp u, Const tp v)+  where+    tp = SingleScalarType $ NumSingleType $ IntegralNumType ty evalDivMod _ _ _   = Nothing -evalBAnd :: Elt a => IntegralType a -> (a,a) :-> a-evalBAnd ty | IntegralDict <- integralDict ty = eval2 (.&.)+evalBAnd :: IntegralType a -> (a,a) :-> a+evalBAnd ty | IntegralDict <- integralDict ty = eval2 (NumSingleType $ IntegralNumType ty) (.&.) -evalBOr :: Elt a => IntegralType a -> (a,a) :-> a-evalBOr ty | IntegralDict <- integralDict ty = eval2 (.|.)+evalBOr :: IntegralType a -> (a,a) :-> a+evalBOr ty | IntegralDict <- integralDict ty = evalBOr' ty -evalBXor :: Elt a => IntegralType a -> (a,a) :-> a-evalBXor ty | IntegralDict <- integralDict ty = eval2 xor+evalBOr' :: (Eq a, Num a, Bits a) => IntegralType a -> (a,a) :-> a+evalBOr' _ (untup2 -> Just (x,y)) env+  | Just 0 <- propagate env x+  = Stats.ruleFired "x .|. 0" $ Just y -evalBNot :: Elt a => IntegralType a -> a :-> a-evalBNot ty | IntegralDict <- integralDict ty = eval1 complement+evalBOr' ty arg env+  = eval2 (NumSingleType $ IntegralNumType ty) (.|.) arg env -evalBShiftL :: Elt a => IntegralType a -> (a,Int) :-> a+evalBXor :: IntegralType a -> (a,a) :-> a+evalBXor ty | IntegralDict <- integralDict ty = eval2 (NumSingleType $ IntegralNumType ty) xor++evalBNot :: IntegralType a -> a :-> a+evalBNot ty | IntegralDict <- integralDict ty = eval1 (NumSingleType $ IntegralNumType ty) complement++evalBShiftL :: IntegralType a -> (a,Int) :-> a evalBShiftL _ (untup2 -> Just (x,i)) env   | Just 0 <- propagate env i   = Stats.ruleFired "x `shiftL` 0" $ Just x  evalBShiftL ty arg env-  | IntegralDict <- integralDict ty = eval2 shiftL arg env+  | IntegralDict <- integralDict ty = eval2 (NumSingleType $ IntegralNumType ty) shiftL arg env -evalBShiftR :: Elt a => IntegralType a -> (a,Int) :-> a+evalBShiftR :: IntegralType a -> (a,Int) :-> a evalBShiftR _ (untup2 -> Just (x,i)) env   | Just 0 <- propagate env i   = Stats.ruleFired "x `shiftR` 0" $ Just x  evalBShiftR ty arg env-  | IntegralDict <- integralDict ty = eval2 shiftR arg env+  | IntegralDict <- integralDict ty = eval2 (NumSingleType $ IntegralNumType ty) shiftR arg env -evalBRotateL :: Elt a => IntegralType a -> (a,Int) :-> a+evalBRotateL :: IntegralType a -> (a,Int) :-> a evalBRotateL _ (untup2 -> Just (x,i)) env   | Just 0 <- propagate env i   = Stats.ruleFired "x `rotateL` 0" $ Just x evalBRotateL ty arg env-  | IntegralDict <- integralDict ty = eval2 rotateL arg env+  | IntegralDict <- integralDict ty = eval2 (NumSingleType $ IntegralNumType ty) rotateL arg env -evalBRotateR :: Elt a => IntegralType a -> (a,Int) :-> a+evalBRotateR :: IntegralType a -> (a,Int) :-> a evalBRotateR _ (untup2 -> Just (x,i)) env   | Just 0 <- propagate env i   = Stats.ruleFired "x `rotateR` 0" $ Just x evalBRotateR ty arg env-  | IntegralDict <- integralDict ty = eval2 rotateR arg env+  | IntegralDict <- integralDict ty = eval2 (NumSingleType $ IntegralNumType ty) rotateR arg env  evalPopCount :: IntegralType a -> a :-> Int-evalPopCount ty | IntegralDict <- integralDict ty = eval1 popCount+evalPopCount ty | IntegralDict <- integralDict ty = eval1 (NumSingleType $ IntegralNumType TypeInt) 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+evalCountLeadingZeros ty | IntegralDict <- integralDict ty = eval1 (NumSingleType $ IntegralNumType TypeInt) countLeadingZeros  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+evalCountTrailingZeros ty | IntegralDict <- integralDict ty = eval1 (NumSingleType $ IntegralNumType TypeInt) countTrailingZeros   -- Methods of Fractional & Floating -- -------------------------------- -evalFDiv :: Elt a => FloatingType a -> (a,a) :-> a-evalFDiv ty | FloatingDict <- floatingDict ty = evalFDiv'+evalFDiv :: FloatingType a -> (a,a) :-> a+evalFDiv ty | FloatingDict <- floatingDict ty = evalFDiv' ty -evalFDiv' :: (Elt a, Fractional a, Eq a) => (a,a) :-> a-evalFDiv' (untup2 -> Just (x,y)) env+evalFDiv' :: (Fractional a, Eq a) => FloatingType a -> (a,a) :-> a+evalFDiv' _ (untup2 -> Just (x,y)) env   | Just 1      <- propagate env y   = Stats.ruleFired "x/1" $ Just x -evalFDiv' arg env-  = eval2 (/) arg env+evalFDiv' ty arg env+  = eval2 (NumSingleType $ FloatingNumType ty) (/) arg env  -evalRecip :: Elt a => FloatingType a -> a :-> a-evalRecip ty | FloatingDict <- floatingDict ty = eval1 recip+evalRecip :: FloatingType a -> a :-> a+evalRecip ty | FloatingDict <- floatingDict ty = eval1 (NumSingleType $ FloatingNumType ty) recip -evalSin :: Elt a => FloatingType a -> a :-> a-evalSin ty | FloatingDict <- floatingDict ty = eval1 sin+evalSin :: FloatingType a -> a :-> a+evalSin ty | FloatingDict <- floatingDict ty = eval1 (NumSingleType $ FloatingNumType ty) sin -evalCos :: Elt a => FloatingType a -> a :-> a-evalCos ty | FloatingDict <- floatingDict ty = eval1 cos+evalCos :: FloatingType a -> a :-> a+evalCos ty | FloatingDict <- floatingDict ty = eval1 (NumSingleType $ FloatingNumType ty) cos -evalTan :: Elt a => FloatingType a -> a :-> a-evalTan ty | FloatingDict <- floatingDict ty = eval1 tan+evalTan :: FloatingType a -> a :-> a+evalTan ty | FloatingDict <- floatingDict ty = eval1 (NumSingleType $ FloatingNumType ty) tan -evalAsin :: Elt a => FloatingType a -> a :-> a-evalAsin ty | FloatingDict <- floatingDict ty = eval1 asin+evalAsin :: FloatingType a -> a :-> a+evalAsin ty | FloatingDict <- floatingDict ty = eval1 (NumSingleType $ FloatingNumType ty) asin -evalAcos :: Elt a => FloatingType a -> a :-> a-evalAcos ty | FloatingDict <- floatingDict ty = eval1 acos+evalAcos :: FloatingType a -> a :-> a+evalAcos ty | FloatingDict <- floatingDict ty = eval1 (NumSingleType $ FloatingNumType ty) acos -evalAtan :: Elt a => FloatingType a -> a :-> a-evalAtan ty | FloatingDict <- floatingDict ty = eval1 atan+evalAtan :: FloatingType a -> a :-> a+evalAtan ty | FloatingDict <- floatingDict ty = eval1 (NumSingleType $ FloatingNumType ty) atan -evalSinh :: Elt a => FloatingType a -> a :-> a-evalSinh ty | FloatingDict <- floatingDict ty = eval1 sinh+evalSinh :: FloatingType a -> a :-> a+evalSinh ty | FloatingDict <- floatingDict ty = eval1 (NumSingleType $ FloatingNumType ty) sinh -evalCosh :: Elt a => FloatingType a -> a :-> a-evalCosh ty | FloatingDict <- floatingDict ty = eval1 cosh+evalCosh :: FloatingType a -> a :-> a+evalCosh ty | FloatingDict <- floatingDict ty = eval1 (NumSingleType $ FloatingNumType ty) cosh -evalTanh :: Elt a => FloatingType a -> a :-> a-evalTanh ty | FloatingDict <- floatingDict ty = eval1 tanh+evalTanh :: FloatingType a -> a :-> a+evalTanh ty | FloatingDict <- floatingDict ty = eval1 (NumSingleType $ FloatingNumType ty) tanh -evalAsinh :: Elt a => FloatingType a -> a :-> a-evalAsinh ty | FloatingDict <- floatingDict ty = eval1 asinh+evalAsinh :: FloatingType a -> a :-> a+evalAsinh ty | FloatingDict <- floatingDict ty = eval1 (NumSingleType $ FloatingNumType ty) asinh -evalAcosh :: Elt a => FloatingType a -> a :-> a-evalAcosh ty | FloatingDict <- floatingDict ty = eval1 acosh+evalAcosh :: FloatingType a -> a :-> a+evalAcosh ty | FloatingDict <- floatingDict ty = eval1 (NumSingleType $ FloatingNumType ty) acosh -evalAtanh :: Elt a => FloatingType a -> a :-> a-evalAtanh ty | FloatingDict <- floatingDict ty = eval1 atanh+evalAtanh :: FloatingType a -> a :-> a+evalAtanh ty | FloatingDict <- floatingDict ty = eval1 (NumSingleType $ FloatingNumType ty) atanh -evalExpFloating :: Elt a => FloatingType a -> a :-> a-evalExpFloating ty | FloatingDict <- floatingDict ty = eval1 P.exp+evalExpFloating :: FloatingType a -> a :-> a+evalExpFloating ty | FloatingDict <- floatingDict ty = eval1 (NumSingleType $ FloatingNumType ty) P.exp -evalSqrt :: Elt a => FloatingType a -> a :-> a-evalSqrt ty | FloatingDict <- floatingDict ty = eval1 sqrt+evalSqrt :: FloatingType a -> a :-> a+evalSqrt ty | FloatingDict <- floatingDict ty = eval1 (NumSingleType $ FloatingNumType ty) sqrt -evalLog :: Elt a => FloatingType a -> a :-> a-evalLog ty | FloatingDict <- floatingDict ty = eval1 log+evalLog :: FloatingType a -> a :-> a+evalLog ty | FloatingDict <- floatingDict ty = eval1 (NumSingleType $ FloatingNumType ty) log -evalFPow :: Elt a => FloatingType a -> (a,a) :-> a-evalFPow ty | FloatingDict <- floatingDict ty = eval2 (**)+evalFPow :: FloatingType a -> (a,a) :-> a+evalFPow ty | FloatingDict <- floatingDict ty = eval2 (NumSingleType $ FloatingNumType ty) (**) -evalLogBase :: Elt a => FloatingType a -> (a,a) :-> a-evalLogBase ty | FloatingDict <- floatingDict ty = eval2 logBase+evalLogBase :: FloatingType a -> (a,a) :-> a+evalLogBase ty | FloatingDict <- floatingDict ty = eval2 (NumSingleType $ FloatingNumType ty) logBase -evalAtan2 :: Elt a => FloatingType a -> (a,a) :-> a-evalAtan2 ty | FloatingDict <- floatingDict ty = eval2 atan2+evalAtan2 :: FloatingType a -> (a,a) :-> a+evalAtan2 ty | FloatingDict <- floatingDict ty = eval2 (NumSingleType $ FloatingNumType ty) atan2 -evalTruncate :: Elt b => FloatingType a -> IntegralType b -> a :-> b+evalTruncate :: FloatingType a -> IntegralType b -> a :-> b evalTruncate ta tb   | FloatingDict <- floatingDict ta-  , IntegralDict <- integralDict tb = eval1 truncate+  , IntegralDict <- integralDict tb+  = eval1 (NumSingleType $ IntegralNumType tb) truncate -evalRound :: Elt b => FloatingType a -> IntegralType b -> a :-> b+evalRound :: FloatingType a -> IntegralType b -> a :-> b evalRound ta tb   | FloatingDict <- floatingDict ta-  , IntegralDict <- integralDict tb = eval1 round+  , IntegralDict <- integralDict tb+  = eval1 (NumSingleType $ IntegralNumType tb) round -evalFloor :: Elt b => FloatingType a -> IntegralType b -> a :-> b+evalFloor :: FloatingType a -> IntegralType b -> a :-> b evalFloor ta tb   | FloatingDict <- floatingDict ta-  , IntegralDict <- integralDict tb = eval1 floor+  , IntegralDict <- integralDict tb+  = eval1 (NumSingleType $ IntegralNumType tb) floor -evalCeiling :: Elt b => FloatingType a -> IntegralType b -> a :-> b+evalCeiling :: FloatingType a -> IntegralType b -> a :-> b evalCeiling ta tb   | FloatingDict <- floatingDict ta-  , IntegralDict <- integralDict tb = eval1 ceiling+  , IntegralDict <- integralDict tb+  = eval1 (NumSingleType $ IntegralNumType tb) ceiling -evalIsNaN :: FloatingType a -> a :-> Bool-evalIsNaN ty | FloatingDict <- floatingDict ty = eval1 isNaN+evalIsNaN :: FloatingType a -> a :-> PrimBool+evalIsNaN ty | FloatingDict <- floatingDict ty = bool1 isNaN -evalIsInfinite :: FloatingType a -> a :-> Bool-evalIsInfinite ty | FloatingDict <- floatingDict ty = eval1 isInfinite+evalIsInfinite :: FloatingType a -> a :-> PrimBool+evalIsInfinite ty | FloatingDict <- floatingDict ty = bool1 isInfinite   -- Relational & Equality -- --------------------- -evalLt :: SingleType a -> (a,a) :-> Bool-evalLt (NumSingleType (IntegralNumType ty)) | IntegralDict <- integralDict ty = eval2 (<)-evalLt (NumSingleType (FloatingNumType ty)) | FloatingDict <- floatingDict ty = eval2 (<)-evalLt (NonNumSingleType ty)                | NonNumDict   <- nonNumDict ty   = eval2 (<)---- evalLt (SingleScalarType s) =---   case s of---     NumSingleType (IntegralNumType t) | IntegralDict <- integralDict t -> eval2 (<)---     NumSingleType (FloatingNumType t) | FloatingDict <- floatingDict t -> eval2 (<)---     NonNumSingleType t                | NonNumDict   <- nonNumDict t   -> eval2 (<)--- evalLt (VectorScalarType (Vector2Type s)) =---   case s of---     NumSingleType (IntegralNumType t) | IntegralDict <- t -> eval2 (<)---     NumSingleType (FloatingNumType t) | FloatingDict <- t -> eval2 (<)---     NonNumSingleType t                | NonNumDict   <- t -> eval2 (<)--evalGt :: SingleType a -> (a,a) :-> Bool-evalGt (NumSingleType (IntegralNumType ty)) | IntegralDict <- integralDict ty = eval2 (>)-evalGt (NumSingleType (FloatingNumType ty)) | FloatingDict <- floatingDict ty = eval2 (>)-evalGt (NonNumSingleType ty)                | NonNumDict   <- nonNumDict ty   = eval2 (>)---- evalGt (SingleScalarType s) =---   case s of---     NumSingleType (IntegralNumType t) | IntegralDict <- integralDict t -> eval2 (>)---     NumSingleType (FloatingNumType t) | FloatingDict <- floatingDict t -> eval2 (>)---     NonNumSingleType t                | NonNumDict   <- nonNumDict t   -> eval2 (>)--evalLtEq :: SingleType a -> (a,a) :-> Bool-evalLtEq (NumSingleType (IntegralNumType ty)) | IntegralDict <- integralDict ty = eval2 (<=)-evalLtEq (NumSingleType (FloatingNumType ty)) | FloatingDict <- floatingDict ty = eval2 (<=)-evalLtEq (NonNumSingleType ty)                | NonNumDict   <- nonNumDict ty   = eval2 (<=)---- evalLtEq (SingleScalarType s) =---   case s of---     NumSingleType (IntegralNumType t) | IntegralDict <- integralDict t -> eval2 (<=)---     NumSingleType (FloatingNumType t) | FloatingDict <- floatingDict t -> eval2 (<=)---     NonNumSingleType t                | NonNumDict   <- nonNumDict t   -> eval2 (<=)--evalGtEq :: SingleType a -> (a,a) :-> Bool-evalGtEq (NumSingleType (IntegralNumType ty)) | IntegralDict <- integralDict ty = eval2 (>=)-evalGtEq (NumSingleType (FloatingNumType ty)) | FloatingDict <- floatingDict ty = eval2 (>=)-evalGtEq (NonNumSingleType ty)                | NonNumDict   <- nonNumDict ty   = eval2 (>=)---- evalGtEq (SingleScalarType s) =---   case s of---     NumSingleType (IntegralNumType t) | IntegralDict <- integralDict t -> eval2 (>=)---     NumSingleType (FloatingNumType t) | FloatingDict <- floatingDict t -> eval2 (>=)---     NonNumSingleType t                | NonNumDict   <- nonNumDict t   -> eval2 (>=)--evalEq :: SingleType a -> (a,a) :-> Bool-evalEq (NumSingleType (IntegralNumType ty)) | IntegralDict <- integralDict ty = eval2 (==)-evalEq (NumSingleType (FloatingNumType ty)) | FloatingDict <- floatingDict ty = eval2 (==)-evalEq (NonNumSingleType ty)                | NonNumDict   <- nonNumDict ty   = eval2 (==)---- evalEq (SingleScalarType s) =---   case s of---     NumSingleType (IntegralNumType t) | IntegralDict <- integralDict t -> eval2 (==)---     NumSingleType (FloatingNumType t) | FloatingDict <- floatingDict t -> eval2 (==)---     NonNumSingleType t                | NonNumDict   <- nonNumDict t   -> eval2 (==)+evalLt :: SingleType a -> (a,a) :-> PrimBool+evalLt (NumSingleType (IntegralNumType ty)) | IntegralDict <- integralDict ty = bool2 (<)+evalLt (NumSingleType (FloatingNumType ty)) | FloatingDict <- floatingDict ty = bool2 (<) -evalNEq :: SingleType a -> (a,a) :-> Bool-evalNEq (NumSingleType (IntegralNumType ty)) | IntegralDict <- integralDict ty = eval2 (/=)-evalNEq (NumSingleType (FloatingNumType ty)) | FloatingDict <- floatingDict ty = eval2 (/=)-evalNEq (NonNumSingleType ty)                | NonNumDict   <- nonNumDict ty   = eval2 (/=)+evalGt :: SingleType a -> (a,a) :-> PrimBool+evalGt (NumSingleType (IntegralNumType ty)) | IntegralDict <- integralDict ty = bool2 (>)+evalGt (NumSingleType (FloatingNumType ty)) | FloatingDict <- floatingDict ty = bool2 (>) --- evalNEq (SingleScalarType s) =---   case s of---     NumSingleType (IntegralNumType t) | IntegralDict <- integralDict t -> eval2 (/=)---     NumSingleType (FloatingNumType t) | FloatingDict <- floatingDict t -> eval2 (/=)---     NonNumSingleType t                | NonNumDict   <- nonNumDict t   -> eval2 (/=)+evalLtEq :: SingleType a -> (a,a) :-> PrimBool+evalLtEq (NumSingleType (IntegralNumType ty)) | IntegralDict <- integralDict ty = bool2 (<=)+evalLtEq (NumSingleType (FloatingNumType ty)) | FloatingDict <- floatingDict ty = bool2 (<=) -evalMax :: Elt a => SingleType a -> (a,a) :-> a-evalMax (NumSingleType (IntegralNumType ty)) | IntegralDict <- integralDict ty = eval2 max-evalMax (NumSingleType (FloatingNumType ty)) | FloatingDict <- floatingDict ty = eval2 max-evalMax (NonNumSingleType ty)                | NonNumDict   <- nonNumDict ty   = eval2 max+evalGtEq :: SingleType a -> (a,a) :-> PrimBool+evalGtEq (NumSingleType (IntegralNumType ty)) | IntegralDict <- integralDict ty = bool2 (>=)+evalGtEq (NumSingleType (FloatingNumType ty)) | FloatingDict <- floatingDict ty = bool2 (>=) --- evalMax (SingleScalarType s) =---   case s of---     NumSingleType (IntegralNumType t) | IntegralDict <- integralDict t -> eval2 max---     NumSingleType (FloatingNumType t) | FloatingDict <- floatingDict t -> eval2 max---     NonNumSingleType t                | NonNumDict   <- nonNumDict t   -> eval2 max+evalEq :: SingleType a -> (a,a) :-> PrimBool+evalEq (NumSingleType (IntegralNumType ty)) | IntegralDict <- integralDict ty = bool2 (==)+evalEq (NumSingleType (FloatingNumType ty)) | FloatingDict <- floatingDict ty = bool2 (==) -evalMin :: Elt a => SingleType a -> (a,a) :-> a-evalMin (NumSingleType (IntegralNumType ty)) | IntegralDict <- integralDict ty = eval2 min-evalMin (NumSingleType (FloatingNumType ty)) | FloatingDict <- floatingDict ty = eval2 min-evalMin (NonNumSingleType ty)                | NonNumDict   <- nonNumDict ty   = eval2 min+evalNEq :: SingleType a -> (a,a) :-> PrimBool+evalNEq (NumSingleType (IntegralNumType ty)) | IntegralDict <- integralDict ty = bool2 (/=)+evalNEq (NumSingleType (FloatingNumType ty)) | FloatingDict <- floatingDict ty = bool2 (/=) --- evalMin (SingleScalarType s) =---   case s of---     NumSingleType (IntegralNumType t) | IntegralDict <- integralDict t -> eval2 min---     NumSingleType (FloatingNumType t) | FloatingDict <- floatingDict t -> eval2 min---     NonNumSingleType t                | NonNumDict   <- nonNumDict t   -> eval2 min+evalMax :: SingleType a -> (a,a) :-> a+evalMax ty@(NumSingleType (IntegralNumType ty')) | IntegralDict <- integralDict ty' = eval2 ty max+evalMax ty@(NumSingleType (FloatingNumType ty')) | FloatingDict <- floatingDict ty' = eval2 ty max +evalMin :: SingleType a -> (a,a) :-> a+evalMin ty@(NumSingleType (IntegralNumType ty')) | IntegralDict <- integralDict ty' = eval2 ty min+evalMin ty@(NumSingleType (FloatingNumType ty')) | FloatingDict <- floatingDict ty' = eval2 ty min  -- Logical operators -- ----------------- -evalLAnd :: (Bool,Bool) :-> Bool+evalLAnd :: (PrimBool,PrimBool) :-> PrimBool evalLAnd (untup2 -> Just (x,y)) env   | Just a      <- propagate env x-  = Just $ if a then Stats.ruleFired "True &&" y-                else Stats.ruleFired "False &&" $ Const (fromElt False)+  = Just+  $ if toBool a then Stats.ruleFired "True &&" y+                else Stats.ruleFired "False &&" $ Const scalarTypeWord8 0 +  | Just b      <- propagate env y+  = Just+  $ if toBool b then Stats.ruleFired "True &&" x+                else Stats.ruleFired "False &&" $ Const scalarTypeWord8 0+ evalLAnd _ _   = Nothing -evalLOr  :: (Bool,Bool) :-> Bool+evalLOr  :: (PrimBool,PrimBool) :-> PrimBool evalLOr (untup2 -> Just (x,y)) env   | Just a      <- propagate env x-  = Just $ if a then Stats.ruleFired "True ||" $ Const (fromElt True)+  = Just+  $ if toBool a then Stats.ruleFired "True ||" $ Const scalarTypeWord8 1                 else Stats.ruleFired "False ||" y +  | Just b      <- propagate env y+  = Just+  $ if toBool b then Stats.ruleFired "True ||" $ Const scalarTypeWord8 1+                else Stats.ruleFired "False ||" x+ evalLOr _ _   = Nothing -evalLNot :: Bool :-> Bool+evalLNot :: PrimBool :-> PrimBool 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--evalChr :: Int :-> Char-evalChr = eval1 chr--evalBoolToInt :: Bool :-> Int-evalBoolToInt = eval1 fromEnum+evalLNot x env                            = bool1 (not . toBool) x env -evalFromIntegral :: Elt b => IntegralType a -> NumType b -> a :-> b+evalFromIntegral :: IntegralType a -> NumType b -> a :-> b evalFromIntegral ta (IntegralNumType tb)   | IntegralDict <- integralDict ta-  , IntegralDict <- integralDict tb = eval1 fromIntegral+  , IntegralDict <- integralDict tb = eval1 (NumSingleType $ IntegralNumType tb) fromIntegral  evalFromIntegral ta (FloatingNumType tb)   | IntegralDict <- integralDict ta-  , FloatingDict <- floatingDict tb = eval1 fromIntegral+  , FloatingDict <- floatingDict tb = eval1 (NumSingleType $ FloatingNumType tb) fromIntegral -evalToFloating :: Elt b => NumType a -> FloatingType b -> a :-> b+evalToFloating :: NumType a -> FloatingType b -> a :-> b evalToFloating (IntegralNumType ta) tb x env   | IntegralDict <- integralDict ta-  , FloatingDict <- floatingDict tb = eval1 realToFrac x env+  , FloatingDict <- floatingDict tb = eval1 (NumSingleType $ FloatingNumType tb) realToFrac x env  evalToFloating (FloatingNumType ta) tb x env-  | TypeHalf   FloatingDict <- ta-  , TypeHalf   FloatingDict <- tb = Just x+  | TypeHalf   <- ta+  , TypeHalf   <- tb = Just x -  | TypeFloat  FloatingDict <- ta-  , TypeFloat  FloatingDict <- tb = Just x+  | TypeFloat  <- ta+  , TypeFloat  <- tb = Just x -  | TypeDouble FloatingDict <- ta-  , TypeDouble FloatingDict <- tb = Just x+  | TypeDouble <- ta+  , TypeDouble <- tb = Just x -  | TypeFloat  FloatingDict <- ta-  , TypeDouble FloatingDict <- tb = eval1 float2Double x env+  | TypeFloat  <- ta+  , TypeDouble <- tb = eval1 (NumSingleType $ FloatingNumType tb) float2Double x env -  | TypeDouble FloatingDict <- ta-  , TypeFloat  FloatingDict <- tb = eval1 double2Float x env+  | TypeDouble <- ta+  , TypeFloat  <- tb = eval1 (NumSingleType $ FloatingNumType tb) double2Float x env    | FloatingDict <- floatingDict ta-  , FloatingDict <- floatingDict tb = eval1 realToFrac x env+  , FloatingDict <- floatingDict tb = eval1 (NumSingleType $ FloatingNumType tb) realToFrac x env   -- Scalar primitives@@ -782,11 +734,9 @@  evalMinBound :: BoundedType a -> a evalMinBound (IntegralBoundedType ty) | IntegralDict <- integralDict ty = minBound-evalMinBound (NonNumBoundedType   ty) | NonNumDict   <- nonNumDict ty   = minBound  evalMaxBound :: BoundedType a -> a evalMaxBound (IntegralBoundedType ty) | IntegralDict <- integralDict ty = maxBound-evalMaxBound (NonNumBoundedType   ty) | NonNumDict   <- nonNumDict ty   = maxBound  evalPi :: FloatingType a -> a evalPi ty | FloatingDict <- floatingDict ty = pi
− src/Data/Array/Accelerate/Trafo/Base.hs
@@ -1,442 +0,0 @@-{-# LANGUAGE CPP                  #-}-{-# LANGUAGE ConstraintKinds      #-}-{-# LANGUAGE FlexibleInstances    #-}-{-# LANGUAGE GADTs                #-}-{-# 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..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.Trafo.Base (--  -- Toolkit-  Kit(..), Match(..), (:~:)(..),-  avarIn, kmap, fromOpenAfun,--  -- Delayed Arrays-  DelayedAcc,  DelayedOpenAcc(..),-  DelayedAfun, DelayedOpenAfun,-  DelayedExp,  DelayedOpenExp,-  DelayedFun,  DelayedOpenFun,-  matchDelayedOpenAcc, encodeDelayedOpenAcc, hashDelayedOpenAcc,--  -- Environments-  Gamma(..), incExp, prjExp, pushExp,-  Extend(..), append, bind,-  Sink(..), sink, sink1,-  Supplement(..), bindExps,--) where---- standard library-import Control.Applicative-import Control.DeepSeq-import Crypto.Hash-import Data.ByteString.Builder-import Data.ByteString.Builder.Extra-import Data.Monoid-import Data.Type.Equality-import Text.PrettyPrint.ANSI.Leijen                     hiding ( (<$>), (<>) )-import Prelude                                          hiding ( until )---- friends-import Data.Array.Accelerate.AST                        hiding ( Val(..) )-import Data.Array.Accelerate.Analysis.Hash-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 (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-  ---  matchAcc      :: MatchAcc acc-  encodeAcc     :: EncodeAcc acc-  prettyAcc     :: PrettyAcc acc--instance Kit OpenAcc where-  inject                 = OpenAcc-  extract (OpenAcc pacc) = pacc-  fromOpenAcc            = id-  ---  {-# INLINEABLE encodeAcc #-}-  {-# INLINEABLE matchAcc  #-}-  {-# INLINEABLE prettyAcc #-}-  encodeAcc (OpenAcc pacc)                  = encodePreOpenAcc encodeAcc pacc-  matchAcc  (OpenAcc pacc1) (OpenAcc pacc2) = matchPreOpenAcc matchAcc encodeAcc pacc1 pacc2-  prettyAcc                                 = prettyOpenAcc--avarIn :: (Kit acc, Arrays arrs) => Idx aenv arrs -> acc aenv arrs-avarIn = inject  . Avar--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)--instance Match (Idx env) where-  {-# INLINEABLE match #-}-  match = matchIdx--instance Kit acc => Match (PreOpenExp acc env aenv) where-  {-# INLINEABLE match #-}-  match = matchPreOpenExp matchAcc encodeAcc--instance Kit acc => Match (PreOpenFun acc env aenv) where-  {-# INLINEABLE match #-}-  match = matchPreOpenFun matchAcc encodeAcc--instance Kit acc => Match (PreOpenAcc acc aenv) where-  {-# INLINEABLE match #-}-  match = matchPreOpenAcc matchAcc encodeAcc--instance {-# INCOHERENT #-} Kit acc => Match (acc aenv) where-  {-# INLINEABLE match #-}-  match = matchAcc----- Delayed Arrays--- ==============---- The type of delayed arrays. This representation is used to annotate the AST--- in the recursive knot to distinguish standard AST terms from operand arrays--- that should be embedded into their consumers.----type DelayedAcc         = DelayedOpenAcc ()-type DelayedAfun        = PreOpenAfun DelayedOpenAcc ()--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--  Delayed               :: (Shape sh, Elt e) =>-    { extentD           :: PreExp DelayedOpenAcc aenv sh-    , indexD            :: PreFun DelayedOpenAcc aenv (sh  -> e)-    , 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 (Manifest pacc) = pacc-  extract Delayed{}       = error "DelayedAcc.extract"-  fromOpenAcc             = error "DelayedAcc.fromOpenAcc"-  ---  {-# INLINEABLE encodeAcc #-}-  {-# INLINEABLE matchAcc  #-}-  {-# INLINEABLE prettyAcc #-}-  encodeAcc               = encodeDelayedOpenAcc-  matchAcc                = matchDelayedOpenAcc-  prettyAcc               = prettyDelayedOpenAcc--instance NFData (DelayedOpenAfun aenv t) where-  rnf = rnfPreOpenAfun rnfDelayedOpenAcc--instance NFData (DelayedOpenAcc aenv t) where-  rnf = rnfDelayedOpenAcc---- instance NFData (DelayedSeq t) where---   rnf = rnfDelayedSeq---hashDelayedOpenAcc :: DelayedOpenAcc aenv a -> Hash-hashDelayedOpenAcc = hashlazy . toLazyByteString . encodeDelayedOpenAcc--{-# INLINEABLE encodeDelayedOpenAcc #-}-encodeDelayedOpenAcc :: EncodeAcc DelayedOpenAcc-encodeDelayedOpenAcc (Manifest pacc) = intHost $(hashQ "Manifest") <> encodePreOpenAcc encodeDelayedOpenAcc pacc-encodeDelayedOpenAcc Delayed{..}     = intHost $(hashQ "Delayed")  <> travE extentD <> travF indexD <> travF linearIndexD-  where-    {-# INLINE travE #-}-    travE :: DelayedExp aenv sh -> Builder-    travE = encodePreOpenExp encodeDelayedOpenAcc--    {-# INLINE travF #-}-    travF :: DelayedFun aenv f -> Builder-    travF = encodePreOpenFun encodeDelayedOpenAcc--{-# INLINEABLE matchDelayedOpenAcc #-}-matchDelayedOpenAcc :: MatchAcc DelayedOpenAcc-matchDelayedOpenAcc (Manifest pacc1) (Manifest pacc2)-  = matchPreOpenAcc matchDelayedOpenAcc encodeDelayedOpenAcc pacc1 pacc2--matchDelayedOpenAcc (Delayed sh1 ix1 lx1) (Delayed sh2 ix2 lx2)-  | Just Refl <- matchPreOpenExp matchDelayedOpenAcc encodeDelayedOpenAcc sh1 sh2-  , Just Refl <- matchPreOpenFun matchDelayedOpenAcc encodeDelayedOpenAcc ix1 ix2-  , Just Refl <- matchPreOpenFun matchDelayedOpenAcc encodeDelayedOpenAcc lx1 lx2-  = Just Refl--matchDelayedOpenAcc _ _-  = Nothing--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:------ > let a0 = <...> in map f (Delayed (shape a0) (\x0 -> a0!x0))------ becomes------ > let a0 = <...> in map f a0----prettyDelayedOpenAcc :: PrettyAcc DelayedOpenAcc-prettyDelayedOpenAcc wrap aenv acc = case acc of-  Manifest pacc         -> prettyPreOpenAcc prettyDelayedOpenAcc wrap aenv pacc-  Delayed sh f _-    | Shape a           <- sh-    , Just Refl         <- match f (Lam (Body (Index a (Var ZeroIdx))))-    -> prettyDelayedOpenAcc wrap aenv a--    | otherwise-    -> wrap $ hang 2 (sep [ green (text "delayed")-                          , parens (align (prettyPreExp prettyDelayedOpenAcc (parens . align) aenv sh))-                          , parens (align (prettyPreFun prettyDelayedOpenAcc 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--- ============---- An environment that holds let-bound scalar expressions. The second--- environment variable env' is used to project out the corresponding--- index when looking up in the environment congruent expressions.----data Gamma acc env env' aenv where-  EmptyExp :: Gamma acc env env' aenv--  PushExp  :: Elt t-           => Gamma acc env env' aenv-           -> WeakPreOpenExp acc env aenv t-           -> Gamma acc env (env', t) aenv--data WeakPreOpenExp acc env aenv t where-  Subst    :: env :> env'-           -> PreOpenExp     acc env  aenv t-           -> PreOpenExp     acc env' aenv t {- LAZY -}-           -> WeakPreOpenExp acc env' aenv t---- XXX: The simplifier calls this function every time it moves under a let--- binding. This means we have a number of calls to 'weakenE' exponential in the--- depth of nested let bindings, which quickly causes problems.------ We can improve the situation slightly by observing that weakening by a single--- variable does no less work than weaking by multiple variables at once; both--- require a deep copy of the AST. By exploiting laziness (or, an IORef) we can--- queue up multiple weakenings to happen in a single step.------ <https://github.com/AccelerateHS/accelerate-llvm/issues/20>----incExp-    :: Kit acc-    => Gamma acc env     env' aenv-    -> Gamma acc (env,s) env' aenv-incExp EmptyExp        = EmptyExp-incExp (PushExp env w) = incExp env `PushExp` subs w-  where-    subs :: forall acc env aenv s t. Kit acc => WeakPreOpenExp acc env aenv t -> WeakPreOpenExp acc (env,s) aenv t-    subs (Subst k (e :: PreOpenExp acc env_ aenv t) _) = Subst k' e (weakenE k' e)-      where-        k' :: env_ :> (env,s)-        k' = SuccIdx . k--prjExp :: Idx env' t -> Gamma acc env env' aenv -> PreOpenExp acc env aenv t-prjExp ZeroIdx      (PushExp _   (Subst _ _ e)) = e-prjExp (SuccIdx ix) (PushExp env _)             = prjExp ix env-prjExp _            _                           = $internalError "prjExp" "inconsistent valuation"--pushExp :: Elt t => Gamma acc env env' aenv -> PreOpenExp acc env aenv t -> Gamma acc env (env',t) aenv-pushExp env e = env `PushExp` Subst id e e--{---lookupExp-    :: Kit acc-    => Gamma      acc env env' aenv-    -> PreOpenExp acc env      aenv t-    -> Maybe (Idx env' t)-lookupExp EmptyExp        _ = Nothing-lookupExp (PushExp env e) x-  | Just Refl <- match e x  = Just ZeroIdx-  | otherwise               = SuccIdx `fmap` lookupExp env x--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)---}---- 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 Extend, but for the scalar environment.----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-
+ src/Data/Array/Accelerate/Trafo/Config.hs view
@@ -0,0 +1,49 @@+{-# OPTIONS_HADDOCK hide #-}+-- |+-- Module      : Data.Array.Accelerate.Trafo.Config+-- Copyright   : [2008..2020] The Accelerate Team+-- License     : BSD3+--+-- Maintainer  : Trevor L. McDonell <trevor.mcdonell@gmail.com>+-- Stability   : experimental+-- Portability : non-portable (GHC extensions)+--++module Data.Array.Accelerate.Trafo.Config (++  Config(..),+  Flag(..),+  defaultOptions,++  -- Other options not controlled by the command line flags+  -- float_out_acc,++) where++import Data.Bits+import Data.BitSet+import Data.Array.Accelerate.Debug.Flags                  as F++import Data.Word+import System.IO.Unsafe+import Foreign.Storable+++data Config = Config+  { options                   :: {-# UNPACK #-} !(BitSet Word32 Flag)+  , unfolding_use_threshold   :: {-# UNPACK #-} !Int+  , max_simplifier_iterations :: {-# UNPACK #-} !Int+  }+  deriving Show++{-# NOINLINE defaultOptions #-}+defaultOptions :: Config+defaultOptions = unsafePerformIO $!+  Config <$> (BitSet . (0x80000000 .|.)) <$> peek F.__cmd_line_flags+         <*> (fromIntegral <$> F.getValue F.unfolding_use_threshold)+         <*> (fromIntegral <$> F.getValue F.max_simplifier_iterations)++-- Extra options not covered by command line flags+--+-- float_out_acc          = Flag 31+
+ src/Data/Array/Accelerate/Trafo/Delayed.hs view
@@ -0,0 +1,126 @@+{-# LANGUAGE FlexibleInstances    #-}+{-# LANGUAGE GADTs                #-}+{-# LANGUAGE LambdaCase           #-}+{-# LANGUAGE OverloadedStrings    #-}+{-# LANGUAGE RecordWildCards      #-}+{-# LANGUAGE TemplateHaskell      #-}+{-# LANGUAGE TypeFamilies         #-}+{-# LANGUAGE TypeSynonymInstances #-}+{-# OPTIONS_HADDOCK hide #-}+-- |+-- Module      : Data.Array.Accelerate.Trafo.Delayed+-- Copyright   : [2012..2020] The Accelerate Team+-- License     : BSD3+--+-- Maintainer  : Trevor L. McDonell <trevor.mcdonell@gmail.com>+-- Stability   : experimental+-- Portability : non-portable (GHC extensions)+--+-- The type of delayed arrays. This representation is used to annotate the AST+-- in the recursive knot to distinguish standard AST terms from operand arrays+-- that should be embedded into their consumers.+--++module Data.Array.Accelerate.Trafo.Delayed+  where++import Data.Array.Accelerate.AST+import Data.Array.Accelerate.Analysis.Hash+import Data.Array.Accelerate.Analysis.Match+import Data.Array.Accelerate.Representation.Array+import Data.Array.Accelerate.Representation.Type+import Data.Array.Accelerate.Trafo.Substitution++import Data.Array.Accelerate.Debug.Stats                            as Stats++import Control.DeepSeq+import Data.ByteString.Builder+import Data.ByteString.Builder.Extra+++type DelayedAcc      = DelayedOpenAcc ()+type DelayedAfun     = PreOpenAfun DelayedOpenAcc ()+type DelayedOpenAfun = PreOpenAfun DelayedOpenAcc++-- type DelayedOpenSeq = PreOpenSeq DelayedOpenAcc+-- data DelayedSeq t where+--   DelayedSeq :: Extend DelayedOpenAcc () aenv+--              -> DelayedOpenSeq aenv () t+--              -> DelayedSeq t++data DelayedOpenAcc aenv a where+  Manifest              :: PreOpenAcc DelayedOpenAcc aenv a+                        -> DelayedOpenAcc aenv a++  Delayed               ::+    { reprD             :: ArrayR (Array sh e)+    , extentD           :: Exp aenv sh+    , indexD            :: Fun aenv (sh  -> e)+    , linearIndexD      :: Fun aenv (Int -> e)+    }                   -> DelayedOpenAcc aenv (Array sh e)++instance HasArraysR DelayedOpenAcc where+  arraysR (Manifest a) = arraysR a+  arraysR Delayed{..}  = TupRsingle reprD++instance Rebuildable DelayedOpenAcc where+  type AccClo DelayedOpenAcc = DelayedOpenAcc+  rebuildPartial v = \case+    Manifest pacc -> Manifest <$> rebuildPartial v pacc+    Delayed{..}   -> (\e i l -> Delayed reprD (unOpenAccExp e) (unOpenAccFun i) (unOpenAccFun l))+                              <$> rebuildPartial v (OpenAccExp extentD)+                              <*> rebuildPartial v (OpenAccFun indexD)+                              <*> rebuildPartial v (OpenAccFun linearIndexD)++instance Sink DelayedOpenAcc where+  weaken k = Stats.substitution "weaken" . rebuildA (rebuildWeakenVar k)++instance NFData (DelayedOpenAfun aenv t) where+  rnf = rnfPreOpenAfun rnfDelayedOpenAcc++instance NFData (DelayedOpenAcc aenv t) where+  rnf = rnfDelayedOpenAcc++encodeDelayedOpenAcc :: EncodeAcc DelayedOpenAcc+encodeDelayedOpenAcc options acc =+  let+      travE :: Exp aenv sh -> Builder+      travE = encodeOpenExp++      travF :: Fun aenv f -> Builder+      travF = encodeOpenFun++      travA :: PreOpenAcc DelayedOpenAcc aenv a -> Builder+      travA = encodePreOpenAcc options encodeDelayedOpenAcc++      deepA :: PreOpenAcc DelayedOpenAcc aenv a -> Builder+      deepA | perfect options = travA+            | otherwise       = encodeArraysType . arraysR+  in+  case acc of+    Manifest pacc    -> intHost $(hashQ ("Manifest" :: String)) <> deepA pacc+    Delayed _ sh f g -> intHost $(hashQ ("Delayed"  :: String)) <> travE sh <> travF f <> travF g++matchDelayedOpenAcc :: MatchAcc DelayedOpenAcc+matchDelayedOpenAcc (Manifest pacc1) (Manifest pacc2)+  = matchPreOpenAcc matchDelayedOpenAcc pacc1 pacc2+matchDelayedOpenAcc (Delayed _ sh1 ix1 lx1) (Delayed _ sh2 ix2 lx2)+  | Just Refl <- matchOpenExp sh1 sh2+  , Just Refl <- matchOpenFun ix1 ix2+  , Just Refl <- matchOpenFun lx1 lx2+  = Just Refl+matchDelayedOpenAcc _ _+  = Nothing++rnfDelayedOpenAcc :: NFDataAcc DelayedOpenAcc+rnfDelayedOpenAcc (Manifest pacc) =+  rnfPreOpenAcc rnfDelayedOpenAcc pacc+rnfDelayedOpenAcc (Delayed aR sh ix lx) =+  rnfArrayR aR `seq` rnfOpenExp sh `seq` rnfOpenFun ix `seq` rnfOpenFun lx++liftDelayedOpenAcc :: LiftAcc DelayedOpenAcc+liftDelayedOpenAcc (Manifest pacc) =+  [|| Manifest $$(liftPreOpenAcc liftDelayedOpenAcc pacc) ||]+liftDelayedOpenAcc (Delayed aR sh ix lx) =+  [|| Delayed $$(liftArrayR aR) $$(liftOpenExp sh) $$(liftOpenFun ix) $$(liftOpenFun lx) ||]+
+ src/Data/Array/Accelerate/Trafo/Environment.hs view
@@ -0,0 +1,163 @@+{-# LANGUAGE GADTs               #-}+{-# LANGUAGE OverloadedStrings   #-}+{-# LANGUAGE RankNTypes          #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TypeOperators       #-}+-- |+-- Module      : Data.Array.Accelerate.Trafo.Environment+-- Copyright   : [2012..2020] The Accelerate Team+-- License     : BSD3+--+-- Maintainer  : Trevor L. McDonell <trevor.mcdonell@gmail.com>+-- Stability   : experimental+-- Portability : non-portable (GHC extensions)+--++module Data.Array.Accelerate.Trafo.Environment+  where++import Data.Array.Accelerate.AST+import Data.Array.Accelerate.AST.Environment+import Data.Array.Accelerate.AST.Idx+import Data.Array.Accelerate.AST.LeftHandSide+import Data.Array.Accelerate.Error+import Data.Array.Accelerate.Representation.Array+import Data.Array.Accelerate.Trafo.Substitution+import Data.Array.Accelerate.Type++import Data.Array.Accelerate.Debug.Stats                            as Stats+++-- An environment that holds let-bound scalar expressions. The second+-- environment variable env' is used to project out the corresponding+-- index when looking up in the environment congruent expressions.+--+data Gamma env env' aenv where+  EmptyExp :: Gamma env env' aenv++  PushExp  :: Gamma env env' aenv+           -> WeakOpenExp env aenv t+           -> Gamma env (env', t) aenv++data WeakOpenExp env aenv t where+  Subst    :: env :> env'+           -> OpenExp     env  aenv t+           -> OpenExp     env' aenv t {- LAZY -}+           -> WeakOpenExp env' aenv t++-- XXX: The simplifier calls this function every time it moves under a let+-- binding. This means we have a number of calls to 'weakenE' exponential in the+-- depth of nested let bindings, which quickly causes problems.+--+-- We can improve the situation slightly by observing that weakening by a single+-- variable does no less work than weaking by multiple variables at once; both+-- require a deep copy of the AST. By exploiting laziness (or, an IORef) we can+-- queue up multiple weakenings to happen in a single step.+--+-- <https://github.com/AccelerateHS/accelerate-llvm/issues/20>+--+incExp+    :: Gamma env     env' aenv+    -> Gamma (env,s) env' aenv+incExp EmptyExp        = EmptyExp+incExp (PushExp env w) = incExp env `PushExp` subs w+  where+    subs :: forall env aenv s t. WeakOpenExp env aenv t -> WeakOpenExp (env,s) aenv t+    subs (Subst k (e :: OpenExp env_ aenv t) _) = Subst (weakenSucc' k) e (weakenE (weakenSucc' k) e)++prjExp :: HasCallStack => Idx env' t -> Gamma env env' aenv -> OpenExp env aenv t+prjExp ZeroIdx      (PushExp _   (Subst _ _ e)) = e+prjExp (SuccIdx ix) (PushExp env _)             = prjExp ix env+prjExp _            _                           = internalError "inconsistent valuation"++pushExp :: Gamma env env' aenv -> OpenExp env aenv t -> Gamma env (env',t) aenv+pushExp env e = env `PushExp` Subst weakenId e e++{--+lookupExp+    :: Gamma   env env' aenv+    -> OpenExp env      aenv t+    -> Maybe (Idx env' t)+lookupExp EmptyExp        _ = Nothing+lookupExp (PushExp env e) x+  | Just Refl <- match e x  = Just ZeroIdx+  | otherwise               = SuccIdx `fmap` lookupExp env x++weakenGamma1+    :: Gamma env env' aenv+    -> Gamma 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 env env' aenv+    -> Gamma env env' aenv'+sinkGamma _   EmptyExp        = EmptyExp+sinkGamma ext (PushExp env e) = PushExp (sinkGamma ext env) (sinkA ext e)+--}++-- 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 s f env env' where+  BaseEnv :: Extend s f env env++  PushEnv :: Extend s f env env'+          -> LeftHandSide s t env' env''+          -> f env' t+          -> Extend s f env env''++pushArrayEnv+    :: HasArraysR acc+    => Extend ArrayR acc aenv aenv'+    -> acc aenv' (Array sh e)+    -> Extend ArrayR acc aenv (aenv', Array sh e)+pushArrayEnv env a = PushEnv env (LeftHandSideSingle $ arrayR a) a+++-- Append two environment witnesses+--+append :: Extend s acc env env' -> Extend s acc env' env'' -> Extend s acc env env''+append x BaseEnv           = x+append x (PushEnv e lhs a) = PushEnv (append x e) lhs 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 :: (forall env t. PreOpenAcc acc env t -> acc env t)+     -> Extend ArrayR  acc aenv aenv'+     -> PreOpenAcc acc      aenv' a+     -> PreOpenAcc acc aenv       a+bind _      BaseEnv           = id+bind inject (PushEnv g lhs a) = bind inject g . Alet lhs 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.+--+sinkA :: Sink f => Extend s acc env env' -> f env t -> f env' t+sinkA env = weaken (sinkWeaken env) -- TODO: Fix Stats sinkA vs sink1++sink1 :: Sink f => Extend s acc env env' -> f (env,t') t -> f (env',t') t+sink1 env = weaken $ sink $ sinkWeaken env++sinkWeaken :: Extend s acc env env' -> env :> env'+sinkWeaken (PushEnv e (LeftHandSideWildcard _) _) = sinkWeaken e+sinkWeaken (PushEnv e (LeftHandSideSingle _)   _) = weakenSucc' $ sinkWeaken e+sinkWeaken (PushEnv e (LeftHandSidePair l1 l2) _) = sinkWeaken (PushEnv (PushEnv e l1 undefined) l2 undefined)+sinkWeaken BaseEnv = Stats.substitution "sink" weakenId++-- Wrapper around OpenExp, with the order of type arguments env and aenv flipped+newtype OpenExp' aenv env e = OpenExp' (OpenExp env aenv e)++bindExps :: Extend ScalarType (OpenExp' aenv) env env'+         -> OpenExp env' aenv e+         -> OpenExp env  aenv e+bindExps BaseEnv = id+bindExps (PushEnv g lhs (OpenExp' b)) = bindExps g . Let lhs b+
src/Data/Array/Accelerate/Trafo/Fusion.hs view
@@ -3,1570 +3,1737 @@ {-# LANGUAGE FlexibleContexts     #-} {-# LANGUAGE FlexibleInstances    #-} {-# LANGUAGE GADTs                #-}-{-# LANGUAGE IncoherentInstances  #-}-{-# LANGUAGE InstanceSigs         #-}-{-# LANGUAGE PatternGuards        #-}-{-# LANGUAGE RankNTypes           #-}-{-# LANGUAGE ScopedTypeVariables  #-}-{-# LANGUAGE TemplateHaskell      #-}-{-# LANGUAGE TypeOperators        #-}-{-# LANGUAGE UndecidableInstances #-}-{-# LANGUAGE ViewPatterns         #-}-{-# OPTIONS_GHC -fno-warn-incomplete-patterns #-}-{-# OPTIONS_GHC -fno-warn-name-shadowing      #-}--- |--- Module      : Data.Array.Accelerate.Trafo.Fusion--- Copyright   : [2012..2017] Manuel M T Chakravarty, Gabriele Keller, 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)------ This module implements producer/producer and consumer/producer fusion as a--- term rewriting of the Accelerate AST.------ The function 'quench' perform the source-to-source fusion transformation,--- while 'anneal' additionally makes the representation of embedded producers--- explicit by representing the AST as a 'DelayedAcc' of manifest and delayed--- nodes.-----module Data.Array.Accelerate.Trafo.Fusion (--  -- ** Types-  DelayedAcc, DelayedOpenAcc(..),-  DelayedAfun, DelayedOpenAfun,-  DelayedExp, DelayedFun, DelayedOpenExp, DelayedOpenFun,--  -- ** Conversion-  convertAcc, convertAfun,--) where---- standard library-import Prelude                                          hiding ( exp, until )---- friends-import Data.Array.Accelerate.AST-import Data.Array.Accelerate.Error-import Data.Array.Accelerate.Trafo.Base-import Data.Array.Accelerate.Trafo.Shrink-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, Tuple(..), Atuple(..)-                                                        , IsAtuple, TupleRepr, eltType )-import Data.Array.Accelerate.Product-import Data.Array.Accelerate.Type--import qualified Data.Array.Accelerate.Debug            as Stats-#ifdef ACCELERATE_DEBUG-import System.IO.Unsafe -- for debugging-#endif----- Delayed Array Fusion--- ====================---- | Apply the fusion transformation to a closed de Bruijn AST----convertAcc :: Arrays arrs => Bool -> Acc arrs -> DelayedAcc arrs-convertAcc fuseAcc = withSimplStats . convertOpenAcc fuseAcc---- | Apply the fusion transformation to a function of array arguments----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-#else-withSimplStats x = x-#endif----- | Apply the fusion transformation to an AST. This consists of two phases:------    1. A bottom-up traversal that converts nodes into the internal delayed---       representation, merging adjacent producer/producer pairs.------    2. A top-down traversal that makes the representation of fused---       consumer/producer pairs explicit as a 'DelayedAcc' of manifest and---       delayed nodes.------ TLM: Note that there really is no ambiguity as to which state an array will---      be in following this process: an array will be either delayed or---      manifest, and the two helper functions are even named as such! We should---      encode this property in the type somehow...----convertOpenAcc :: Arrays arrs => Bool -> OpenAcc aenv arrs -> DelayedOpenAcc aenv arrs-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-    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-    -- ----------    ---    -- 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)--    Replicate{}             -> fusionError-    Slice{}                 -> fusionError-    ZipWith{}               -> fusionError--    -- 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 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) (cvtB x) (delayed fuseAcc a)-    Stencil2 f x a y b      -> Stencil2 (cvtF f) (cvtB x) (delayed fuseAcc a) (cvtB y) (delayed fuseAcc b)-    -- Collect s               -> Collect  (cvtS s)--    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--        | otherwise-        = Alet bnd body--      cvtAT :: Atuple (OpenAcc aenv) a -> Atuple (DelayedOpenAcc aenv) a-      cvtAT NilAtup        = NilAtup-      cvtAT (SnocAtup t a) = cvtAT t `SnocAtup` manifest fuseAcc a--      cvtAF :: OpenAfun aenv f -> PreOpenAfun DelayedOpenAcc aenv f-      cvtAF (Alam f)  = Alam  (cvtAF f)-      cvtAF (Abody b) = Abody (manifest fuseAcc b)--      -- cvtS :: PreOpenSeq OpenAcc aenv senv s -> PreOpenSeq DelayedOpenAcc aenv senv s-      -- cvtS = convertOpenSeq fuseAcc--      -- 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)--      cvtE :: OpenExp env aenv t -> DelayedOpenExp env aenv t-      cvtE = convertOpenExp fuseAcc--      cvtB :: Boundary aenv t -> PreBoundary DelayedOpenAcc aenv t-      cvtB Clamp        = Clamp-      cvtB Mirror       = Mirror-      cvtB Wrap         = Wrap-      cvtB (Constant v) = Constant v-      cvtB (Function f) = Function (cvtF f)--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-    Undef                   -> Undef-    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)-    Coerce e                -> Coerce (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-    cvtF (Lam f)  = Lam (cvtF f)-    cvtF (Body b) = Body (cvtE b)--    cvtE :: OpenExp env aenv t -> DelayedOpenExp env aenv t-    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--- number of combinations that need to be considered.----type EmbedAcc acc = forall aenv arrs. Arrays arrs => acc aenv arrs -> Embed acc aenv arrs-type ElimAcc  acc = forall aenv s t. acc aenv s -> acc (aenv,s) t -> Bool--embedOpenAcc :: Arrays arrs => Bool -> OpenAcc aenv arrs -> Embed OpenAcc aenv arrs-embedOpenAcc fuseAcc (OpenAcc pacc) =-  embedPreAcc fuseAcc (embedOpenAcc fuseAcc) elimOpenAcc pacc-  where-    -- 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]-    ---    elimOpenAcc :: ElimAcc OpenAcc-    elimOpenAcc _bnd body-      | count False ZeroIdx body <= lIMIT = True-      | otherwise                         = False-      where-        lIMIT = 1--        count :: UsesOfAcc OpenAcc-        count no ix (OpenAcc pacc) = usesOfPreAcc no count ix pacc---embedPreAcc-    :: forall acc aenv arrs. (Kit acc, Arrays arrs)-    => Bool-    -> EmbedAcc   acc-    -> ElimAcc    acc-    -> PreOpenAcc acc aenv arrs-    -> Embed      acc aenv arrs-embedPreAcc fuseAcc embedAcc elimAcc pacc-  = unembed-  $ case pacc of--    -- Non-fusible terms-    -- ------------------    ---    -- 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-    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)-    Aforeign ff f a     -> done $ Aforeign ff (cvtAF f) (cvtA a)-    -- Collect s           -> collectD s--    -- Array injection-    Avar v              -> done $ Avar v-    Use arrs            -> done $ Use arrs-    Unit e              -> done $ Unit (cvtE e)--    -- Producers-    -- ----------    ---    -- The class of operations that given a set of zero or more input arrays,-    -- produce a _single_ element for the output array by manipulating a-    -- _single_ element from each input array. These can be further classified-    -- as value (map, zipWith) or index space (backpermute, slice, replicate)-    -- transformations.-    ---    -- The critical feature is that each element of the output is produced-    -- independently of all others, and so we can aggressively fuse arbitrary-    -- sequences of these operations.-    ---    Generate sh f       -> generateD (cvtE sh) (cvtF f)--    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-    Reshape sl a        -> reshapeD (embedAcc a) (cvtE sl)--    -- Consumers-    -- ----------    ---    -- Operations where each element of the output array depends on multiple-    -- elements of the input array. To implement these operations efficiently in-    -- parallel, we need to know how elements of the array depend on each other:-    -- a parallel scan is implemented very differently from a parallel fold, for-    -- example.-    ---    -- In order to avoid obfuscating this crucial information required for-    -- parallel implementation, fusion is separated into to phases:-    -- producer/producer, implemented above, and consumer/producer, which is-    -- implemented below. This will place producers adjacent to the consumer-    -- node, so that the producer can be directly embedded into the consumer-    -- during the code generation phase.-    ---    Fold f z a          -> embed  (into2 Fold          (cvtF f) (cvtE z)) a-    Fold1 f a           -> embed  (into  Fold1         (cvtF f)) a-    FoldSeg f z a s     -> embed2 (into2 FoldSeg       (cvtF f) (cvtE z)) a s-    Fold1Seg f a s      -> embed2 (into  Fold1Seg      (cvtF f)) a s-    Scanl f z a         -> embed  (into2 Scanl         (cvtF f) (cvtE z)) a-    Scanl1 f a          -> embed  (into  Scanl1        (cvtF f)) a-    Scanl' f z a        -> embed  (into2 Scanl'        (cvtF f) (cvtE z)) a-    Scanr f z a         -> embed  (into2 Scanr         (cvtF f) (cvtE z)) a-    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       -> stencil  (cvtF f) (cvtB x) a-    Stencil2 f x a y b  -> stencil2 (cvtF f) (cvtB x) (cvtB y) a b--  where-    -- If fusion is not enabled, force terms to the manifest representation-    ---    unembed :: Embed acc aenv arrs -> Embed acc aenv arrs-    unembed x-      | fuseAcc         = x-      | otherwise       = done (compute x)--    cvtA :: Arrays a => acc aenv' a -> acc aenv' a-    cvtA = computeAcc . embedAcc--    cvtAT :: Atuple (acc aenv') a -> Atuple (acc aenv') a-    cvtAT NilAtup          = NilAtup-    cvtAT (SnocAtup tup a) = cvtAT tup `SnocAtup` cvtA a--    cvtAF :: PreOpenAfun acc aenv' f -> PreOpenAfun acc aenv' f-    cvtAF (Alam  f) = Alam  (cvtAF f)-    cvtAF (Abody a) = Abody (cvtA a)--    -- Helpers to shuffle the order of arguments to a constructor-    ---    permute f p d a     = Permute f d p a--    -- Stencils can delay their argument arrays-    ---    stencil-        :: Stencil sh a stencil-        => PreFun      acc aenv (stencil -> b)-        -> PreBoundary acc aenv (Array sh a)-        ->             acc aenv (Array sh a)-        -> Embed       acc aenv (Array sh b)-    stencil f@(Lam (Body e)) x =-      trav1 (if ua <= lIMIT then id else force) (into2 Stencil f x)-      where-        ua    = usesOfExp ZeroIdx e-        lIMIT = 1--    stencil2-        :: (Stencil sh a stencil1, Stencil sh b stencil2)-        => PreFun      acc aenv (stencil1 -> stencil2 -> c)-        -> PreBoundary acc aenv (Array sh a)-        -> PreBoundary acc aenv (Array sh b)-        ->             acc aenv (Array sh a)-        ->             acc aenv (Array sh b)-        -> Embed       acc aenv (Array sh c)-    stencil2 f@(Lam (Lam (Body e))) x y =-      trav2 (if ua <= lIMIT then id else force)-            (if ub <= lIMIT then id else force)-            (into3 op f x y)-      where-        op f x y a b  = Stencil2 f x a y b-        ua            = usesOfExp (SuccIdx ZeroIdx) e-        ub            = usesOfExp ZeroIdx           e-        lIMIT         = 1--    -- Conversions for closed scalar functions and expressions. This just-    -- applies scalar simplifications.-    ---    cvtF :: PreFun acc aenv' t -> PreFun acc aenv' t-    cvtF = simplify--    cvtE :: Elt t => PreExp acc aenv' t -> PreExp acc aenv' t-    cvtE = simplify--    cvtB :: PreBoundary acc aenv' t -> PreBoundary acc aenv' t-    cvtB Clamp        = Clamp-    cvtB Mirror       = Mirror-    cvtB Wrap         = Wrap-    cvtB (Constant c) = Constant c-    cvtB (Function f) = Function (cvtF f)--    -- Helpers to embed and fuse delayed terms-    ---    into :: Sink f => (f env' a -> b) -> f env a -> Extend acc env env' -> b-    into op a env = op (sink env a)--    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)--    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-         -> Embed acc aenv bs-    fuse op (embedAcc -> Embed env cc) = Embed env (op env cc)--    fuse2 :: (Arrays as, Arrays bs)-          => (forall aenv'. Extend acc aenv aenv' -> Cunctation acc aenv' as -> Cunctation acc aenv' bs -> Cunctation acc aenv' cs)-          ->       acc aenv as-          ->       acc aenv bs-          -> Embed acc aenv cs-    fuse2 op a1 a0-      | Embed env1 cc1  <- embedAcc a1-      , Embed env0 cc0  <- embedAcc (sink env1 a0)-      , env             <- env1 `append` env0-      = Embed env (op env (sink env0 cc1) cc0)--    embed :: (Arrays as, Arrays bs)-          => (forall aenv'. Extend acc aenv aenv' -> acc aenv' as -> PreOpenAcc acc aenv' bs)-          ->       acc aenv as-          -> Embed acc aenv bs-    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 = trav2 id id--    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` inject (op env acc1 acc0)) (Done ZeroIdx)--    force :: Arrays as => Embed acc aenv' as -> Embed acc aenv' as-    force (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--- =======================---- Note: [Representing delayed array]------ During the fusion transformation we represent terms as a pair consisting of--- a collection of supplementary environment bindings and a description of how--- to construct the array.------ It is critical to separate these two. To create a real AST node we need both--- the environment and array term, but analysis of how to fuse terms requires--- only the array description. If the additional bindings are bundled as part of--- the representation, the existentially quantified extended environment type--- will be untouchable. This is problematic because the terms of the two arrays--- are defined with respect to this existentially quantified type, and there is--- no way to directly combine these two environments:------   append :: Extend env env1 -> Extend env env2 -> Extend env ???------ And hence, no way to combine the terms of the delayed representation.------ The only way to bring terms into the same scope is to operate via the--- manifest terms. This entails a great deal of conversion between delayed and--- AST terms, but is certainly possible.------ However, because of the limited scope into which this existential type is--- available, we ultimately perform this process many times. In fact, complexity--- of the fusion algorithm for an AST of N terms becomes O(r^n), where r is the--- number of different rules we have for combining terms.----data Embed acc aenv a where-  Embed :: Extend     acc aenv aenv'-        -> Cunctation acc      aenv' a-        -> Embed      acc aenv       a----- Cunctation (n): the action or an instance of delaying; a tardy action.------ This describes the ways in which the fusion transformation represents--- intermediate arrays. The fusion process operates by recasting producer array--- computations in terms of a set of scalar functions used to construct an--- element at each index, and fusing successive producers by combining these--- scalar functions.----data Cunctation acc aenv a where--  -- The base case is just a real (manifest) array term. No fusion happens here.-  -- Note that the array is referenced by an index into the extended-  -- environment, ensuring that the array is manifest and making the term-  -- non-recursive in 'acc'. Also note that the return type is a general-  -- instance of Arrays and not restricted to a single Array.-  ---  Done  :: Arrays a-        => Idx            aenv a-        -> Cunctation acc aenv a--  -- We can represent an array by its shape and a function to compute an element-  -- at each index.-  ---  Yield :: (Shape sh, Elt e)-        => PreExp     acc aenv sh-        -> PreFun     acc aenv (sh -> e)-        -> Cunctation acc aenv (Array sh e)--  -- A more restrictive form than 'Yield' may afford greater opportunities for-  -- optimisation by a backend. This more structured form applies an index and-  -- value transform to an input array. Note that the transform is applied to an-  -- array stored as an environment index, so that the term is non-recursive and-  -- it is always possible to embed into a collective operation.-  ---  Step  :: (Shape sh, Shape sh', Elt a, Elt b)-        => PreExp     acc aenv sh'-        -> PreFun     acc aenv (sh' -> sh)-        -> PreFun     acc aenv (a   -> b)-        -> Idx            aenv (Array sh  a)-        -> Cunctation acc aenv (Array sh' b)---instance Kit acc => Simplify (Cunctation acc aenv a) where-  simplify (Done v)        = Done v-  simplify (Yield sh f)    = Yield (simplify sh) (simplify f)-  simplify (Step sh p f v) = Step (simplify sh) (simplify p) (simplify f) v----- Convert a real AST node into the internal representation----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` inject pacc) (Done ZeroIdx)----- Recast a cunctation into a mapping from indices to elements.----yield :: Kit acc-      => Cunctation acc aenv (Array sh e)-      -> Cunctation acc aenv (Array sh e)-yield cc =-  case cc of-    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)-      | otherwise                       -> error "yield: impossible case"----- Recast a cunctation into transformation step form. Not possible if the source--- was in the Yield formulation.----step :: Kit acc-     => Cunctation acc aenv (Array sh e)-     -> Maybe (Cunctation acc aenv (Array sh e))-step cc =-  case cc of-    Yield{}                             -> Nothing-    Step{}                              -> Just cc-    Done v-      | ArraysRarray <- accType cc      -> Just $ Step (arrayShape v) identity identity v-      | otherwise                       -> error "step: impossible case"----- Get the shape of a delayed array----shape :: Kit acc => Cunctation acc aenv (Array sh e) -> PreExp acc aenv sh-shape cc-  | Just (Step sh _ _ _) <- step cc     = sh-  | Yield sh _           <- yield cc    = sh----- 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)----- Environment manipulation--- ========================--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"--{----- Rearrange type arguments to fit with Sink type class.-newtype SinkSeq acc senv aenv a = SinkSeq { unSinkSeq :: PreOpenSeq acc aenv senv a }---- 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 (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--    where-      weakenL :: forall senv' arrs'. PreOpenSeq acc aenv senv' arrs' -> PreOpenSeq acc aenv' senv' arrs'-      weakenL s' = unSinkSeq (weaken k (SinkSeq s'))--      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--- ===========================================---- Array computations--- ---------------------- Recast the internal representation of delayed arrays into a real AST node.--- Use the most specific version of a combinator whenever possible.----compute :: (Kit acc, Arrays arrs) => Embed acc aenv arrs -> PreOpenAcc acc aenv arrs-compute (Embed env cc) = bind env (compute' cc)--compute' :: (Kit acc, Arrays arrs) => Cunctation acc aenv arrs -> PreOpenAcc acc aenv arrs-compute' cc = case simplify cc of-  Done v                                              -> Avar v-  Yield sh f                                          -> Generate sh f-  Step sh p f v-    | Just Refl <- match sh (simplify (arrayShape v))-    , Just Refl <- isIdentity p-    , Just Refl <- isIdentity f                       -> Avar v-    | Just Refl <- match sh (simplify (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)----- Evaluate a delayed computation and tie the recursive knot----computeAcc :: (Kit acc, Arrays arrs) => Embed acc aenv arrs -> acc aenv arrs-computeAcc = inject . compute----- Representation of a generator as a delayed array----generateD :: (Shape sh, Elt e)-          => PreExp acc aenv sh-          -> PreFun acc aenv (sh -> e)-          -> Embed  acc aenv (Array sh e)-generateD sh f-  = Stats.ruleFired "generateD"-  $ Embed BaseEnv (Yield sh f)----- Fuse a unary function into a delayed array. Also looks for unzips which can--- be executed in constant time; SEE [unzipD]----mapD :: (Kit acc, Shape sh, Elt a, 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 (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--- cheap; no environment changing operations are required.----unzipD-    :: forall acc aenv sh a b. (Kit acc, Shape sh, Elt a, 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))-  | TypeRscalar VectorScalarType{} <- eltType (undefined::a)-  = Nothing--  | 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.----backpermuteD-    :: (Kit acc, Shape sh')-    => PreExp     acc aenv sh'-    -> PreFun     acc aenv (sh' -> sh)-    -> Cunctation acc aenv (Array sh  e)-    -> 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)----- Transform as a combined map and backwards permutation----transformD-    :: (Kit acc, Shape sh, Shape sh', Elt a, 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"-  . 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---       cases it might be beneficial to not fuse these terms, if `f` is---       expensive and/or `sh` is large.----replicateD-    :: (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)-    -> Cunctation acc aenv (Array sh e)-replicateD sliceIndex slix cc-  = Stats.ruleFired "replicateD"-  $ backpermuteD (IndexFull sliceIndex slix (shape cc)) (extend sliceIndex slix) cc----- Dimensional slice as a backwards permutation----sliceD-    :: (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)-    -> Cunctation acc aenv (Array sl e)-sliceD sliceIndex slix cc-  = Stats.ruleFired "sliceD"-  $ backpermuteD (IndexSlice sliceIndex slix (shape cc)) (restrict sliceIndex slix) cc----- Reshape an array------ For delayed arrays this is implemented as an index space transformation. For--- manifest arrays this can be done with the standard Reshape operation in--- constant time without executing any array operations. This does not affect--- the fusion process since the term is already manifest.------ TLM: there was a runtime check to ensure the old and new shapes contained the---      same number of elements: this has been lost for the delayed cases!----reshapeD-    :: (Kit acc, Shape sh, Shape sl, Elt e)-    => Embed  acc aenv (Array sh e)-    -> PreExp acc aenv sl-    -> Embed  acc aenv (Array sl e)-reshapeD (Embed env cc) (sink env -> sl)-  | Done v      <- cc-  = Embed (env `PushEnv` inject (Reshape sl (avarIn v))) (Done ZeroIdx)--  | otherwise-  = Stats.ruleFired "reshapeD"-  $ Embed env (backpermuteD sl (reindex (shape cc) sl) cc)----- Combine two arrays element-wise with a binary function to produce a delayed--- array.----zipWithD :: (Kit acc, Shape sh, Elt a, Elt b, Elt c)-         => PreFun     acc aenv (a -> b -> c)-         -> Cunctation acc aenv (Array sh a)-         -> Cunctation acc aenv (Array sh b)-         -> Cunctation acc aenv (Array sh c)-zipWithD f cc1 cc0-  -- Two stepper functions identically accessing the same array can be kept in-  -- stepping form. This might yield a simpler final term.-  ---  | 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-  = Stats.ruleFired "zipWithD/step"-  $ Step (sh1 `Intersect` sh0) p0 (combine f f1 f0) v0--  -- Otherwise transform both delayed terms into (index -> value) mappings and-  -- combine the two indexing functions that way.-  ---  | Yield sh1 f1                <- yield cc1-  , Yield sh0 f0                <- yield cc0-  = Stats.ruleFired "zipWithD"-  $ Yield (sh1 `Intersect` sh0) (combine f f1 f0)--  where-    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'))     <- 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'----- NOTE: [Sharing vs. Fusion]------ The approach to array fusion is similar to that the first generation of Repa.--- It was discovered that the most immediately pressing problem with delayed--- arrays in Repa-1 was that it did not preserve sharing of collective--- operations, leading to excessive recomputation and severe repercussions on--- performance if the user did not explicitly intervene.------ However, as we have explicit sharing information in the term tree, so it is--- straightforward to respect sharing by not fusing let-bindings, as that--- introduces work duplication. However, sometimes we can be cleverer.------ let-floating:--- ------------------- If the binding is of manifest data, we can instead move the let-binding to a--- different point in the program and then continue to fuse into the body. This--- is done by adding the bound term to the Extend environment. In essence this--- is covering a different occurrence of the same problem Extend was introduced--- to handle: let bindings of manifest data unnecessarily get in the way of the--- fusion process. For example:------   map f (zipWith g xs (map h xs))------ after sharing recovery results in:------   map f (let a0 = xs in zipWith g a0 (map h a0))------ Without allowing the binding for a0 to float outwards, `map f` will not be--- fused into the rest of the program.------ let-elimination:--- ---------------------- Array binding points appear in the program because the array data _or_ shape--- was accessed multiple times in the source program. In general we want to fuse--- arbitrary sequences of array _data_, irrespective of how the shape component--- is used. For example, reverse is defined in the prelude as:------   reverse xs = let len   = unindex1 (shape xs)---                    pf i  = len - i - 1---                in---                backpermute (shape xs) (ilift1 pf) xs------ Sharing recovery introduces a let-binding for the input `xs` since it is used--- thrice in the definition, which impedes subsequent fusion. However the actual--- array data is only accessed once, with the remaining two uses querying the--- array shape. Since the delayed terms contain the shape of the array they--- represent as a scalar term, if the data component otherwise satisfies the--- rules for fusing terms, as it does in this example, we can eliminate the--- let-binding by pushing the scalar shape and value generation terms directly--- into the body.------ Let-elimination can also be used to _introduce_ work duplication, which may--- be beneficial if we can estimate that the cost of recomputation is less than--- the cost of completely evaluating the array and subsequently retrieving the--- data from memory.------ let-binding:--- ------------------ Ultimately, we might not want to eliminate the binding. If so, evaluate it--- and add it to a _clean_ Extend environment for the body. If not, the Extend--- list effectively _flattens_ all bindings, so any terms required for the bound--- term get lifted out to the same scope as the body. This increases their--- lifetime and hence raises the maximum memory used. If we don't do this, we--- get terms such as:------   let a0  = <terms for binding> in---   let bnd = <bound term> in---   <body term>------ rather than the following, where the scope of a0 is clearly only availably--- when evaluating the bound term, as it should be:------   let bnd =---     let a0 = <terms for binding>---     in <bound term>---   in <body term>----aletD :: (Kit acc, Arrays arrs, Arrays brrs)-      => EmbedAcc acc-      -> ElimAcc  acc-      ->          acc aenv        arrs-      ->          acc (aenv,arrs) brrs-      -> Embed    acc aenv        brrs-aletD embedAcc elimAcc (embedAcc -> Embed env1 cc1) acc0--  -- let-floating-  -- -------------  ---  -- Immediately inline the variable referring to the bound expression into the-  -- body, instead of adding to the environments and creating an indirection-  -- that must be later eliminated by shrinking.-  ---  | Done v1             <- cc1-  , Embed env0 cc0      <- embedAcc $ rebuildA (subAtop (Avar v1) . sink1 env1) acc0-  = Stats.ruleFired "aletD/float"-  $ Embed (env1 `append` env0) cc0--  -- Ensure we only call 'embedAcc' once on the body expression-  ---  | otherwise-  = aletD' embedAcc elimAcc (Embed env1 cc1) (embedAcc acc0)---aletD' :: forall acc aenv arrs brrs. (Kit acc, Arrays arrs, Arrays brrs)-       => EmbedAcc acc-       -> ElimAcc  acc-       -> Embed    acc aenv         arrs-       -> Embed    acc (aenv, arrs) brrs-       -> Embed    acc aenv         brrs-aletD' embedAcc elimAcc (Embed env1 cc1) (Embed env0 cc0)--  -- let-binding-  -- ------------  ---  -- Check whether we can eliminate the let-binding. Note that we must inspect-  -- the entire term, not just the Cunctation that would be produced by-  -- embedAcc. If we don't we can be left with dead terms that don't get-  -- eliminated. This problem occurred in the canny program.-  ---  | acc1                <- compute (Embed env1 cc1)-  , False               <- elimAcc (inject acc1) acc0-  = Stats.ruleFired "aletD/bind"-  $ Embed (BaseEnv `PushEnv` inject acc1 `append` env0) cc0--  -- let-elimination-  -- ----------------  ---  -- Handle the remaining cases in a separate function. It turns out that this-  -- is important so we aren't excessively sinking/delaying terms.-  ---  | acc0'               <- sink1 env1 acc0-  = Stats.ruleFired "aletD/eliminate"-  $ case cc1 of-      Step{}    -> eliminate env1 cc1 acc0'-      Yield{}   -> eliminate env1 cc1 acc0'--  where-    acc0 :: acc (aenv, arrs) brrs-    acc0 = computeAcc (Embed env0 cc0)--    -- The second part of let-elimination. Splitting into two steps exposes the-    -- 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. (Shape sh, Elt e, Arrays brrs)-              => Extend     acc aenv aenv'-              -> Cunctation acc      aenv' (Array sh e)-              ->            acc     (aenv', Array sh e) brrs-              -> Embed      acc aenv                    brrs-    eliminate env1 cc1 body-      | Done v1           <- cc1 = elim (arrayShape v1) (indexArray v1)-      | Step sh1 p1 f1 v1 <- cc1 = elim sh1 (f1 `compose` indexArray v1 `compose` p1)-      | Yield sh1 f1      <- cc1 = elim sh1 f1-      where-        bnd :: PreOpenAcc acc aenv' (Array sh e)-        bnd = compute' cc1--        elim :: PreExp acc aenv' sh -> PreFun acc aenv' (sh -> e) -> Embed acc aenv brrs-        elim sh1 f1-          | 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-    -- scalar expressions with an equivalent expression that generates the-    -- result directly-    ---    -- TODO: when we inline bindings we ought to let bind at the first-    --       occurrence and use a variable at all subsequent locations. At the-    --       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. (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') (weakenE SuccIdx f') avar y)-        Var i                           -> Var i-        Foreign ff f e                  -> Foreign ff f (cvtE e)-        Const c                         -> Const c-        Undef                           -> Undef-        Tuple t                         -> Tuple (cvtT t)-        Prj ix e                        -> Prj ix (cvtE e)-        IndexNil                        -> IndexNil-        IndexCons sl sz                 -> IndexCons (cvtE sl) (cvtE sz)-        IndexHead sh                    -> IndexHead (cvtE sh)-        IndexTail sz                    -> IndexTail (cvtE sz)-        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 i                  -> FromIndex (cvtE sh) (cvtE i)-        Cond p t e                      -> Cond (cvtE p) (cvtE t) (cvtE e)-        PrimConst c                     -> PrimConst c-        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)-        Coerce e                        -> Coerce (cvtE e)--        Shape a-          | Just Refl <- match a a'     -> Stats.substitution "replaceE/shape" sh'-          | otherwise                   -> exp--        Index a sh-          | 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'-          , 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-        cvtE = replaceE sh' f' avar--        cvtT :: Tuple (PreOpenExp acc env aenv) s -> Tuple (PreOpenExp acc env aenv) s-        cvtT NilTup        = NilTup-        cvtT (SnocTup t e) = cvtT t `SnocTup` cvtE 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') (weakenE SuccIdx f') avar f)--    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-          | otherwise                   -> Avar v--        Alet bnd body                   ->-          let sh'' = weaken SuccIdx sh'-              f''  = weaken SuccIdx f'-          in-          Alet (cvtA bnd) (kmap (replaceA sh'' f'' (SuccIdx avar)) body)--        Use arrs                -> Use arrs-        Unit e                  -> Unit (cvtE e)-        Acond p at ae           -> Acond (cvtE p) (cvtA at) (cvtA ae)-        Aprj ix tup             -> Aprj ix (cvtA tup)-        Atuple tup              -> Atuple (cvtAT tup)-        Awhile p f a            -> Awhile (cvtAF p) (cvtAF f) (cvtA a)-        Apply f a               -> Apply (cvtAF f) (cvtA a)-        Aforeign ff f a         -> Aforeign ff f (cvtA a)       -- no sharing between f and a-        Generate sh f           -> Generate (cvtE sh) (cvtF f)-        Map f a                 -> Map (cvtF f) (cvtA a)-        ZipWith f a b           -> ZipWith (cvtF f) (cvtA a) (cvtA b)-        Backpermute sh p a      -> Backpermute (cvtE sh) (cvtF p) (cvtA a)-        Transform sh p f a      -> Transform (cvtE sh) (cvtF p) (cvtF f) (cvtA a)-        Slice slix a sl         -> Slice slix (cvtA a) (cvtE sl)-        Replicate slix sh a     -> Replicate slix (cvtE sh) (cvtA a)-        Reshape sl a            -> Reshape (cvtE sl) (cvtA a)-        Fold f z a              -> Fold (cvtF f) (cvtE z) (cvtA a)-        Fold1 f a               -> Fold1 (cvtF f) (cvtA a)-        FoldSeg f z a s         -> FoldSeg (cvtF f) (cvtE z) (cvtA a) (cvtA s)-        Fold1Seg f a s          -> Fold1Seg (cvtF f) (cvtA a) (cvtA s)-        Scanl f z a             -> Scanl (cvtF f) (cvtE z) (cvtA a)-        Scanl1 f a              -> Scanl1 (cvtF f) (cvtA a)-        Scanl' f z a            -> Scanl' (cvtF f) (cvtE z) (cvtA a)-        Scanr f z a             -> Scanr (cvtF f) (cvtE z) (cvtA a)-        Scanr1 f a              -> Scanr1 (cvtF f) (cvtA a)-        Scanr' f z a            -> Scanr' (cvtF f) (cvtE z) (cvtA a)-        Permute f d p a         -> Permute (cvtF f) (cvtA d) (cvtF p) (cvtA a)-        Stencil f x a           -> Stencil (cvtF f) (cvtB x) (cvtA a)-        Stencil2 f x a y b      -> Stencil2 (cvtF f) (cvtB x) (cvtA a) (cvtB 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--        cvtB :: PreBoundary acc aenv s -> PreBoundary acc aenv s-        cvtB Clamp        = Clamp-        cvtB Mirror       = Mirror-        cvtB Wrap         = Wrap-        cvtB (Constant c) = Constant c-        cvtB (Function f) = Function (cvtF f)--        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-            cvt :: forall aenv a.-                   PreExp acc aenv sh -> PreFun acc aenv (sh -> e) -> Idx aenv (Array sh e)-                -> 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 (weaken SuccIdx sh'')-                                                       (weaken SuccIdx f'')-                                                       (SuccIdx avar')-                                                       af--{---        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--        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)--        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.------ Note that we take the raw unprocessed terms as input. If instead we had the--- terms for each branch in the delayed representation, this would require that--- each term has been sunk into a common environment, which implies the--- conditional has been pushed underneath the intersection of bound terms for--- both branches. This would result in redundant work processing the bindings--- for the branch not taken.----acondD :: (Kit acc, Arrays arrs)-       => EmbedAcc acc-       -> PreExp   acc aenv Bool-       ->          acc aenv arrs-       ->          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-  | otherwise               = done $ Acond p (computeAcc (embedAcc t))-                                             (computeAcc (embedAcc e))----- 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, IsAtuple arrs, Arrays arrs, Arrays a)-      => EmbedAcc acc-      -> TupleIdx (TupleRepr arrs) a-      ->       acc aenv arrs-      -> Embed acc aenv a-aprjD embedAcc ix a-  | Atuple tup <- extract a = Stats.ruleFired "aprj/Atuple" . embedAcc $ aprjAT ix tup-  | otherwise               = done $ Aprj ix (cvtA a)-  where-    cvtA :: acc aenv arrs -> acc aenv arrs-    cvtA = computeAcc . embedAcc--    aprjAT :: TupleIdx atup a -> Atuple (acc aenv) atup -> acc aenv a-    aprjAT ZeroTupIdx      (SnocAtup _ a) = a-    aprjAT (SuccTupIdx ix) (SnocAtup t _) = aprjAT ix t----- Scalar expressions--- --------------------isIdentity :: PreFun acc aenv (a -> b) -> Maybe (a :~: b)-isIdentity f-  | Lam (Body (Var ZeroIdx)) <- f       = Just Refl-  | otherwise                           = Nothing--identity :: Elt a => PreOpenFun acc env aenv (a -> a)-identity = Lam (Body (Var ZeroIdx))--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 :: (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')-        => PreOpenExp acc env aenv sh'-        -> PreOpenExp acc env aenv sh-        -> PreOpenFun acc env aenv (sh -> sh')-reindex sh' sh-  | Just Refl <- match sh sh'   = identity-  | otherwise                   = fromIndex sh' `compose` toIndex sh--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 :: (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)-restrict sliceIndex slix = Lam (Body (IndexFull sliceIndex (weakenE SuccIdx slix) (Var ZeroIdx)))--arrayShape :: (Kit acc, Shape sh, Elt e) => Idx aenv (Array sh e) -> PreExp acc aenv sh-arrayShape = Shape . avarIn--indexArray :: (Kit acc, Shape sh, Elt e) => Idx aenv (Array sh e) -> PreFun acc aenv (sh -> e)-indexArray v = Lam (Body (Index (avarIn v) (Var ZeroIdx)))--linearIndex :: (Kit acc, Shape sh, Elt e) => Idx aenv (Array sh e) -> PreFun acc aenv (Int -> e)-linearIndex v = Lam (Body (LinearIndex (avarIn v) (Var ZeroIdx)))+{-# LANGUAGE InstanceSigs         #-}+{-# LANGUAGE LambdaCase           #-}+{-# LANGUAGE OverloadedStrings    #-}+{-# LANGUAGE PatternGuards        #-}+{-# LANGUAGE RankNTypes           #-}+{-# LANGUAGE ScopedTypeVariables  #-}+{-# LANGUAGE TypeApplications     #-}+{-# LANGUAGE TypeOperators        #-}+{-# LANGUAGE ViewPatterns         #-}+{-# OPTIONS_GHC -fno-warn-incomplete-patterns #-} -- TODO: remove this & fix warnings+{-# OPTIONS_GHC -fno-warn-name-shadowing      #-}+{-# OPTIONS_HADDOCK hide #-}+-- |+-- Module      : Data.Array.Accelerate.Trafo.Fusion+-- Copyright   : [2012..2020] The Accelerate Team+-- License     : BSD3+--+-- Maintainer  : Trevor L. McDonell <trevor.mcdonell@gmail.com>+-- Stability   : experimental+-- Portability : non-portable (GHC extensions)+--+-- This module implements producer/producer and consumer/producer fusion as a+-- term rewriting of the Accelerate AST.+--+-- The function 'quench' perform the source-to-source fusion transformation,+-- while 'anneal' additionally makes the representation of embedded producers+-- explicit by representing the AST as a 'DelayedAcc' of manifest and delayed+-- nodes.+--++module Data.Array.Accelerate.Trafo.Fusion (++  convertAcc,  convertAccWith,+  convertAfun, convertAfunWith,++) where++import Data.BitSet+import Data.Array.Accelerate.AST+import Data.Array.Accelerate.AST.LeftHandSide+import Data.Array.Accelerate.AST.Environment+import Data.Array.Accelerate.AST.Var+import Data.Array.Accelerate.AST.Idx+import Data.Array.Accelerate.Error+import Data.Array.Accelerate.Trafo.Config+import Data.Array.Accelerate.Trafo.Var+import Data.Array.Accelerate.Trafo.Delayed+import Data.Array.Accelerate.Trafo.Environment+import Data.Array.Accelerate.Trafo.Shrink+import Data.Array.Accelerate.Trafo.Simplify+import Data.Array.Accelerate.Trafo.Substitution+import Data.Array.Accelerate.Representation.Array       ( Array, ArrayR(..), ArraysR )+import Data.Array.Accelerate.Representation.Shape       ( ShapeR(..), shapeType )+import Data.Array.Accelerate.Representation.Slice+import Data.Array.Accelerate.Representation.Type+import Data.Array.Accelerate.Analysis.Match+import Data.Array.Accelerate.Type++import Data.Array.Accelerate.Debug.Flags                ( array_fusion )+import qualified Data.Array.Accelerate.Debug.Stats      as Stats+#ifdef ACCELERATE_DEBUG+import System.IO.Unsafe -- for debugging+#endif++import Control.Lens                                     ( over, mapped, _2 )+import Prelude                                          hiding ( exp, until )+++-- Delayed Array Fusion+-- ====================++-- | Apply the fusion transformation to a closed de Bruijn AST+--+convertAcc :: HasCallStack => Acc arrs -> DelayedAcc arrs+convertAcc = convertAccWith defaultOptions++convertAccWith :: HasCallStack => Config -> Acc arrs -> DelayedAcc arrs+convertAccWith config = withSimplStats . convertOpenAcc config++-- | Apply the fusion transformation to a function of array arguments+--+convertAfun :: HasCallStack => Afun f -> DelayedAfun f+convertAfun = convertAfunWith defaultOptions++convertAfunWith :: HasCallStack => Config -> Afun f -> DelayedAfun f+convertAfunWith config = withSimplStats . convertOpenAfun config++-- -- | 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+#else+withSimplStats x = x+#endif+++-- | Apply the fusion transformation to an AST. This consists of two phases:+--+--    1. A bottom-up traversal that converts nodes into the internal delayed+--       representation, merging adjacent producer/producer pairs.+--+--    2. A top-down traversal that makes the representation of fused+--       consumer/producer pairs explicit as a 'DelayedAcc' of manifest and+--       delayed nodes.+--+-- TLM: Note that there really is no ambiguity as to which state an array will+--      be in following this process: an array will be either delayed or+--      manifest, and the two helper functions are even named as such! We should+--      encode this property in the type somehow...+--+convertOpenAcc+    :: HasCallStack+    => Config+    -> OpenAcc aenv arrs+    -> DelayedOpenAcc aenv arrs+convertOpenAcc config = manifest config . computeAcc . embedOpenAcc config+++-- 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+    :: HasCallStack+    => Config+    -> OpenAcc aenv (Array sh e)+    -> DelayedOpenAcc aenv (Array sh e)+delayed config (embedOpenAcc config -> Embed env cc)+  | BaseEnv <- env+  = case simplifyCC cc of+      Done v                                                -> avarsIn Manifest v+      Yield aR sh f                                         -> Delayed aR sh f (f `compose` fromIndex (arrayRshape aR) sh)+      Step  aR sh p f v+        | Just Refl <- matchOpenExp sh (arrayShape v)+        , Just Refl <- isIdentity p                         -> Delayed aR sh (f `compose` indexArray v) (f `compose` linearIndex v)+        | f'        <- f `compose` indexArray v `compose` p -> Delayed aR sh f' (f' `compose` fromIndex (arrayRshape aR) sh)+  --+  | otherwise+  = manifest config (computeAcc (Embed env cc))+++-- Convert array programs as manifest terms.+--+manifest+    :: HasCallStack+    => Config+    -> OpenAcc aenv a+    -> DelayedOpenAcc aenv a+manifest config (OpenAcc pacc) =+  let fusionError = internalError "unexpected fusible materials"+  in+  Manifest $ case pacc of+    -- Non-fusible terms+    -- -----------------+    Avar ix                 -> Avar ix+    Use aR a                -> Use aR a+    Unit t e                -> Unit t e+    Alet lhs bnd body       -> alet lhs (manifest config bnd) (manifest config body)+    Acond p t e             -> Acond p (manifest config t) (manifest config e)+    Awhile p f a            -> Awhile (cvtAF p) (cvtAF f) (manifest config a)+    Apair a1 a2             -> Apair (manifest config a1) (manifest config a2)+    Anil                    -> Anil+    Apply repr f a          -> apply repr (cvtAF f) (manifest config a)+    Aforeign repr ff f a    -> Aforeign repr ff (cvtAF f) (manifest config a)++    -- 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 a evaluated array term, else something went wrong.+    --+    Map t f a               -> Map t f (delayed config a)+    Generate repr sh f      -> Generate repr sh f+    Transform repr sh p f a -> Transform repr sh p f (delayed config a)+    Backpermute shR sh p a  -> Backpermute shR sh p (delayed config a)+    Reshape slr sl a        -> Reshape slr sl (manifest config a)++    Replicate{}             -> fusionError+    Slice{}                 -> fusionError+    ZipWith{}               -> fusionError++    -- Consumers+    -- ---------+    --+    -- Embed producers directly into the representation. For delayed terms+    -- with local bindings, these will have been floated up above the+    -- consumer already+    --+    Fold f z a              -> Fold     f z (delayed config a)+    FoldSeg i f z a s       -> FoldSeg  i f z (delayed config a) (delayed config s)+    Scan  d f z a           -> Scan     d f z (delayed config a)+    Scan' d f z a           -> Scan'    d f z (delayed config a)+    Permute f d p a         -> Permute  f (manifest config d) p (delayed config a)+    Stencil s t f x a       -> Stencil  s t f x (delayed config a)+    Stencil2 s1 s2 t f x a y b+                            -> Stencil2 s1 s2 t f x (delayed config a) y (delayed config b)+    -- Collect s               -> Collect  (cvtS s)++    where+      -- Flatten needless let-binds, which can be introduced by the+      -- conversion to the internal embeddable representation.+      --+      alet :: HasCallStack+           => ALeftHandSide a aenv aenv'+           -> DelayedOpenAcc aenv a+           -> DelayedOpenAcc aenv' b+           -> PreOpenAcc DelayedOpenAcc aenv b+      alet lhs bnd body+        | Just bodyVars  <- extractDelayedArrayVars body+        , Just Refl      <- bindingIsTrivial lhs bodyVars+        , Manifest x     <- bnd+        = x+        --+        | otherwise+        = Alet lhs bnd body++      -- Eliminate redundant application to an identity function. This+      -- arises in the use of pipe to avoid fusion and force its argument+      -- to be evaluated, i.e.:+      --+      -- > compute :: Acc a -> Acc a+      -- > compute = id >-> id+      --+      apply :: HasCallStack+            => ArraysR b+            -> PreOpenAfun DelayedOpenAcc aenv (a -> b)+            ->             DelayedOpenAcc aenv a+            -> PreOpenAcc  DelayedOpenAcc aenv b+      apply repr afun x+        | Alam lhs (Abody body)   <- afun+        , Just bodyVars           <- extractDelayedArrayVars body+        , Just Refl               <- bindingIsTrivial lhs bodyVars+        , Manifest x'             <- x+        = Stats.ruleFired "applyD/identity" x'+        --+        | otherwise+        = Apply repr afun x++      cvtAF :: HasCallStack => OpenAfun aenv f -> PreOpenAfun DelayedOpenAcc aenv f+      cvtAF (Alam lhs f) = Alam lhs (cvtAF f)+      cvtAF (Abody b)    = Abody (manifest config b)++      -- cvtS :: PreOpenSeq OpenAcc aenv senv s -> PreOpenSeq DelayedOpenAcc aenv senv s+      -- cvtS = convertOpenSeq config++convertOpenAfun :: HasCallStack => Config -> OpenAfun aenv f -> DelayedOpenAfun aenv f+convertOpenAfun c (Alam lhs f) = Alam lhs (convertOpenAfun c f)+convertOpenAfun c (Abody b) = Abody (convertOpenAcc  c b)++{--+convertOpenSeq :: Config -> PreOpenSeq OpenAcc aenv senv a -> PreOpenSeq DelayedOpenAcc aenv senv a+convertOpenSeq config s =+  case s of+    Consumer c          -> Consumer (cvtC c)+    Reify ix            -> Reify ix+    Producer p s'       -> Producer p' (convertOpenSeq config s')+      where+        p' = case p of+               StreamIn arrs     -> StreamIn arrs+               ToSeq slix sh a   -> ToSeq slix sh (delayed config 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 config 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 config b)++    cvtE :: OpenExp env aenv t -> DelayedOpenExp env aenv t+    cvtE = convertOpenExp config++    cvtF :: OpenFun env aenv f -> DelayedOpenFun env aenv f+    cvtF (Lam f)  = Lam (cvtF f)+    cvtF (Body b) = Body (cvtE b)+--}+++type EmbedAcc acc = forall aenv arrs. acc aenv arrs -> Embed acc aenv arrs+type ElimAcc  acc = forall aenv s t. acc aenv s -> acc (aenv,s) t -> Bool++-- | 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+-- number of combinations that need to be considered.+--+embedOpenAcc :: HasCallStack => Config -> OpenAcc aenv arrs -> Embed OpenAcc aenv arrs+embedOpenAcc config (OpenAcc pacc) =+  embedPreOpenAcc config matchOpenAcc (embedOpenAcc config) elimOpenAcc pacc+  where+    -- 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]+    --+    elimOpenAcc :: ElimAcc OpenAcc+    elimOpenAcc _bnd body+      | count False ZeroIdx body <= lIMIT = True+      | otherwise                         = False+      where+        lIMIT = 1++        count :: UsesOfAcc OpenAcc+        count no ix (OpenAcc pacc) = usesOfPreAcc no count ix pacc++    matchOpenAcc :: MatchAcc OpenAcc+    matchOpenAcc (OpenAcc pacc1) (OpenAcc pacc2) =+      matchPreOpenAcc matchOpenAcc pacc1 pacc2+++embedPreOpenAcc+    :: HasCallStack+    => Config+    -> MatchAcc   OpenAcc+    -> EmbedAcc   OpenAcc+    -> ElimAcc    OpenAcc+    -> PreOpenAcc OpenAcc aenv arrs+    -> Embed      OpenAcc aenv arrs+embedPreOpenAcc config matchAcc embedAcc elimAcc pacc+  = unembed+  $ case pacc of++    -- Non-fusible terms+    -- -----------------+    --+    -- 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]+    --+    Alet lhs bnd body   -> aletD embedAcc elimAcc lhs bnd body+    Anil                -> done $ Anil+    Acond p at ae       -> acondD matchAcc embedAcc (cvtE p) at ae+    Apply aR f a        -> done $ Apply aR (cvtAF f) (cvtA a)+    Awhile p f a        -> done $ Awhile (cvtAF p) (cvtAF f) (cvtA a)+    Apair a1 a2         -> done $ Apair (cvtA a1) (cvtA a2)+    Aforeign aR ff f a  -> done $ Aforeign aR ff (cvtAF f) (cvtA a)+    -- Collect s           -> collectD s++    -- Array injection+    Avar v              -> done $ Avar v+    Use aR a            -> done $ Use aR a+    Unit t e            -> done $ Unit t (cvtE e)++    -- Producers+    -- ---------+    --+    -- The class of operations that given a set of zero or more input arrays,+    -- produce a _single_ element for the output array by manipulating a+    -- _single_ element from each input array. These can be further classified+    -- as value (map, zipWith) or index space (backpermute, slice, replicate)+    -- transformations.+    --+    -- The critical feature is that each element of the output is produced+    -- independently of all others, and so we can aggressively fuse arbitrary+    -- sequences of these operations.+    --+    Generate aR sh f    -> generateD aR (cvtE sh) (cvtF f)++    Map t f a           -> mapD t (cvtF f) (embedAcc a)+    ZipWith t f a b     -> fuse2 (into (zipWithD t) (cvtF f)) a b+    Transform aR sh p f a -> transformD aR (cvtE sh) (cvtF p) (cvtF f) (embedAcc a)++    Backpermute slr sl p a+                        -> fuse (into2 (backpermuteD slr) (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 slr sl a    -> reshapeD slr (embedAcc a) (cvtE sl)++    -- Consumers+    -- ---------+    --+    -- Operations where each element of the output array depends on multiple+    -- elements of the input array. To implement these operations efficiently in+    -- parallel, we need to know how elements of the array depend on each other:+    -- a parallel scan is implemented very differently from a parallel fold, for+    -- example.+    --+    -- In order to avoid obfuscating this crucial information required for+    -- parallel implementation, fusion is separated into to phases:+    -- producer/producer, implemented above, and consumer/producer, which is+    -- implemented below. This will place producers adjacent to the consumer+    -- node, so that the producer can be directly embedded into the consumer+    -- during the code generation phase.+    --+    Fold f z a          -> embed  aR  (into2M Fold           (cvtF f) (cvtE <$> z)) a+    FoldSeg i f z a s   -> embed2 aR  (into2M (FoldSeg i)    (cvtF f) (cvtE <$> z)) a s+    Scan  d f z a       -> embed  aR  (into2M (Scan  d)      (cvtF f) (cvtE <$> z)) a+    Scan' d f z a       -> embed  aR  (into2  (Scan' d)      (cvtF f) (cvtE z)) a+    Permute f d p a     -> embed2 aR  (into2  permute        (cvtF f) (cvtF p)) d a+    Stencil s t f x a   -> embed  aR  (into2  (stencil1 s t) (cvtF f) (cvtB x)) a+    Stencil2 s1 s2 t f x a y b+                        -> embed2 aR  (into3  (stencil2 s1 s2 t) (cvtF f) (cvtB x) (cvtB y)) a b++  where+    aR = arraysR pacc++    -- If fusion is not enabled, force terms to the manifest representation+    --+    unembed :: HasCallStack => Embed OpenAcc aenv arrs -> Embed OpenAcc aenv arrs+    unembed x+      | array_fusion `member` options config = x+      | Embed env cc <- x+      , pacc         <- compute cc+      = case avarsOut extractOpenAcc pacc of+          Just vars -> Embed env $ Done vars+          _+            | DeclareVars lhs _ value <- declareVars (arraysR pacc)+              -> Embed (PushEnv env lhs $ OpenAcc pacc) $ Done $ value weakenId++    cvtA :: HasCallStack => OpenAcc aenv' a -> OpenAcc aenv' a+    cvtA = computeAcc . embedAcc++    cvtAF :: HasCallStack => PreOpenAfun OpenAcc aenv' f -> PreOpenAfun OpenAcc aenv' f+    cvtAF (Alam lhs f) = Alam lhs (cvtAF f)+    cvtAF (Abody a)    = Abody (cvtA a)++    -- Helpers to shuffle the order of arguments to a constructor+    --+    permute f p d a     = Permute f d p a++    -- NOTE: [Stencil fusion]+    --+    -- We allow stencils to delay their argument arrays with no special+    -- considerations. This means that the delayed function will be evaluated+    -- _at every element_ of the stencil pattern. We should do some analysis of+    -- when this duplication is beneficial (keeping in mind that the stencil+    -- implementations themselves may share neighbouring elements).+    --+    stencil1 s t f x a          = Stencil  s     t f x a+    stencil2 s1 s2 t f x y a b  = Stencil2 s1 s2 t f x a y b++    -- Conversions for closed scalar functions and expressions. This just+    -- applies scalar simplifications.+    --+    cvtF :: HasCallStack => Fun aenv' t -> Fun aenv' t+    cvtF = simplifyFun++    cvtE :: HasCallStack => Exp aenv' t -> Exp aenv' t+    cvtE = simplifyExp++    cvtB :: HasCallStack => Boundary aenv' t -> Boundary aenv' t+    cvtB Clamp        = Clamp+    cvtB Mirror       = Mirror+    cvtB Wrap         = Wrap+    cvtB (Constant c) = Constant c+    cvtB (Function f) = Function (cvtF f)++    -- Helpers to embed and fuse delayed terms+    --+    into :: (HasCallStack, Sink f)+         => (f env' a -> b)+         -> f env a+         -> Extend ArrayR OpenAcc env env'+         -> b+    into op a env = op (sinkA env a)++    into2 :: (HasCallStack, Sink f1, Sink f2)+          => (f1 env' a -> f2 env' b -> c)+          -> f1 env a+          -> f2 env b+          -> Extend ArrayR OpenAcc env env'+          -> c+    into2 op a b env = op (sinkA env a) (sinkA env b)++    into2M :: (HasCallStack, Sink f1, Sink f2)+           => (f1 env' a -> Maybe (f2 env' b) -> c)+           -> f1 env a+           -> Maybe (f2 env b)+           -> Extend ArrayR acc env env'+           -> c+    into2M op a b env = op (sinkA env a) (sinkA env <$> b)++    into3 :: (HasCallStack, 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 ArrayR OpenAcc env env'+          -> d+    into3 op a b c env = op (sinkA env a) (sinkA env b) (sinkA env c)++    -- Operations which can be fused into consumers. Move all of the local+    -- bindings out of the way so that the fusible function operates+    -- directly on the delayed representation. See also: [Representing+    -- delayed arrays]+    --+    fuse :: HasCallStack+         => (forall aenv'. Extend ArrayR OpenAcc aenv aenv' -> Cunctation aenv' as -> Cunctation aenv' bs)+         ->       OpenAcc aenv as+         -> Embed OpenAcc aenv bs+    fuse op (embedAcc -> Embed env cc) = Embed env (op env cc)++    fuse2 :: HasCallStack+          => (forall aenv'. Extend ArrayR OpenAcc aenv aenv' -> Cunctation aenv' as -> Cunctation aenv' bs -> Cunctation aenv' cs)+          ->       OpenAcc aenv as+          ->       OpenAcc aenv bs+          -> Embed OpenAcc aenv cs+    fuse2 op a1 a0+      | Embed env1 cc1  <- embedAcc a1+      , Embed env0 cc0  <- embedAcc (sinkA env1 a0)+      , env             <- env1 `append` env0+      = Embed env (op env (sinkA env0 cc1) cc0)++    -- Consumer operations which will be evaluated.+    --+    -- NOTE: [Fusion and the lowest common use site]+    --+    -- The AST given to us by sharing recovery will place let bindings at+    -- the lowest common use site for that shared term. For example:+    --+    --   fold f z (let a0 = ..+    --                 a1 = ..+    --              in zipWith g a0 a1)+    --+    -- In order to enable producer/consumer fusion for the above example,+    -- it is necessary to float the let bindings above the `fold`+    -- operation; SEE: [Sharing vs. Fusion] for more information.+    --+    -- Furthermore, we used to maintain an invariant that all (manifest)+    -- arguments were supplied as array variables, for example:+    --+    --   fold1 f (let a0 = ..               let a0 = ..+    --             in stencil g a0)   ==>       a1 = stencil g a0+    --                                          a2 = fold1 f a1+    --+    -- However, if the argument term will be evaluated (i.e. can not be+    -- fused into the producer) then it is better that we do _not_ float+    -- those terms, and instead leave them under the consumer. This helps+    -- to syntactically constrain the "liveness" of terms: if the argument+    -- to an operation is not an array variable, we can see directly that+    -- this will be the last use-site of that array. In particular, this is+    -- useful for the 'permute' operation to know when it can in-place+    -- update the array of default values.+    --+    embed :: HasCallStack+          => ArraysR bs+          -> (forall aenv'. Extend ArrayR OpenAcc aenv aenv' -> OpenAcc aenv' as -> PreOpenAcc OpenAcc aenv' bs)+          ->       OpenAcc aenv as+          -> Embed OpenAcc aenv bs+    embed reprBs op (embedAcc -> Embed env cc)+      | Done{} <- cc+      , DeclareVars lhs _ value <- declareVars reprBs+      = Embed (PushEnv BaseEnv lhs $ OpenAcc (op BaseEnv (computeAcc (Embed env cc)))) $ Done $ value weakenId+      | otherwise+      -- Next line is duplicated for both branches, as the type variable for the environment is instantiated differently+      , DeclareVars lhs _ value <- declareVars reprBs+      = Embed (PushEnv env     lhs $ OpenAcc (op env     (OpenAcc (compute cc))))      $ Done $ value weakenId++    embed2 :: HasCallStack+           => ArraysR cs+           -> (forall aenv'. Extend ArrayR OpenAcc aenv aenv' -> OpenAcc aenv' as -> OpenAcc aenv' bs -> PreOpenAcc OpenAcc aenv' cs)+           ->       OpenAcc aenv as+           ->       OpenAcc aenv bs+           -> Embed OpenAcc aenv cs+    embed2 reprCs op (embedAcc -> Embed env1 cc1) a0+      | Done{}          <- cc1+      , a1              <- computeAcc (Embed env1 cc1)+      = embed reprCs (\env0 -> op env0 (sinkA env0 a1)) a0+      --+      | Embed env0 cc0  <- embedAcc (sinkA env1 a0)+      , env             <- env1 `append` env0+      = case cc0 of+          Done{}+            | DeclareVars lhs _ value <- declareVars reprCs+              -> Embed (PushEnv env1 lhs $ OpenAcc (op env1 (OpenAcc (compute cc1)) (computeAcc (Embed env0 cc0))))+                       $ Done+                       $ value weakenId+          _+            -- Next line is duplicated for both branches, as the type+            -- variable for the environment is instantiated differently+            | DeclareVars lhs _ value <- declareVars reprCs+              -> Embed (PushEnv env  lhs $ OpenAcc (op env  (OpenAcc (compute (sinkA env0 cc1))) (OpenAcc (compute cc0))))+                       $ Done+                       $ value weakenId++    -- trav1 :: (Arrays as, Arrays bs)+    --       => (forall aenv'. Embed acc aenv' as -> Embed acc aenv' as)+    --       -> (forall aenv'. Extend ArrayR 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 `pushArrayEnv` inject (op env (inject (compute cc)))) doneZeroIdx++    -- trav2 :: (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 ArrayR 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 . sinkA env1 -> Embed env0 cc0)+    --   | env     <- env1 `append` env0+    --   , acc1    <- inject . compute $ sinkA env0 cc1+    --   , acc0    <- inject . compute $ cc0+    --   = Embed (env `pushArrayEnv` inject (op env acc1 acc0)) doneZeroIdx++    -- force :: Arrays as => Embed acc aenv' as -> Embed acc aenv' as+    -- force (Embed env cc)+    --   | Done{} <- cc = Embed env                                  cc+    --   | otherwise    = Embed (env `pushArrayEnv` inject (compute cc)) doneZeroIdx++    -- -- 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 `pushArrayEnv` inject (Collect s')) doneZeroIdx+++{--+-- 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 => Exp aenv' t -> Exp aenv' t+    cvtE = simplifyExp++    cvtF :: Fun aenv' t -> Fun aenv' t+    cvtF = simplifyFun++    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+-- =======================++-- NOTE: [Representing delayed arrays]+--+-- During the fusion transformation we represent terms as a pair consisting of+-- a collection of supplementary environment bindings and a description of how+-- to construct the array.+--+-- It is critical to separate these two. To create a real AST node we need both+-- the environment and array term, but analysis of how to fuse terms requires+-- only the array description. If the additional bindings are bundled as part of+-- the representation, the existentially quantified extended environment type+-- will be untouchable. This is problematic because the terms of the two arrays+-- are defined with respect to this existentially quantified type, and there is+-- no way to directly combine these two environments:+--+--   append :: Extend env env1 -> Extend env env2 -> Extend env ???+--+-- And hence, no way to combine the terms of the delayed representation.+--+-- The only way to bring terms into the same scope is to operate via the+-- manifest terms. This entails a great deal of conversion between delayed and+-- AST terms, but is certainly possible.+--+-- However, because of the limited scope into which this existential type is+-- available, we ultimately perform this process many times. In fact, complexity+-- of the fusion algorithm for an AST of N terms becomes O(r^n), where r is the+-- number of different rules we have for combining terms.+--+data Embed acc aenv a where+  Embed :: Extend ArrayR acc aenv aenv'+        -> Cunctation             aenv' a+        -> Embed         acc aenv       a++instance HasArraysR acc => HasArraysR (Embed acc) where+  arraysR (Embed _ c) = arraysR c++-- Cunctation (n): the action or an instance of delaying; a tardy action.+--+-- This describes the ways in which the fusion transformation represents+-- intermediate arrays. The fusion process operates by recasting producer array+-- computations in terms of a set of scalar functions used to construct an+-- element at each index, and fusing successive producers by combining these+-- scalar functions.+--+data Cunctation aenv a where++  -- The base case is just a real (manifest) array term. No fusion happens here.+  -- Note that the array is referenced by an index into the extended+  -- environment, ensuring that the array is manifest and making the term+  -- non-recursive in 'acc'.+  --+  Done  :: ArrayVars  aenv arrs+        -> Cunctation aenv arrs++  -- We can represent an array by its shape and a function to compute an element+  -- at each index.+  --+  Yield :: ArrayR (Array sh e)+        -> Exp        aenv sh+        -> Fun        aenv (sh -> e)+        -> Cunctation aenv (Array sh e)++  -- A more restrictive form than 'Yield' may afford greater opportunities for+  -- optimisation by a backend. This more structured form applies an index and+  -- value transform to an input array. Note that the transform is applied to an+  -- array stored as an environment index, so that the term is non-recursive and+  -- it is always possible to embed into a collective operation.+  --+  Step  :: ArrayR (Array sh' b)+        -> Exp        aenv sh'+        -> Fun        aenv (sh' -> sh)+        -> Fun        aenv (a   -> b)+        -> ArrayVar   aenv (Array sh  a)+        -> Cunctation aenv (Array sh' b)++instance HasArraysR Cunctation where+  arraysR (Done v)          = varsType v+  arraysR (Yield aR _ _)    = TupRsingle aR+  arraysR (Step aR _ _ _ _) = TupRsingle aR++instance Sink Cunctation where+  weaken k = \case+    Done v              -> Done (weakenVars k v)+    Step repr sh p f v  -> Step  repr (weaken k sh) (weaken k p) (weaken k f) (weaken k v)+    Yield repr sh f     -> Yield repr (weaken k sh) (weaken k f)++simplifyCC :: HasCallStack => Cunctation aenv a -> Cunctation aenv a+simplifyCC = \case+  Done v+    -> Done v+  Yield aR (simplifyExp -> sh) (simplifyFun -> f)+    -> Yield aR sh f+  Step aR (simplifyExp -> sh) (simplifyFun -> p) (simplifyFun -> f) v+    | Just Refl <- matchOpenExp sh (arrayShape v)+    , Just Refl <- isIdentity p+    , Just Refl <- isIdentity f+    -> Done $ TupRsingle v+    | otherwise+    -> Step aR sh p f v+++-- Convert a real AST node into the internal representation+--+done :: HasCallStack => PreOpenAcc OpenAcc aenv a -> Embed OpenAcc aenv a+done pacc+  | Just vars <- avarsOut extractOpenAcc pacc+  = Embed BaseEnv (Done vars)+  | DeclareVars lhs _ value <- declareVars (arraysR pacc)+  = Embed (PushEnv BaseEnv lhs $ OpenAcc pacc) $ Done $ value weakenId++doneZeroIdx :: ArrayR (Array sh e) -> Cunctation (aenv, Array sh e) (Array sh e)+doneZeroIdx repr = Done $ TupRsingle $ Var repr ZeroIdx++-- Recast a cunctation into a mapping from indices to elements.+--+yield :: HasCallStack+      => Cunctation aenv (Array sh e)+      -> Cunctation aenv (Array sh e)+yield cc =+  case cc of+    Yield{}                        -> cc+    Step tR sh p f v               -> Yield tR sh (f `compose` indexArray v `compose` p)+    Done (TupRsingle v@(Var tR _)) -> Yield tR (arrayShape v) (indexArray v)+++-- Recast a cunctation into transformation step form. Not possible if the source+-- was in the Yield formulation.+--+step :: HasCallStack+     => Cunctation aenv (Array sh e)+     -> Maybe (Cunctation aenv (Array sh e))+step cc =+  case cc of+    Yield{} -> Nothing+    Step{}  -> Just cc+    Done (TupRsingle v@(Var aR@(ArrayR shR tR) _))+      -> Just $ Step aR (arrayShape v) (identity $ shapeType shR) (identity tR) v+++-- Get the shape of a delayed array+--+shape :: HasCallStack => Cunctation aenv (Array sh e) -> Exp aenv sh+shape cc+  | Just (Step _ sh _ _ _) <- step cc  = sh+  | Yield _ sh _           <- yield cc = sh+++-- 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"++{--+-- Rearrange type arguments to fit with Sink type class.+newtype SinkSeq acc senv aenv a = SinkSeq { unSinkSeq :: PreOpenSeq acc aenv senv a }++-- 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 (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++    where+      weakenL :: forall senv' arrs'. PreOpenSeq acc aenv senv' arrs' -> PreOpenSeq acc aenv' senv' arrs'+      weakenL s' = unSinkSeq (weaken k (SinkSeq s'))++      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+-- ===========================================++-- Array computations+-- ------------------++-- Evaluate a delayed computation and tie the recursive knot+--+-- We do a bit of extra work to (try to) maintain that terms should be left+-- at their lowest common use site. SEE: [Fusion and the lowest common use site]+--+computeAcc+    :: HasCallStack+    => Embed OpenAcc aenv arrs+    -> OpenAcc aenv arrs+computeAcc (Embed      BaseEnv              cc) = OpenAcc (compute cc)+computeAcc (Embed env@(PushEnv bot lhs top) cc) =+  case simplifyCC cc of+    Done v          -> bindA env (avarsIn OpenAcc v)+    Yield repr sh f -> bindA env (OpenAcc (Generate repr sh f))+    Step repr sh p f v@(Var _ ix)+      | Just Refl <- matchOpenExp sh (arrayShape v)+      , Just Refl <- isIdentity p+      -> case ix of+           ZeroIdx+             | LeftHandSideSingle ArrayR{} <- lhs+             , Just (OpenAccFun g) <- strengthen noTop (OpenAccFun f)+                  -> bindA bot (OpenAcc (Map (arrayRtype repr) g top))+           _      -> bindA env (OpenAcc (Map (arrayRtype repr) f (avarIn OpenAcc v)))++      | Just Refl <- isIdentity f+      -> case ix of+           ZeroIdx+             | LeftHandSideSingle ArrayR{} <- lhs+             , Just (OpenAccFun q)  <- strengthen noTop (OpenAccFun p)+             , Just (OpenAccExp sz) <- strengthen noTop (OpenAccExp sh)+                  -> bindA bot (OpenAcc (Backpermute (arrayRshape repr) sz q top))+           _      -> bindA env (OpenAcc (Backpermute (arrayRshape repr) sh p (avarIn OpenAcc v)))++      | otherwise+      -> case ix of+           ZeroIdx+             | LeftHandSideSingle ArrayR{} <- lhs+             , Just (OpenAccFun g)  <- strengthen noTop (OpenAccFun f)+             , Just (OpenAccFun q)  <- strengthen noTop (OpenAccFun p)+             , Just (OpenAccExp sz) <- strengthen noTop (OpenAccExp sh)+                  -> bindA bot (OpenAcc (Transform repr sz q g top))+           _      -> bindA env (OpenAcc (Transform repr sh p f (avarIn OpenAcc v)))++  where+    bindA :: HasCallStack+          => Extend ArrayR OpenAcc aenv aenv'+          -> OpenAcc aenv' a+          -> OpenAcc aenv  a+    bindA BaseEnv             b = b+    bindA (PushEnv env lhs a) b+      -- If the freshly bound value is directly, returned, we don't have to bind it in a+      -- let. We can do this if the left hand side does not contain wildcards (other than+      -- wildcards for unit / nil) and if the value contains the same variables.+      | Just vars <- extractOpenArrayVars b+      , Just Refl <- bindingIsTrivial lhs vars = bindA env a+      | otherwise                              = bindA env (OpenAcc (Alet lhs a b))++    noTop :: (aenv, a) :?> aenv+    noTop ZeroIdx      = Nothing+    noTop (SuccIdx ix) = Just ix+++-- Convert the internal representation of delayed arrays into a real AST+-- node. Use the most specific version of a combinator whenever possible.+--+compute+    :: HasCallStack+    => Cunctation aenv arrs+    -> PreOpenAcc OpenAcc aenv arrs+compute cc = case simplifyCC cc of+  Done TupRunit                             -> Anil+  Done (TupRsingle v@(Var ArrayR{} _))      -> Avar v+  Done (TupRpair v1 v2)                     -> avarsIn OpenAcc v1 `Apair` avarsIn OpenAcc v2+  Yield repr  sh f                          -> Generate repr sh f+  Step (ArrayR shR tR) sh p f v+    | Just Refl <- matchOpenExp sh (arrayShape v)+    , Just Refl <- isIdentity p             -> Map tR f (avarIn OpenAcc v)+    | Just Refl <- isIdentity f             -> Backpermute shR sh p (avarIn OpenAcc v)+    | otherwise                             -> Transform (ArrayR shR tR) sh p f (avarIn OpenAcc v)+++-- Representation of a generator as a delayed array+--+generateD+    :: HasCallStack+    => ArrayR (Array sh e)+    -> Exp aenv sh+    -> Fun aenv (sh -> e)+    -> Embed OpenAcc aenv (Array sh e)+generateD repr sh f+  = Stats.ruleFired "generateD"+  $ Embed BaseEnv (Yield repr sh f)+++-- Fuse a unary function into a delayed array. Also looks for unzips which can+-- be executed in constant time; SEE [unzipD]+--+mapD :: HasCallStack+     => TypeR b+     -> Fun           aenv (a -> b)+     -> Embed OpenAcc aenv (Array sh a)+     -> Embed OpenAcc aenv (Array sh b)+mapD tR f (unzipD tR f -> Just a) = a+mapD tR f (Embed env cc)+  = Stats.ruleFired "mapD"+  $ Embed env (go cc)+  where+    go (step  -> Just (Step (ArrayR shR _) sh ix g v)) = Step  (ArrayR shR tR) sh ix (sinkA env f `compose` g) v+    go (yield -> Yield (ArrayR shR _) sh g)            = Yield (ArrayR shR tR) sh    (sinkA 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.+--+unzipD+    :: HasCallStack+    => TypeR b+    -> Fun                  aenv (a -> b)+    -> Embed OpenAcc        aenv (Array sh a)+    -> Maybe (Embed OpenAcc aenv (Array sh b))+unzipD tR f (Embed env cc@(Done v))+  | Lam lhs (Body a) <- f+  , Just vars        <- extractExpVars a+  , ArrayR shR _     <- arrayR cc+  , f' <- Lam lhs $ Body $ expVars vars+  = Just $ Embed (env `pushArrayEnv` OpenAcc (Map tR f' $ avarsIn OpenAcc v)) $ doneZeroIdx $ ArrayR shR tR++unzipD _ _ _+  = Nothing++-- Fuse an index space transformation function that specifies where elements in+-- the destination array read there data from in the source array.+--+backpermuteD+    :: HasCallStack+    => ShapeR sh'+    -> Exp        aenv sh'+    -> Fun        aenv (sh' -> sh)+    -> Cunctation aenv (Array sh  e)+    -> Cunctation aenv (Array sh' e)+backpermuteD shR' sh' p = Stats.ruleFired "backpermuteD" . go+  where+    go (step  -> Just (Step (ArrayR _ tR) _ q f v)) = Step  (ArrayR shR' tR) sh' (q `compose` p) f v+    go (yield -> Yield (ArrayR _ tR) _ g)           = Yield (ArrayR shR' tR) sh' (g `compose` p)+++-- Transform as a combined map and backwards permutation+--+transformD+    :: HasCallStack+    => ArrayR (Array sh' b)+    -> Exp           aenv sh'+    -> Fun           aenv (sh' -> sh)+    -> Fun           aenv (a   -> b)+    -> Embed OpenAcc aenv (Array sh  a)+    -> Embed OpenAcc aenv (Array sh' b)+transformD (ArrayR shR' tR) sh' p f+  = Stats.ruleFired "transformD"+  . fuse (into2 (backpermuteD shR') sh' p)+  . mapD tR f+  where+    fuse :: HasCallStack+         => (forall aenv'. Extend ArrayR OpenAcc aenv aenv' -> Cunctation aenv' as -> Cunctation aenv' bs)+         -> Embed OpenAcc aenv as+         -> Embed OpenAcc aenv bs+    fuse op (Embed env cc) = Embed env (op env cc)++    into2 :: (HasCallStack, Sink f1, Sink f2)+          => (f1 env' a -> f2 env' b -> c)+          -> f1 env a+          -> f2 env b+          -> Extend ArrayR OpenAcc env env'+          -> c+    into2 op a b env = op (sinkA env a) (sinkA env b)+++-- Replicate as a backwards permutation+--+-- TODO: If we have a pattern such as `replicate sh (map f xs)` then in some+--       cases it might be beneficial to not fuse these terms, if `f` is+--       expensive and/or `sh` is large.+--+replicateD+    :: HasCallStack+    => SliceIndex slix sl co sh+    -> Exp        aenv slix+    -> Cunctation aenv (Array sl e)+    -> Cunctation aenv (Array sh e)+replicateD sliceIndex slix cc+  = Stats.ruleFired "replicateD"+  $ backpermuteD (sliceDomainR sliceIndex) (IndexFull sliceIndex slix (shape cc)) (extend sliceIndex slix) cc+++-- Dimensional slice as a backwards permutation+--+sliceD+    :: HasCallStack+    => SliceIndex slix sl co sh+    -> Exp            aenv slix+    -> Cunctation aenv (Array sh e)+    -> Cunctation aenv (Array sl e)+sliceD sliceIndex slix cc+  = Stats.ruleFired "sliceD"+  $ backpermuteD (sliceShapeR sliceIndex) (IndexSlice sliceIndex slix (shape cc)) (restrict sliceIndex slix) cc+++-- Reshape an array+--+-- For delayed arrays this is implemented as an index space transformation. For+-- manifest arrays this can be done with the standard Reshape operation in+-- constant time without executing any array operations. This does not affect+-- the fusion process since the term is already manifest.+--+-- TLM: there was a runtime check to ensure the old and new shapes contained the+--      same number of elements: this has been lost for the delayed cases!+--+reshapeD+    :: HasCallStack+    => ShapeR sl+    -> Embed OpenAcc aenv (Array sh e)+    -> Exp           aenv sl+    -> Embed OpenAcc aenv (Array sl e)+reshapeD slr (Embed env cc) (sinkA env -> sl)+  | Done v <- cc+  = Embed (env `pushArrayEnv` OpenAcc (Reshape slr sl (avarsIn OpenAcc v))) $ doneZeroIdx repr++  | otherwise+  = Stats.ruleFired "reshapeD"+  $ Embed env (backpermuteD slr sl (reindex (arrayRshape $ arrayR cc) (shape cc) slr sl) cc)++  where+    ArrayR _ tR = arrayR cc+    repr        = ArrayR slr tR+++-- Combine two arrays element-wise with a binary function to produce a delayed+-- array.+--+zipWithD+    :: HasCallStack+    => TypeR c+    -> Fun        aenv (a -> b -> c)+    -> Cunctation aenv (Array sh a)+    -> Cunctation aenv (Array sh b)+    -> Cunctation aenv (Array sh c)+zipWithD tR f cc1 cc0+  -- Two stepper functions identically accessing the same array can be kept in+  -- stepping form. This might yield a simpler final term.+  --+  | Just (Step (ArrayR shR _) sh1 p1 f1 v1) <- step cc1+  , Just (Step _              sh0 p0 f0 v0) <- step cc0+  , Just Refl                               <- matchVar v1 v0+  , Just Refl                               <- matchOpenFun p1 p0+  = Stats.ruleFired "zipWithD/step"+  $ Step (ArrayR shR tR) (intersect shR sh1 sh0) p0 (combine f f1 f0) v0++  -- Otherwise transform both delayed terms into (index -> value) mappings and+  -- combine the two indexing functions that way.+  --+  | Yield (ArrayR shR _) sh1 f1 <- yield cc1+  , Yield _              sh0 f0 <- yield cc0+  = Stats.ruleFired "zipWithD"+  $ Yield (ArrayR shR tR) (intersect shR sh1 sh0) (combine f f1 f0)++  where+    combine :: forall aenv a b c e. HasCallStack+            => Fun aenv (a -> b -> c)+            -> Fun aenv (e -> a)+            -> Fun aenv (e -> b)+            -> Fun aenv (e -> c)+    combine c ixa ixb+      | Lam lhs1 (Body ixa')          <- ixa                          -- else the skolem 'e' will escape+      , Lam lhs2 (Body ixb')          <- ixb+      -- The two LeftHandSides may differ in the use of wildcards. If they do not match, we must+      -- combine them as done in `combineLhs`. As this will probably not occur often and requires+      -- additional weakening, we do a quick check whether the left hand sides are equal.+      --+      = case matchELeftHandSide lhs1 lhs2 of+          Just Refl+            | Lam lhsA (Lam lhsB (Body c')) <- weakenE (weakenWithLHS lhs1) c+              -> Lam lhs1 $ Body $ Let lhsA ixa'  $ Let lhsB (weakenE (weakenWithLHS lhsA)       ixb') c'+          Nothing+            | CombinedLHS lhs k1 k2 <- combineLhs lhs1 lhs2+            , Lam lhsA (Lam lhsB (Body c')) <- weakenE (weakenWithLHS lhs) c+            , ixa'' <- weakenE k1 ixa'+              -> Lam lhs  $ Body $ Let lhsA ixa'' $ Let lhsB (weakenE (weakenWithLHS lhsA .> k2) ixb') c'++combineLhs+    :: HasCallStack+    => LeftHandSide s t env env1'+    -> LeftHandSide s t env env2'+    -> CombinedLHS  s t env1' env2' env+combineLhs = go weakenId weakenId+  where+    go :: env1 :> env -> env2 :> env -> LeftHandSide s t env1 env1' -> LeftHandSide s t env2 env2' -> CombinedLHS s t env1' env2' env+    go k1 k2 (LeftHandSideWildcard tR) (LeftHandSideWildcard _) = CombinedLHS (LeftHandSideWildcard tR)    k1        k2+    go k1 k2 (LeftHandSideSingle tR)   (LeftHandSideSingle _)   = CombinedLHS (LeftHandSideSingle tR)      (sink k1) (sink k2)+    go k1 k2 (LeftHandSidePair l1 h1)  (LeftHandSidePair l2 h2)+      | CombinedLHS l k1'  k2'  <- go k1  k2  l1 l2+      , CombinedLHS h k1'' k2'' <- go k1' k2' h1 h2             = CombinedLHS (LeftHandSidePair l h)       k1''      k2''+    go k1 k2 (LeftHandSideWildcard _)  lhs+      | Exists lhs' <- rebuildLHS lhs                           = CombinedLHS lhs'        (weakenWithLHS lhs' .> k1) (sinkWithLHS lhs lhs' k2)+    go k1 k2 lhs                       (LeftHandSideWildcard _)+      | Exists lhs' <- rebuildLHS lhs                           = CombinedLHS lhs'        (sinkWithLHS lhs lhs' k1)  (weakenWithLHS lhs' .> k2)++data CombinedLHS s t env1' env2' env where+  CombinedLHS :: LeftHandSide s t env env'+              -> env1' :> env'+              -> env2' :> env'+              -> CombinedLHS s t env1' env2' env++-- NOTE: [Sharing vs. Fusion]+--+-- The approach to array fusion is similar to that the first generation of Repa.+-- It was discovered that the most immediately pressing problem with delayed+-- arrays in Repa-1 was that it did not preserve sharing of collective+-- operations, leading to excessive recomputation and severe repercussions on+-- performance if the user did not explicitly intervene.+--+-- However, as we have explicit sharing information in the term tree, so it is+-- straightforward to respect sharing by not fusing let-bindings, as that+-- introduces work duplication. However, sometimes we can be cleverer.+--+-- let-floating:+-- -------------+--+-- If the binding is of manifest data, we can instead move the let-binding to a+-- different point in the program and then continue to fuse into the body. This+-- is done by adding the bound term to the Extend environment. In essence this+-- is covering a different occurrence of the same problem Extend was introduced+-- to handle: let bindings of manifest data unnecessarily get in the way of the+-- fusion process. For example:+--+--   map f (zipWith g xs (map h xs))+--+-- after sharing recovery results in:+--+--   map f (let a0 = xs in zipWith g a0 (map h a0))+--+-- Without allowing the binding for a0 to float outwards, `map f` will not be+-- fused into the rest of the program.+--+-- let-elimination:+-- ----------------+--+-- Array binding points appear in the program because the array data _or_ shape+-- was accessed multiple times in the source program. In general we want to fuse+-- arbitrary sequences of array _data_, irrespective of how the shape component+-- is used. For example, reverse is defined in the prelude as:+--+--   reverse xs = let len  = unindex1 (shape xs)+--                    pf i = len - i - 1+--                in+--                backpermute (shape xs) (ilift1 pf) xs+--+-- Sharing recovery introduces a let-binding for the input `xs` since it is used+-- thrice in the definition, which impedes subsequent fusion. However the actual+-- array data is only accessed once, with the remaining two uses querying the+-- array shape. Since the delayed terms contain the shape of the array they+-- represent as a scalar term, if the data component otherwise satisfies the+-- rules for fusing terms, as it does in this example, we can eliminate the+-- let-binding by pushing the scalar shape and value generation terms directly+-- into the body.+--+-- Let-elimination can also be used to _introduce_ work duplication, which may+-- be beneficial if we can estimate that the cost of re-computation is less than+-- the cost of completely evaluating the array and subsequently retrieving the+-- data from memory.+--+-- let-binding:+-- ------------+--+-- Ultimately, we might not want to eliminate the binding. If so, evaluate it+-- and add it to a _clean_ Extend environment for the body. If not, the Extend+-- list effectively _flattens_ all bindings, so any terms required for the bound+-- term get lifted out to the same scope as the body. This increases their+-- lifetime and hence raises the maximum memory used. If we don't do this, we+-- get terms such as:+--+--   let a0  = <terms for binding> in+--   let bnd = <bound term> in+--   <body term>+--+-- rather than the following, where the scope of a0 is clearly only availably+-- when evaluating the bound term, as it should be:+--+--   let bnd =+--     let a0 = <terms for binding>+--     in <bound term>+--   in <body term>+--+aletD :: HasCallStack+      => EmbedAcc OpenAcc+      -> ElimAcc  OpenAcc+      -> ALeftHandSide arrs aenv aenv'+      ->       OpenAcc aenv  arrs+      ->       OpenAcc aenv' brrs+      -> Embed OpenAcc aenv  brrs+aletD embedAcc elimAcc lhs (embedAcc -> Embed env1 cc1) acc0++  -- let-floating+  -- ------------+  --+  -- Immediately inline the variable referring to the bound expression into the+  -- body, instead of adding to the environments and creating an indirection+  -- that must be later eliminated by shrinking.+  --+  | LeftHandSideSingle _                  <- lhs+  , Done (TupRsingle v1@(Var ArrayR{} _)) <- cc1+  , Embed env0 cc0                        <- embedAcc $ rebuildA (subAtop (Avar v1) . sink1 env1) acc0+  = Stats.ruleFired "aletD/float"+  $ Embed (env1 `append` env0) cc0++  -- Ensure we only call 'embedAcc' once on the body expression+  --+  | otherwise+  = aletD' embedAcc elimAcc lhs (Embed env1 cc1) (embedAcc acc0)+++aletD' :: forall aenv aenv' arrs brrs. HasCallStack+       => EmbedAcc OpenAcc+       -> ElimAcc OpenAcc+       -> ALeftHandSide arrs aenv aenv'+       -> Embed OpenAcc aenv  arrs+       -> Embed OpenAcc aenv' brrs+       -> Embed OpenAcc aenv  brrs+aletD' embedAcc elimAcc (LeftHandSideSingle ArrayR{}) (Embed env1 cc1) (Embed env0 cc0)++  -- let-binding+  -- -----------+  --+  -- Check whether we can eliminate the let-binding. Note that we must inspect+  -- the entire term, not just the Cunctation that would be produced by+  -- embedAcc. If we don't we can be left with dead terms that don't get+  -- eliminated. This problem occurred in the canny program.+  --+  | acc1    <- computeAcc (Embed env1 cc1)+  , False   <- elimAcc acc1 acc0+  = Stats.ruleFired "aletD/bind"+  $ Embed (BaseEnv `pushArrayEnv` acc1 `append` env0) cc0++  -- let-elimination+  -- ---------------+  --+  -- Handle the remaining cases in a separate function. It turns out that this+  -- is important so we aren't excessively sinking/delaying terms.+  --+  | acc0'   <- sink1 env1 acc0+  = Stats.ruleFired "aletD/eliminate"+  $ case cc1 of+      Step{}  -> eliminate env1 cc1 acc0'+      Yield{} -> eliminate env1 cc1 acc0'++  where+    acc0 :: OpenAcc aenv' brrs+    acc0 = computeAcc (Embed env0 cc0)++    kmap :: forall aenv a b. (PreOpenAcc OpenAcc aenv a -> PreOpenAcc OpenAcc aenv b)+         -> OpenAcc aenv a+         -> OpenAcc aenv b+    kmap f (OpenAcc pacc) = OpenAcc (f pacc)++    -- The second part of let-elimination. Splitting into two steps exposes the+    -- 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. HasCallStack+        => Extend ArrayR OpenAcc aenv aenv'+        -> Cunctation aenv' (Array sh e)+        -> OpenAcc (aenv', Array sh e) brrs+        -> Embed OpenAcc aenv brrs+    eliminate env1 cc1 body+      | Done v1                  <- cc1+      , TupRsingle v1'@(Var r _) <- v1  = elim r (arrayShape v1') (indexArray v1')+      | Step r sh1 p1 f1 v1      <- cc1 = elim r sh1 (f1 `compose` indexArray v1 `compose` p1)+      | Yield r sh1 f1           <- cc1 = elim r sh1 f1+      where+        bnd :: PreOpenAcc OpenAcc aenv' (Array sh e)+        bnd = compute cc1++        elim :: HasCallStack+             => ArrayR (Array sh e)+             -> Exp aenv' sh+             -> Fun aenv' (sh -> e)+             -> Embed OpenAcc aenv brrs+        elim r sh1 f1+          | sh1'              <- weaken (weakenSucc' weakenId) sh1+          , f1'               <- weaken (weakenSucc' weakenId) f1+          , Embed env0' cc0'  <- embedAcc $ rebuildA (subAtop bnd) $ kmap (replaceA sh1' f1' $ Var r ZeroIdx) body+          = Embed (env1 `append` env0') cc0'++    -- As part of let-elimination, we need to replace uses of array variables in+    -- scalar expressions with an equivalent expression that generates the+    -- result directly+    --+    -- TODO: when we inline bindings we ought to let bind at the first+    --       occurrence and use a variable at all subsequent locations. At the+    --       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. HasCallStack+             => OpenExp env aenv sh+             -> OpenFun env aenv (sh -> e)+             -> ArrayVar aenv (Array sh e)+             -> OpenExp env aenv t+             -> OpenExp env aenv t+    replaceE sh' f' avar@(Var (ArrayR shR _) _) exp =+      case exp of+        Let lhs x y                     -> let k = weakenWithLHS lhs+                                           in  Let lhs (cvtE x) (replaceE (weakenE k sh') (weakenE k f') avar y)+        Evar var                        -> Evar var+        Foreign tR ff f e               -> Foreign tR ff f (cvtE e)+        Const tR c                      -> Const tR c+        Undef tR                        -> Undef tR+        Nil                             -> Nil+        Pair e1 e2                      -> Pair (cvtE e1) (cvtE e2)+        VecPack vR e                    -> VecPack vR (cvtE e)+        VecUnpack vR e                  -> VecUnpack vR (cvtE e)+        IndexSlice x ix sh              -> IndexSlice x (cvtE ix) (cvtE sh)+        IndexFull x ix sl               -> IndexFull x (cvtE ix) (cvtE sl)+        ToIndex shR' sh ix              -> ToIndex shR' (cvtE sh) (cvtE ix)+        FromIndex shR' sh i             -> FromIndex shR' (cvtE sh) (cvtE i)+        Case e rhs def                  -> Case (cvtE e) (over (mapped . _2) cvtE rhs) (fmap cvtE def)+        Cond p t e                      -> Cond (cvtE p) (cvtE t) (cvtE e)+        PrimConst c                     -> PrimConst c+        PrimApp g x                     -> PrimApp g (cvtE x)+        ShapeSize shR' sh               -> ShapeSize shR' (cvtE sh)+        While p f x                     -> While (replaceF sh' f' avar p) (replaceF sh' f' avar f) (cvtE x)+        Coerce t1 t2 e                  -> Coerce t1 t2 (cvtE e)++        Shape a+          | Just Refl <- matchVar a avar -> Stats.substitution "replaceE/shape" sh'+          | otherwise                    -> exp++        Index a sh+          | Just Refl        <- matchVar a avar+          , Lam lhs (Body b) <- f'      -> Stats.substitution "replaceE/!" . cvtE $ Let lhs sh b+          | otherwise                   -> Index a (cvtE sh)++        LinearIndex a i+          | Just Refl        <- matchVar a avar+          , Lam lhs (Body b) <- f'+                                        -> Stats.substitution "replaceE/!!" . cvtE+                                         $ Let lhs+                                               (Let (LeftHandSideSingle scalarTypeInt) i $ FromIndex shR (weakenE (weakenSucc' weakenId) sh') $ Evar $ Var scalarTypeInt ZeroIdx)+                                               b+          | otherwise                   -> LinearIndex a (cvtE i)++      where+        cvtE :: OpenExp env aenv s -> OpenExp env aenv s+        cvtE = replaceE sh' f' avar++    replaceF :: forall env aenv sh e t. HasCallStack+             => OpenExp env aenv sh+             -> OpenFun env aenv (sh -> e)+             -> ArrayVar aenv (Array sh e)+             -> OpenFun env aenv t+             -> OpenFun env aenv t+    replaceF sh' f' avar fun =+      case fun of+        Body e          -> Body (replaceE sh' f' avar e)+        Lam lhs f       -> let k = weakenWithLHS lhs+                           in  Lam lhs (replaceF (weakenE k sh') (weakenE k f') avar f)++    replaceA :: forall aenv sh e a. HasCallStack+             => Exp aenv sh+             -> Fun aenv (sh -> e)+             -> ArrayVar aenv (Array sh e)+             -> PreOpenAcc OpenAcc aenv a+             -> PreOpenAcc OpenAcc aenv a+    replaceA sh' f' avar pacc =+      case pacc of+        Avar v+          | Just Refl <- matchVar v avar -> Avar avar+          | otherwise                    -> Avar v++        Alet lhs bnd (body :: OpenAcc aenv1 a) ->+          let w :: aenv :> aenv1+              w    = weakenWithLHS lhs+              sh'' = weaken w sh'+              f''  = weaken w f'+          in+          Alet lhs (cvtA bnd) (kmap (replaceA sh'' f'' (weaken w avar)) body)++        Use repr arrs           -> Use repr arrs+        Unit tR e               -> Unit tR (cvtE e)+        Acond p at ae           -> Acond (cvtE p) (cvtA at) (cvtA ae)+        Anil                    -> Anil+        Apair a1 a2             -> Apair (cvtA a1) (cvtA a2)+        Awhile p f a            -> Awhile (cvtAF p) (cvtAF f) (cvtA a)+        Apply repr f a          -> Apply repr (cvtAF f) (cvtA a)+        Aforeign repr ff f a    -> Aforeign repr ff f (cvtA a)       -- no sharing between f and a+        Generate repr sh f      -> Generate repr (cvtE sh) (cvtF f)+        Map tR f a              -> Map tR (cvtF f) (cvtA a)+        ZipWith tR f a b        -> ZipWith tR (cvtF f) (cvtA a) (cvtA b)+        Backpermute shR sh p a  -> Backpermute shR (cvtE sh) (cvtF p) (cvtA a)+        Transform repr sh p f a -> Transform repr (cvtE sh) (cvtF p) (cvtF f) (cvtA a)+        Slice slix a sl         -> Slice slix (cvtA a) (cvtE sl)+        Replicate slix sh a     -> Replicate slix (cvtE sh) (cvtA a)+        Reshape shR sl a        -> Reshape shR (cvtE sl) (cvtA a)+        Fold f z a              -> Fold (cvtF f) (cvtE <$> z) (cvtA a)+        FoldSeg i f z a s       -> FoldSeg i (cvtF f) (cvtE <$> z) (cvtA a) (cvtA s)+        Scan  d f z a           -> Scan d (cvtF f) (cvtE <$> z) (cvtA a)+        Scan' d f z a           -> Scan' d (cvtF f) (cvtE z) (cvtA a)+        Permute f d p a         -> Permute (cvtF f) (cvtA d) (cvtF p) (cvtA a)+        Stencil s t f x a       -> Stencil s t (cvtF f) (cvtB x) (cvtA a)+        Stencil2 s1 s2 t f x a y b+                                -> Stencil2 s1 s2 t (cvtF f) (cvtB x) (cvtA a) (cvtB y) (cvtA b)+        -- Collect seq             -> Collect (cvtSeq seq)++      where+        cvtA :: OpenAcc aenv s -> OpenAcc aenv s+        cvtA = kmap (replaceA sh' f' avar)++        cvtE :: Exp aenv s -> Exp aenv s+        cvtE = replaceE sh' f' avar++        cvtF :: Fun aenv s -> Fun aenv s+        cvtF = replaceF sh' f' avar++        cvtB :: Boundary aenv s -> Boundary aenv s+        cvtB Clamp        = Clamp+        cvtB Mirror       = Mirror+        cvtB Wrap         = Wrap+        cvtB (Constant c) = Constant c+        cvtB (Function f) = Function (cvtF f)++        cvtAF :: HasCallStack => PreOpenAfun OpenAcc aenv s -> PreOpenAfun OpenAcc aenv s+        cvtAF = cvt sh' f' avar+          where+            cvt :: forall aenv a.+                   Exp aenv sh -> Fun aenv (sh -> e) -> ArrayVar aenv (Array sh e)+                -> PreOpenAfun OpenAcc aenv a+                -> PreOpenAfun OpenAcc aenv a+            cvt sh'' f'' avar' (Abody a) = Abody $ kmap (replaceA sh'' f'' avar') a+            cvt sh'' f'' avar' (Alam lhs (af :: PreOpenAfun OpenAcc aenv1 b)) =+              Alam lhs $ cvt (weaken w sh'')+                (weaken w f'')+                (weaken w avar')+                af+              where+                w :: aenv :> aenv1+                w = weakenWithLHS lhs++-- Do not fuse bindings of multiple variables+aletD' _ _ lhs (Embed env1 cc1) (Embed env0 cc0)+  = Stats.ruleFired "aletD/bind"+  $ Embed (PushEnv BaseEnv lhs acc1 `append` env0) cc0+  where+    acc1 = computeAcc $ Embed env1 cc1+++{--+        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++        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)++        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+--}+++-- Array conditionals, in particular eliminate branches when the predicate+-- reduces to a known constant.+--+-- Note that we take the raw unprocessed terms as input. If instead we had the+-- terms for each branch in the delayed representation, this would require that+-- each term has been sunk into a common environment, which implies the+-- conditional has been pushed underneath the intersection of bound terms for+-- both branches. This would result in redundant work processing the bindings+-- for the branch not taken.+--+acondD :: HasCallStack+       => MatchAcc OpenAcc+       -> EmbedAcc OpenAcc+       -> Exp              aenv PrimBool+       ->          OpenAcc aenv arrs+       ->          OpenAcc aenv arrs+       -> Embed    OpenAcc aenv arrs+acondD matchAcc embedAcc p t e+  | Const _ 1 <- p            = Stats.knownBranch "True"      $ embedAcc t+  | Const _ 0 <- p            = Stats.knownBranch "False"     $ embedAcc e+  | Just Refl <- matchAcc t e = Stats.knownBranch "redundant" $ embedAcc e+  | otherwise                 = done $ Acond p (computeAcc (embedAcc t))+                                               (computeAcc (embedAcc e))+++-- Scalar expressions+-- ------------------++identity :: TypeR a -> OpenFun env aenv (a -> a)+identity t+  | DeclareVars lhs _ value <- declareVars t+  = Lam lhs $ Body $ expVars $ value weakenId++toIndex :: ShapeR sh -> OpenExp env aenv sh -> OpenFun env aenv (sh -> Int)+toIndex shR sh+  | DeclareVars lhs k value <- declareVars $ shapeType shR+  = Lam lhs $ Body $ ToIndex shR (weakenE k sh) $ expVars $ value weakenId++fromIndex :: ShapeR sh -> OpenExp env aenv sh -> OpenFun env aenv (Int -> sh)+fromIndex shR sh+  = Lam (LeftHandSideSingle scalarTypeInt)+  $ Body+  $ FromIndex shR (weakenE (weakenSucc' weakenId) sh)+  $ Evar+  $ Var scalarTypeInt ZeroIdx++intersect :: ShapeR sh -> OpenExp env aenv sh -> OpenExp env aenv sh -> OpenExp env aenv sh+intersect = mkShapeBinary f+  where+    f a b = PrimApp (PrimMin singleType) $ Pair a b++-- union :: ShapeR sh -> OpenExp env aenv sh -> OpenExp env aenv sh -> OpenExp env aenv sh+-- union = mkShapeBinary f+--   where+--     f a b = PrimApp (PrimMax singleType) $ Pair a b++mkShapeBinary+    :: (forall env'. OpenExp env' aenv Int -> OpenExp env' aenv Int -> OpenExp env' aenv Int)+    -> ShapeR sh+    -> OpenExp env aenv sh+    -> OpenExp env aenv sh+    -> OpenExp env aenv sh+mkShapeBinary _ ShapeRz _ _ = Nil+mkShapeBinary f (ShapeRsnoc shR) (Pair as a) (Pair bs b) = mkShapeBinary f shR as bs `Pair` f a b+mkShapeBinary f shR (Let lhs bnd a) b = Let lhs bnd $ mkShapeBinary f shR a (weakenE (weakenWithLHS lhs) b)+mkShapeBinary f shR a (Let lhs bnd b) = Let lhs bnd $ mkShapeBinary f shR (weakenE (weakenWithLHS lhs) a) b+mkShapeBinary f shR a b@Pair{} -- `a` is not Pair+  | DeclareVars lhs k value <- declareVars $ shapeType shR+  = Let lhs a $ mkShapeBinary f shR (expVars $ value weakenId) (weakenE k b)+mkShapeBinary f shR a b -- `b` is not a Pair+  | DeclareVars lhs k value <- declareVars $ shapeType shR+  = Let lhs b $ mkShapeBinary f shR (weakenE k a) (expVars $ value weakenId)++reindex :: ShapeR sh'+        -> OpenExp env aenv sh'+        -> ShapeR sh+        -> OpenExp env aenv sh+        -> OpenFun env aenv (sh -> sh')+reindex shR' sh' shR sh+  | Just Refl <- matchOpenExp sh sh' = identity (shapeType shR')+  | otherwise                        = fromIndex shR' sh' `compose` toIndex shR sh++extend :: SliceIndex slix sl co sh+       -> Exp aenv slix+       -> Fun aenv (sh -> sl)+extend sliceIndex slix+  | DeclareVars lhs k value <- declareVars $ shapeType $ sliceDomainR sliceIndex+  = Lam lhs $ Body $ IndexSlice sliceIndex (weakenE k slix) $ expVars $ value weakenId++restrict :: SliceIndex slix sl co sh+         -> Exp aenv slix+         -> Fun aenv (sl -> sh)+restrict sliceIndex slix+  | DeclareVars lhs k value <- declareVars $ shapeType $ sliceShapeR sliceIndex+  = Lam lhs $ Body $ IndexFull sliceIndex (weakenE k slix) $ expVars $ value weakenId++arrayShape :: ArrayVar aenv (Array sh e) -> Exp aenv sh+arrayShape = simplifyExp . Shape++indexArray :: ArrayVar aenv (Array sh e) -> Fun aenv (sh -> e)+indexArray v@(Var (ArrayR shR _) _)+  | DeclareVars lhs _ value <- declareVars $ shapeType shR+  = Lam lhs $ Body $ Index v $ expVars $ value weakenId++linearIndex :: ArrayVar aenv (Array sh e) -> Fun aenv (Int -> e)+linearIndex v = Lam (LeftHandSideSingle scalarTypeInt) $ Body $ LinearIndex v $ Evar $ Var scalarTypeInt ZeroIdx+++extractOpenAcc :: ExtractAcc OpenAcc+extractOpenAcc (OpenAcc pacc) = Just pacc++extractDelayedOpenAcc :: ExtractAcc DelayedOpenAcc+extractDelayedOpenAcc (Manifest pacc) = Just pacc+extractDelayedOpenAcc _               = Nothing++extractOpenArrayVars+    :: OpenAcc aenv a+    -> Maybe (ArrayVars aenv a)+extractOpenArrayVars (OpenAcc pacc) =+  avarsOut extractOpenAcc pacc++extractDelayedArrayVars+    :: DelayedOpenAcc aenv a+    -> Maybe (ArrayVars aenv a)+extractDelayedArrayVars acc+  | Just pacc <- extractDelayedOpenAcc acc = avarsOut extractDelayedOpenAcc pacc+  | otherwise                              = Nothing 
+ src/Data/Array/Accelerate/Trafo/LetSplit.hs view
@@ -0,0 +1,75 @@+{-# LANGUAGE LambdaCase #-}+{-# LANGUAGE GADTs      #-}+-- |+-- Module      : Data.Array.Accelerate.Trafo.LetSplit+-- Copyright   : [2012..2020] The Accelerate Team+-- License     : BSD3+--+-- Maintainer  : Trevor L. McDonell <trevor.mcdonell@gmail.com>+-- Stability   : experimental+-- Portability : non-portable (GHC extensions)+--++module Data.Array.Accelerate.Trafo.LetSplit (++  convertAfun,+  convertAcc,++) where++import Prelude                                          hiding ( exp )+import Data.Array.Accelerate.AST+import Data.Array.Accelerate.AST.LeftHandSide+import Data.Array.Accelerate.AST.Environment+import Data.Array.Accelerate.Trafo.Substitution+++convertAfun :: PreOpenAfun OpenAcc aenv f -> PreOpenAfun OpenAcc aenv f+convertAfun (Alam lhs f) = Alam lhs (convertAfun f)+convertAfun (Abody a)    = Abody (convertAcc a)++convertAcc :: OpenAcc aenv a -> OpenAcc aenv a+convertAcc (OpenAcc pacc) = OpenAcc (convertPreOpenAcc pacc)++convertPreOpenAcc :: PreOpenAcc OpenAcc aenv a -> PreOpenAcc OpenAcc aenv a+convertPreOpenAcc = \case+  Alet lhs bnd body               -> convertLHS lhs (convertAcc bnd) (convertAcc body)+  Avar var                        -> Avar var+  Apair a1 a2                     -> Apair (convertAcc a1) (convertAcc a2)+  Anil                            -> Anil+  Apply repr f a                  -> Apply repr (convertAfun f) (convertAcc a)+  Aforeign repr asm f a           -> Aforeign repr asm (convertAfun f) (convertAcc a)+  Acond e a1 a2                   -> Acond e (convertAcc a1) (convertAcc a2)+  Awhile c f a                    -> Awhile (convertAfun c) (convertAfun f) (convertAcc a)+  Use repr arr                    -> Use repr arr+  Unit tp e                       -> Unit tp e+  Reshape shr e a                 -> Reshape shr e a+  Generate repr e f               -> Generate repr e f+  Transform repr sh f g a         -> Transform repr sh f g (convertAcc a)+  Replicate slix sl a             -> Replicate slix sl (convertAcc a)+  Slice slix a sl                 -> Slice slix (convertAcc a) sl+  Map tp f a                      -> Map tp f (convertAcc a)+  ZipWith tp f a1 a2              -> ZipWith tp f (convertAcc a1) (convertAcc a2)+  Fold f e a                      -> Fold f e (convertAcc a)+  FoldSeg i f e a s               -> FoldSeg i f e (convertAcc a) (convertAcc s)+  Scan d f e a                    -> Scan d f e (convertAcc a)+  Scan' d f e a                   -> Scan' d f e (convertAcc a)+  Permute f a1 g a2               -> Permute f (convertAcc a1) g (convertAcc a2)+  Backpermute shr sh f a          -> Backpermute shr sh f (convertAcc a)+  Stencil s tp f b a              -> Stencil s tp f b (convertAcc a)+  Stencil2 s1 s2 tp f b1 a1 b2 a2 -> Stencil2 s1 s2 tp f b1 (convertAcc a1) b2 (convertAcc a2)++convertLHS+    :: ALeftHandSide bnd aenv aenv'+    -> OpenAcc aenv bnd+    -> OpenAcc aenv' a+    -> PreOpenAcc OpenAcc aenv a+convertLHS lhs bnd@(OpenAcc pbnd) a@(OpenAcc pa) =+  case lhs of+    LeftHandSideWildcard{} -> pa+    LeftHandSideSingle{}   -> Alet lhs bnd a+    LeftHandSidePair l1 l2 ->+      case pbnd of+        Apair b1 b2 -> convertLHS l1 b1 (OpenAcc (convertLHS l2 (weaken (weakenWithLHS l1) b2) a))+        _           -> Alet lhs bnd a+
− src/Data/Array/Accelerate/Trafo/Rewrite.hs
@@ -1,152 +0,0 @@-{-# LANGUAGE GADTs               #-}-{-# LANGUAGE ScopedTypeVariables #-}--- |--- Module      : Data.Array.Accelerate.Trafo.Rewrite--- 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.Trafo.Rewrite-  where--import Prelude                                          hiding ( seq )---- friends-import Data.Array.Accelerate.AST-import Data.Array.Accelerate.Type-import Data.Array.Accelerate.Trafo.Substitution-import Data.Array.Accelerate.Array.Sugar                ( Arrays, Segments, Elt, fromElt, Tuple(..), Atuple(..) )----- Convert segment length arrays passed to segmented operations into offset--- index style. This is achieved by wrapping the segmented array argument in a--- left prefix-sum, so you must only ever apply this once.----convertSegments :: OpenAcc aenv a -> OpenAcc aenv a-convertSegments = cvtA-  where-    cvtT :: Atuple (OpenAcc aenv) t -> Atuple (OpenAcc aenv) t-    cvtT atup = case atup of-      NilAtup      -> NilAtup-      SnocAtup t a -> cvtT t `SnocAtup` cvtA a--    cvtAfun :: OpenAfun aenv t -> OpenAfun aenv t-    cvtAfun = convertSegmentsAfun--    cvtE :: Exp aenv t -> Exp aenv t-    cvtE = id--    cvtF :: Fun aenv t -> Fun aenv t-    cvtF = id--    a0 :: Arrays a => OpenAcc (aenv, a) a-    a0 = OpenAcc (Avar ZeroIdx)--    segments :: (Elt i, IsIntegral i) => OpenAcc aenv (Segments i) -> OpenAcc aenv (Segments i)-    segments s = OpenAcc $ Scanl plus zero (cvtA s)--    zero :: forall aenv i. (Elt i, IsIntegral i) => PreOpenExp OpenAcc () aenv i-    zero = Const (fromElt (0::i))--    plus :: (Elt i, IsIntegral i) => PreOpenFun OpenAcc () aenv (i -> i -> i)-    plus = Lam (Lam (Body (PrimAdd numType-                          `PrimApp`-                          Tuple (NilTup `SnocTup` Var (SuccIdx ZeroIdx)-                                        `SnocTup` Var ZeroIdx))))--    cvtA :: OpenAcc aenv a -> OpenAcc aenv a-    cvtA (OpenAcc pacc) = OpenAcc $ case pacc of-      Alet bnd body             -> Alet (cvtA bnd) (cvtA body)-      Avar ix                   -> Avar ix-      Atuple tup                -> Atuple (cvtT tup)-      Aprj tup a                -> Aprj tup (cvtA a)-      Apply f a                 -> Apply (cvtAfun f) (cvtA a)-      Aforeign ff afun acc      -> Aforeign ff (cvtAfun afun) (cvtA acc)-      Acond p t e               -> Acond (cvtE p) (cvtA t) (cvtA e)-      Awhile p f a              -> Awhile (cvtAfun p) (cvtAfun f) (cvtA a)-      Use a                     -> Use a-      Unit e                    -> Unit (cvtE e)-      Reshape e a               -> Reshape (cvtE e) (cvtA a)-      Generate e f              -> Generate (cvtE e) (cvtF f)-      Transform sh ix f a       -> Transform (cvtE sh) (cvtF ix) (cvtF f) (cvtA a)-      Replicate sl slix a       -> Replicate sl (cvtE slix) (cvtA a)-      Slice sl a slix           -> Slice sl (cvtA a) (cvtE slix)-      Map f a                   -> Map (cvtF f) (cvtA a)-      ZipWith f a1 a2           -> ZipWith (cvtF f) (cvtA a1) (cvtA a2)-      Fold f z a                -> Fold (cvtF f) (cvtE z) (cvtA a)-      Fold1 f a                 -> Fold1 (cvtF f) (cvtA a)-      Scanl f z a               -> Scanl (cvtF f) (cvtE z) (cvtA a)-      Scanl' f z a              -> Scanl' (cvtF f) (cvtE z) (cvtA a)-      Scanl1 f a                -> Scanl1 (cvtF f) (cvtA a)-      Scanr f z a               -> Scanr (cvtF f) (cvtE z) (cvtA a)-      Scanr' f z a              -> Scanr' (cvtF f) (cvtE z) (cvtA a)-      Scanr1 f a                -> Scanr1 (cvtF f) (cvtA a)-      Permute f1 a1 f2 a2       -> Permute (cvtF f1) (cvtA a1) (cvtF f2) (cvtA a2)-      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' = 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' = 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)--{---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---}-
src/Data/Array/Accelerate/Trafo/Sharing.hs view
@@ -1,2936 +1,3108 @@-{-# LANGUAGE BangPatterns         #-}-{-# LANGUAGE DeriveDataTypeable   #-}-{-# LANGUAGE FlexibleInstances    #-}-{-# LANGUAGE GADTs                #-}-{-# LANGUAGE LambdaCase           #-}-{-# 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..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>--- Stability   : experimental--- Portability : non-portable (GHC extensions)------ This module implements HOAS to de Bruijn conversion of array expressions--- while incorporating sharing information.-----module Data.Array.Accelerate.Trafo.Sharing (--  -- * HOAS -> de Bruijn conversion-  convertAcc, convertAfun, Afunction, AfunctionR,-  convertExp, convertFun,  Function,  FunctionR,-  -- convertSeq--) where---- standard library-import Control.Applicative                              hiding ( Const )-import Control.Monad.Fix-import Data.List-import Data.Maybe-import Data.Hashable-import Data.Typeable-import System.Mem.StableName-import System.IO.Unsafe                                 ( unsafePerformIO )-import Text.Printf-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 Prelude---- friends-import Data.Array.Accelerate.Error-import Data.Array.Accelerate.Smart-import Data.Array.Accelerate.Array.Sugar                as Sugar hiding ( (!!) )-import Data.Array.Accelerate.AST                        hiding ( PreOpenAcc(..), OpenAcc(..), Acc-                                                               , PreOpenExp(..), OpenExp, PreExp, Exp-                                                               , PreBoundary(..), Boundary, Stencil(..)-                                                               , showPreAccOp, showPreExpOp )-import qualified Data.Array.Accelerate.AST              as AST-import qualified Data.Array.Accelerate.Debug            as Debug----- Configuration--- ----------------- Perhaps the configuration should be passed as a reader monad or some such,--- but that's a little inconvenient.----data Config = Config-  {-    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--- ----------- A layout of an environment has an entry for each entry of the environment.--- Each entry in the layout holds the de Bruijn index that refers to the--- corresponding entry in the environment.----data Layout env env' where-  EmptyLayout :: Layout env ()-  PushLayout  :: Typeable t-              => Layout env env' -> Idx env t -> Layout env (env', t)---- Project the nth index out of an environment layout.------ The first argument provides context information for error messages in the--- case of failure.----prjIdx :: Typeable t-       => String-       -> Int-       -> Layout env env'-       -> Idx env t-prjIdx context = go-  where-    go :: forall env env' t. Typeable t => Int -> Layout env env' -> Idx env t-    go _ EmptyLayout                        = no "environment does not contain index"-    go 0 (PushLayout _ (ix :: Idx env0 s))-      | Just ix' <- gcast ix                = ix'-      | otherwise                           = no $ printf "couldn't match expected type `%s' with actual type `%s'"-                                                          (show (typeOf (undefined::t)))-                                                          (show (typeOf (undefined::s)))-    go n (PushLayout l _)                   = go (n-1) l--    no :: String -> a-    no reason = $internalError "prjIdx" (printf "%s\nin the context: %s" reason context)----- Add an entry to a layout, incrementing all indices----incLayout :: Layout env env' -> Layout (env, t) env'-incLayout EmptyLayout         = EmptyLayout-incLayout (PushLayout lyt ix) = PushLayout (incLayout lyt) (SuccIdx ix)--sizeLayout :: Layout env env' -> Int-sizeLayout EmptyLayout        = 0-sizeLayout (PushLayout lyt _) = 1 + sizeLayout lyt----- Conversion from HOAS to de Bruijn computation AST--- =================================================---- Array computations--- ---------------------- | Convert a closed array expression to de Bruijn form while also incorporating sharing--- information.----convertAcc-    :: 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 shareSeq floatAcc acc-  = let config  = Config shareAcc shareExp shareSeq (shareAcc && floatAcc)-    in-    convertOpenAcc config 0 [] EmptyLayout acc----- | Convert a closed function over array computations, while incorporating--- sharing information.----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----- Convert a HOAS fragment into de Bruijn form, binding variables into the typed--- environment layout one binder at a time.------ NOTE: Because we convert one binder at a time left-to-right, the bound---       variables ('vars') will have de Bruijn index _zero_ as the outermost---       binding, and thus go to the end of the list.----class Afunction f where-  type AfunctionR f-  aconvert :: Config -> Layout aenv aenv -> f -> AST.OpenAfun aenv (AfunctionR f)--instance (Arrays a, Afunction r) => Afunction (Acc a -> r) where-  type AfunctionR (Acc a -> r) = a -> AfunctionR r-  ---  aconvert config alyt f-    = let a     = Acc $ Atag (sizeLayout alyt)-          alyt' = incLayout alyt `PushLayout` ZeroIdx-      in-      Alam $ aconvert config alyt' (f a)--instance Arrays b => Afunction (Acc b) where-  type AfunctionR (Acc b) = b-  ---  aconvert config alyt body-    = let lvl    = sizeLayout alyt-          vars   = [lvl-1, lvl-2 .. 0]-      in-      Abody $ convertOpenAcc config lvl vars alyt body----- | Convert an open array expression to de Bruijn form while also incorporating sharing--- information.----convertOpenAcc-    :: Arrays arrs-    => Config-    -> Level-    -> [Level]-    -> Layout aenv aenv-    -> Acc arrs-    -> AST.OpenAcc aenv arrs-convertOpenAcc config lvl fvs alyt acc-  = let (sharingAcc, initialEnv) = recoverSharingAcc config lvl fvs acc-    in-    convertSharingAcc config alyt initialEnv sharingAcc---- | Convert an array expression with given array environment layout and sharing information into--- de Bruijn form while recovering sharing at the same time (by introducing appropriate let--- bindings).  The latter implements the third phase of sharing recovery.------ The sharing environment 'env' keeps track of all currently bound sharing variables, keeping them--- in reverse chronological order (outermost variable is at the end of the list).----convertSharingAcc-    :: forall aenv arrs. Arrays arrs-    => Config-    -> Layout aenv aenv-    -> [StableSharingAcc]-    -> ScopedAcc arrs-    -> AST.OpenAcc aenv arrs-convertSharingAcc _ alyt aenv (ScopedAcc lams (AvarSharing sa))-  | Just i <- findIndex (matchStableAcc sa) aenv'-  = AST.OpenAcc $ AST.Avar (prjIdx (ctxt ++ "; i = " ++ show i) i alyt)-  | null aenv'-  = error $ "Cyclic definition of a value of type 'Acc' (sa = " ++-            show (hashStableNameHeight sa) ++ ")"-  | otherwise-  = $internalError "convertSharingAcc" err-  where-    aenv' = lams ++ aenv-    ctxt = "shared 'Acc' tree with stable name " ++ show (hashStableNameHeight sa)-    err  = "inconsistent valuation @ " ++ ctxt ++ ";\n  aenv = " ++ show aenv'--convertSharingAcc config alyt aenv (ScopedAcc lams (AletSharing sa@(StableSharingAcc _ boundAcc) bodyAcc))-  = AST.OpenAcc-  $ let alyt' = incLayout alyt `PushLayout` ZeroIdx-        aenv' = lams ++ aenv-    in-    AST.Alet (convertSharingAcc config alyt aenv' (ScopedAcc [] boundAcc))-             (convertSharingAcc config alyt' (sa:aenv') bodyAcc)--convertSharingAcc config alyt aenv (ScopedAcc lams (AccSharing _ preAcc))-  = AST.OpenAcc-  $ let aenv' = lams ++ aenv--        cvtA :: Arrays a => ScopedAcc a -> AST.OpenAcc aenv a-        cvtA = convertSharingAcc config alyt aenv'--        cvtE :: Elt t => ScopedExp t -> AST.Exp aenv t-        cvtE = convertSharingExp config EmptyLayout alyt [] aenv'--        cvtF1 :: (Elt a, Elt b) => (Exp a -> ScopedExp b) -> AST.Fun aenv (a -> b)-        cvtF1 = convertSharingFun1 config 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'--        cvtAfun1 :: (Arrays a, Arrays b) => (Acc a -> ScopedAcc b) -> AST.OpenAfun aenv (a -> b)-        cvtAfun1 = convertSharingAfun1 config alyt aenv'-    in-    case preAcc of--      Atag i-        -> AST.Avar (prjIdx ("de Bruijn conversion tag " ++ show i) i alyt)--      Pipe afun1 afun2 acc-        -> let noStableSharing = StableSharingAcc noStableAccName (undefined :: SharingAcc acc exp ())-               alyt'    = incLayout alyt `PushLayout` ZeroIdx-               boundAcc = cvtAfun1 afun1 `AST.Apply` cvtA acc-               bodyAcc  = convertSharingAfun1 config alyt' (noStableSharing : aenv') afun2-                          `AST.Apply`-                          AST.OpenAcc (AST.Avar AST.ZeroIdx)-           in-           AST.Alet (AST.OpenAcc boundAcc) (AST.OpenAcc bodyAcc)--      Aforeign ff afun acc-        -> let a = recoverAccSharing config-               e = recoverExpSharing config-               s = recoverSeqSharing config-               f = floatOutAcc config-           in-           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)-      Atuple arrs                 -> AST.Atuple (convertSharingAtuple config alyt aenv' arrs)-      Aprj ix a                   -> AST.Aprj ix (cvtA a)-      Use array                   -> AST.Use (fromArr array)-      Unit e                      -> AST.Unit (cvtE e)-      Generate sh f               -> AST.Generate (cvtE sh) (cvtF1 f)-      Reshape e acc               -> AST.Reshape (cvtE e) (cvtA acc)-      Replicate ix acc            -> mkReplicate (cvtE ix) (cvtA acc)-      Slice acc ix                -> mkIndex (cvtA acc) (cvtE ix)-      Map f acc                   -> AST.Map (cvtF1 f) (cvtA acc)-      ZipWith f acc1 acc2         -> AST.ZipWith (cvtF2 f) (cvtA acc1) (cvtA acc2)-      Fold f e acc                -> AST.Fold (cvtF2 f) (cvtE e) (cvtA acc)-      Fold1 f acc                 -> AST.Fold1 (cvtF2 f) (cvtA acc)-      FoldSeg f e acc1 acc2       -> AST.FoldSeg (cvtF2 f) (cvtE e) (cvtA acc1) (cvtA acc2)-      Fold1Seg f acc1 acc2        -> AST.Fold1Seg (cvtF2 f) (cvtA acc1) (cvtA acc2)-      Scanl f e acc               -> AST.Scanl (cvtF2 f) (cvtE e) (cvtA acc)-      Scanl' f e acc              -> AST.Scanl' (cvtF2 f) (cvtE e) (cvtA acc)-      Scanl1 f acc                -> AST.Scanl1 (cvtF2 f) (cvtA acc)-      Scanr f e acc               -> AST.Scanr (cvtF2 f) (cvtE e) (cvtA acc)-      Scanr' f e acc              -> AST.Scanr' (cvtF2 f) (cvtE e) (cvtA acc)-      Scanr1 f acc                -> AST.Scanr1 (cvtF2 f) (cvtA acc)-      Permute f dftAcc perm acc   -> AST.Permute (cvtF2 f) (cvtA dftAcc) (cvtF1 perm) (cvtA acc)-      Backpermute newDim perm acc -> AST.Backpermute (cvtE newDim) (cvtF1 perm) (cvtA acc)-      Stencil stencil boundary acc-        -> AST.Stencil (convertSharingStencilFun1 config acc alyt aenv' stencil)-                       (convertSharingBoundary config alyt aenv' boundary)-                       (cvtA acc)-      Stencil2 stencil bndy1 acc1 bndy2 acc2-        -> AST.Stencil2 (convertSharingStencilFun2 config acc1 acc2 alyt aenv' stencil)-                        (convertSharingBoundary config alyt aenv' bndy1)-                        (cvtA acc1)-                        (convertSharingBoundary config alyt aenv' 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-    -> Layout aenv aenv-    -> [StableSharingAcc]-    -> (Acc a -> ScopedAcc b)-    -> OpenAfun aenv (a -> b)-convertSharingAfun1 config alyt aenv f-  = Alam (Abody (convertSharingAcc config alyt' aenv body))-      where-        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]-    -> Atuple ScopedAcc a-    -> Atuple (AST.OpenAcc aenv) a-convertSharingAtuple config alyt aenv = cvt-  where-    cvt :: Atuple ScopedAcc a' -> Atuple (AST.OpenAcc aenv) a'-    cvt NilAtup         = NilAtup-    cvt (SnocAtup t a)  = cvt t `SnocAtup` convertSharingAcc config alyt aenv a----- | Convert a boundary condition----convertSharingBoundary-    :: forall aenv t.-       Config-    -> Layout aenv aenv-    -> [StableSharingAcc]-    -> PreBoundary ScopedAcc ScopedExp t-    -> AST.PreBoundary AST.OpenAcc aenv t-convertSharingBoundary config alyt aenv = cvt-  where-    cvt :: PreBoundary ScopedAcc ScopedExp t -> AST.Boundary aenv t-    cvt bndy =-      case bndy of-        Clamp       -> AST.Clamp-        Mirror      -> AST.Mirror-        Wrap        -> AST.Wrap-        Constant v  -> AST.Constant $ fromElt v-        Function f  -> AST.Function $ convertSharingFun1 config alyt aenv f----- Smart constructors to represent AST forms----mkIndex :: forall slix e aenv. (Slice slix, Elt e)-        => AST.OpenAcc                aenv (Array (FullShape  slix) e)-        -> AST.Exp                    aenv slix-        -> AST.PreOpenAcc AST.OpenAcc aenv (Array (SliceShape slix) e)-mkIndex = AST.Slice (sliceIndex slix)-  where-    slix = undefined :: slix--mkReplicate :: forall slix e aenv. (Slice slix, Elt e)-        => AST.Exp                    aenv slix-        -> AST.OpenAcc                aenv (Array (SliceShape slix) e)-        -> AST.PreOpenAcc AST.OpenAcc aenv (Array (FullShape  slix) e)-mkReplicate = AST.Replicate (sliceIndex slix)-  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--- -------------------- | Convert a closed scalar function to de Bruijn form while incorporating--- sharing information.------ The current design requires all free variables to be bound at the outermost--- level --- we have no general apply term, and so lambdas are always outermost.--- In higher-order abstract syntax, this represents an n-ary, polyvariadic--- function.----convertFun :: Function f => Bool -> f -> AST.Fun () (FunctionR f)-convertFun shareExp =-  let config = Config False shareExp False False-  in  convert config EmptyLayout---class Function f where-  type FunctionR f-  convert :: Config -> Layout env env -> f -> AST.OpenFun env () (FunctionR f)--instance (Elt a, Function r) => Function (Exp a -> r) where-  type FunctionR (Exp a -> r) = a -> FunctionR r-  ---  convert config lyt f-    = let x     = Exp $ Tag (sizeLayout lyt)-          lyt'  = incLayout lyt `PushLayout` ZeroIdx-      in-      Lam $ convert config lyt' (f x)--instance Elt b => Function (Exp b) where-  type FunctionR (Exp b) = b-  ---  convert config lyt body-    = let lvl    = sizeLayout lyt-          vars   = [lvl-1, lvl-2 .. 0]-      in-      Body $ convertOpenExp config lvl vars lyt body----- Scalar expressions--- ---------------------- | Convert a closed scalar expression to de Bruijn form while incorporating--- sharing information.----convertExp-    :: Elt e-    => Bool             -- ^ recover sharing of scalar expressions ?-    -> Exp e            -- ^ expression to be converted-    -> AST.Exp () e-convertExp shareExp exp-  = let config = Config False shareExp False False-    in-    convertOpenExp config 0 [] EmptyLayout exp--convertOpenExp-    :: Elt e-    => Config-    -> Level            -- level of currently bound scalar variables-    -> [Level]          -- tags of bound scalar variables-    -> Layout env env-    -> Exp e-    -> AST.OpenExp env () e-convertOpenExp config lvl fvar lyt exp-  = let (sharingExp, initialEnv) = recoverSharingExp config lvl fvar exp-    in-    convertSharingExp config lyt EmptyLayout initialEnv [] sharingExp----- | Convert an open expression with given environment layouts and sharing information into--- de Bruijn form while recovering sharing at the same time (by introducing appropriate let--- bindings).  The latter implements the third phase of sharing recovery.------ The sharing environments 'env' and 'aenv' keep track of all currently bound sharing variables,--- keeping them in reverse chronological order (outermost variable is at the end of the list).----convertSharingExp-    :: forall t env aenv. Elt t-    => Config-    -> Layout env  env          -- scalar environment-    -> Layout aenv aenv         -- array environment-    -> [StableSharingExp]       -- currently bound sharing variables of expressions-    -> [StableSharingAcc]       -- currently bound sharing variables of array computations-    -> ScopedExp t              -- expression to be converted-    -> AST.OpenExp env aenv t-convertSharingExp config lyt alyt env aenv exp@(ScopedExp lams _) = cvt exp-  where-    -- scalar environment with any lambda bound variables this expression is rooted in-    env' = lams ++ env--    cvt :: Elt t' => ScopedExp t' -> AST.OpenExp env aenv t'-    cvt (ScopedExp _ (VarSharing se))-      | Just i <- findIndex (matchStableExp se) env' = AST.Var (prjIdx (ctx i) i lyt)-      | otherwise                                    = $internalError "convertSharingExp" msg-      where-        ctx i = printf "shared 'Exp' tree with stable name %d; i=%d" (hashStableNameHeight se) i-        msg   = unlines-          [ if null env'-               then printf "cyclic definition of a value of type 'Exp' (sa=%d)" (hashStableNameHeight se)-               else printf "inconsistent valuation at shared 'Exp' tree (sa=%d; env=%s)" (hashStableNameHeight se) (show env')-          , ""-          , "Note that this error usually arises due to the presence of nested data"-          , "parallelism; when a parallel computation attempts to initiate new parallel"-          , "work _which depends on_ a scalar variable given by the first computation."-          , ""-          , "For example, suppose we wish to sum the columns of a two-dimensional array."-          , "You might think to do this in the following (incorrect) way: by constructing"-          , "a vector using 'generate' where at each index we 'slice' out the"-          , "corresponding column of the matrix and 'sum' it:"-          , ""-          , "> sum_columns_ndp :: Num a => Acc (Matrix a) -> Acc (Vector a)"-          , "> sum_columns_ndp mat ="-          , ">   let Z :. rows :. cols = unlift (shape mat) :: Z :. Exp Int :. Exp Int"-          , ">   in  generate (index1 cols)"-          , ">                (\\col -> the $ sum (slice mat (lift (Z :. All :. unindex1 col))))"-          , ""-          , "However, since both 'generate' and 'slice' are data-parallel operators, and"-          , "moreover that 'slice' _depends on_ the argument 'col' given to it by the"-          , "'generate' function, this operation requires nested parallelism and is thus"-          , "not (at this time) permitted. The clue that this definition is invalid is"-          , "that in order to create a program which will be accepted by the type checker,"-          , "we had to use the function 'the' to retrieve the result of the parallel"-          , "'sum', effectively concealing that this is a collective operation in order to"-          , "match the type expected by 'generate'."-          , ""-          , "To solve this particular example, we can make use of the fact that (most)"-          , "collective operations in Accelerate are _rank polymorphic_. The 'sum'"-          , "operation reduces along the innermost dimension of an array of arbitrary"-          , "rank, reducing the dimensionality of the array by one. To reduce the array"-          , "column-wise then, we first need to simply 'transpose' the array:"-          , ""-          , "> sum_columns :: Num a => Acc (Matrix a) -> Acc (Vector a)"-          , "> sum_columns = sum . transpose"-          , ""-          , "If you feel like this is not the cause of your error, or you would like some"-          , "advice locating the problem and perhaps with a workaround, feel free to"-          , "submit an issue at the above URL."-          ]--    cvt (ScopedExp _ (LetSharing se@(StableSharingExp _ boundExp) bodyExp))-      = let lyt' = incLayout lyt `PushLayout` ZeroIdx-        in-        AST.Let (cvt (ScopedExp [] boundExp)) (convertSharingExp config lyt' alyt (se:env') aenv bodyExp)-    cvt (ScopedExp _ (ExpSharing _ pexp))-      = case pexp of-          Tag i                 -> AST.Var (prjIdx ("de Bruijn conversion tag " ++ show i) i lyt)-          Const v               -> AST.Const (fromElt v)-          Undef                 -> AST.Undef-          Tuple tup             -> AST.Tuple (cvtT tup)-          Prj idx e             -> AST.Prj idx (cvt e)-          IndexNil              -> AST.IndexNil-          IndexCons ix i        -> AST.IndexCons (cvt ix) (cvt i)-          IndexHead i           -> AST.IndexHead (cvt i)-          IndexTail ix          -> AST.IndexTail (cvt ix)-          IndexAny              -> AST.IndexAny-          ToIndex sh ix         -> AST.ToIndex (cvt sh) (cvt ix)-          FromIndex sh e        -> AST.FromIndex (cvt sh) (cvt e)-          Cond e1 e2 e3         -> AST.Cond (cvt e1) (cvt e2) (cvt e3)-          While p it i          -> AST.While (cvtFun1 p) (cvtFun1 it) (cvt i)-          PrimConst c           -> AST.PrimConst c-          PrimApp f e           -> cvtPrimFun f (cvt e)-          Index a e             -> AST.Index (cvtA a) (cvt e)-          LinearIndex a i       -> AST.LinearIndex (cvtA a) (cvt i)-          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)-          Coerce e              -> AST.Coerce (cvt e)--    cvtA :: Arrays a => ScopedAcc a -> AST.OpenAcc aenv a-    cvtA = convertSharingAcc config alyt aenv--    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)-    cvtFun1 f = Lam (Body (convertSharingExp config lyt' alyt env' aenv body))-      where-        lyt' = incLayout lyt `PushLayout` ZeroIdx-        body = f undefined--    -- Push primitive function applications down through let bindings so that-    -- they are adjacent to their arguments. It looks a bit nicer this way.-    ---    cvtPrimFun :: (Elt a, Elt r)-               => AST.PrimFun (a -> r) -> AST.OpenExp env' aenv' a -> AST.OpenExp env' aenv' r-    cvtPrimFun f e = case e of-      AST.Let bnd body    -> AST.Let bnd (cvtPrimFun f body)-      x                   -> AST.PrimApp f x---- | Convert a tuple expression----convertSharingTuple-    :: Config-    -> Layout env env-    -> Layout aenv aenv-    -> [StableSharingExp]                 -- currently bound scalar sharing-variables-    -> [StableSharingAcc]                 -- currently bound array sharing-variables-    -> Tuple ScopedExp t-    -> Tuple (AST.OpenExp env aenv) t-convertSharingTuple config lyt alyt env aenv tup =-  case tup of-    NilTup      -> NilTup-    SnocTup t e -> convertSharingTuple config lyt alyt env aenv t-         `SnocTup` convertSharingExp   config lyt alyt env aenv e---- | Convert a unary functions----convertSharingFun1-    :: forall a b aenv. (Elt a, Elt b)-    => Config-    -> Layout aenv aenv-    -> [StableSharingAcc]       -- currently bound array sharing-variables-    -> (Exp a -> ScopedExp b)-    -> AST.Fun aenv (a -> b)-convertSharingFun1 config alyt aenv f = Lam (Body openF)-  where-    a               = Exp undefined             -- the 'tag' was already embedded in Phase 1-    lyt             = EmptyLayout-                      `PushLayout`-                      (ZeroIdx :: Idx ((), a) a)-    openF           = convertSharingExp config lyt alyt [] aenv (f a)---- | Convert a binary functions----convertSharingFun2-    :: forall a b c aenv. (Elt a, Elt b, Elt c)-    => Config-    -> Layout aenv aenv-    -> [StableSharingAcc]       -- currently bound array sharing-variables-    -> (Exp a -> Exp b -> ScopedExp c)-    -> AST.Fun aenv (a -> b -> c)-convertSharingFun2 config alyt aenv f = Lam (Lam (Body openF))-  where-    a               = Exp undefined-    b               = Exp undefined-    lyt             = EmptyLayout-                      `PushLayout`-                      (SuccIdx ZeroIdx :: Idx (((), a), b) a)-                      `PushLayout`-                      (ZeroIdx         :: Idx (((), a), b) b)-    openF           = convertSharingExp config lyt alyt [] aenv (f a b)---- | Convert a unary stencil function----convertSharingStencilFun1-    :: forall sh a stencil b aenv. (Elt a, Stencil sh a stencil, Elt b)-    => Config-    -> ScopedAcc (Array sh a)          -- just passed to fix the type variables-    -> Layout aenv aenv-    -> [StableSharingAcc]               -- currently bound array sharing-variables-    -> (stencil -> ScopedExp b)-    -> AST.Fun aenv (StencilRepr sh stencil -> b)-convertSharingStencilFun1 config _ alyt aenv stencilFun = Lam (Body openStencilFun)-  where-    stencil = Exp undefined :: Exp (StencilRepr sh stencil)-    lyt     = EmptyLayout-              `PushLayout`-              (ZeroIdx :: Idx ((), StencilRepr sh stencil)-                              (StencilRepr sh stencil))--    body = stencilFun (stencilPrj (undefined::sh) (undefined::a) stencil)-    openStencilFun  = convertSharingExp config lyt alyt [] aenv body---- | Convert a binary stencil function----convertSharingStencilFun2-    :: forall sh a b stencil1 stencil2 c aenv.-       (Elt a, Stencil sh a stencil1,-        Elt b, Stencil sh b stencil2,-        Elt c)-    => Config-    -> ScopedAcc (Array sh a)          -- just passed to fix the type variables-    -> ScopedAcc (Array sh b)          -- just passed to fix the type variables-    -> Layout aenv aenv-    -> [StableSharingAcc]               -- currently bound array sharing-variables-    -> (stencil1 -> stencil2 -> ScopedExp c)-    -> AST.Fun aenv (StencilRepr sh stencil1 -> StencilRepr sh stencil2 -> c)-convertSharingStencilFun2 config _ _ alyt aenv stencilFun = Lam (Lam (Body openStencilFun))-  where-    stencil1 = Exp undefined :: Exp (StencilRepr sh stencil1)-    stencil2 = Exp undefined :: Exp (StencilRepr sh stencil2)-    lyt     = EmptyLayout-              `PushLayout`-              (SuccIdx ZeroIdx :: Idx (((), StencilRepr sh stencil1),-                                            StencilRepr sh stencil2)-                                       (StencilRepr sh stencil1))-              `PushLayout`-              (ZeroIdx         :: Idx (((), StencilRepr sh stencil1),-                                            StencilRepr sh stencil2)-                                       (StencilRepr sh stencil2))--    body = stencilFun (stencilPrj (undefined::sh) (undefined::a) stencil1)-                      (stencilPrj (undefined::sh) (undefined::b) stencil2)-    openStencilFun  = convertSharingExp config lyt alyt [] aenv body----- Sharing recovery--- ================---- Sharing recovery proceeds in two phases:------ /Phase One: build the occurrence map/------ This is a top-down traversal of the AST that computes a map from AST nodes to the number of--- occurrences of that AST node in the overall Accelerate program.  An occurrences count of two or--- more indicates sharing.------ IMPORTANT: To avoid unfolding the sharing, we do not descent into subtrees that we have---   previously encountered.  Hence, the complexity is proportional to the number of nodes in the---   tree /with/ sharing.  Consequently, the occurrence count is that in the tree with sharing---   as well.------ During computation of the occurrences, the tree is annotated with stable names on every node--- using 'AccSharing' constructors and all but the first occurrence of shared subtrees are pruned--- using 'AvarSharing' constructors (see 'SharingAcc' below).  This phase is impure as it is based--- on stable names.------ We use a hash table (instead of 'Data.Map') as computing stable names forces us to live in IO--- anyway.  Once, the computation of occurrence counts is complete, we freeze the hash table into--- a 'Data.Map'.------ (Implemented by 'makeOccMap*'.)------ /Phase Two: determine scopes and inject sharing information/------ This is a bottom-up traversal that determines the scope for every binding to be introduced--- to share a subterm.  It uses the occurrence map to determine, for every shared subtree, the--- lowest AST node at which the binding for that shared subtree can be placed (using a--- 'AletSharing' constructor)— it's the meet of all the shared subtree occurrences.------ The second phase is also replacing the first occurrence of each shared subtree with a--- 'AvarSharing' node and floats the shared subtree up to its binding point.------  (Implemented by 'determineScopes*'.)------ /Sharing recovery for expressions/------ We recover sharing for each expression (including function bodies) independently of any other--- expression — i.e., we cannot share scalar expressions across array computations.  Hence, during--- Phase One, we mark all scalar expression nodes with a stable name and compute one occurrence map--- for every scalar expression (including functions) that occurs in an array computation.  These--- occurrence maps are added to the root of scalar expressions using 'RootExp'.------ NB: We do not need to worry sharing recovery will try to float a shared subexpression past a---     binder that occurs in that subexpression.  Why?  Otherwise, the binder would already occur---     out of scope in the original source program.------ /Lambda bound variables/------ During sharing recovery, lambda bound variables appear in the form of 'Atag' and 'Tag' data--- constructors.  The tag values are determined during Phase One of sharing recovery by computing--- the /level/ of each variable at its binding occurrence.  The level at the root of the AST is 0--- and increases by one with each lambda on each path through the AST.---- Stable names--- ---------------- Opaque stable name for AST nodes — used to key the occurrence map.----data StableASTName c where-  StableASTName :: (Typeable c, Typeable t) => StableName (c t) -> StableASTName c--instance Show (StableASTName c) where-  show (StableASTName sn) = show $ hashStableName sn--instance Eq (StableASTName c) where-  StableASTName sn1 == StableASTName sn2-    | Just sn1' <- gcast sn1 = sn1' == sn2-    | otherwise              = False--instance Hashable (StableASTName c) where-  hashWithSalt s (StableASTName sn) = hashWithSalt s sn--makeStableAST :: c t -> IO (StableName (c t))-makeStableAST e = e `seq` makeStableName e---- Stable name for an AST node including the height of the AST representing the array computation.----data StableNameHeight t = StableNameHeight (StableName t) Int--instance Eq (StableNameHeight t) where-  (StableNameHeight sn1 _) == (StableNameHeight sn2 _) = sn1 == sn2--higherSNH :: StableNameHeight t1 -> StableNameHeight t2 -> Bool-StableNameHeight _ h1 `higherSNH` StableNameHeight _ h2 = h1 > h2--hashStableNameHeight :: StableNameHeight t -> Int-hashStableNameHeight (StableNameHeight sn _) = hashStableName sn---- Mutable occurrence map--- -------------------------- Hash table keyed on the stable names of array computations.----type HashTable key val = Hash.BasicHashTable key val-type ASTHashTable c v  = HashTable (StableASTName c) v---- Mutable hashtable version of the occurrence map, which associates each AST node with an--- occurrence count and the height of the AST.----type OccMapHash c = ASTHashTable c (Int, Int)---- Create a new hash table keyed on AST nodes.----newASTHashTable :: IO (ASTHashTable c v)-newASTHashTable = Hash.new---- Enter one AST node occurrence into an occurrence map.  Returns 'Just h' if this is a repeated--- occurrence and the height of the repeatedly occurring AST is 'h'.------ If this is the first occurrence, the 'height' *argument* must provide the height of the AST;--- otherwise, the height will be *extracted* from the occurrence map.  In the latter case, this--- function yields the AST height.----enterOcc :: OccMapHash c -> StableASTName c -> Int -> IO (Maybe Int)-enterOcc occMap sa height-  = Hash.mutate occMap sa-  $ \case-      Nothing           -> (Just (1,   height),  Nothing)-      Just (n, heightS) -> (Just (n+1, heightS), Just heightS)----- Immutable occurrence map--- ---------------------------- Immutable version of the occurrence map (storing the occurrence count only, not the height).  We--- use the 'StableName' hash to index an 'IntMap' and disambiguate 'StableName's with identical--- hashes explicitly, storing them in a list in the 'IntMap'.----type OccMap c = IntMap.IntMap [(StableASTName c, Int)]---- Turn a mutable into an immutable occurrence map.----freezeOccMap :: OccMapHash c -> IO (OccMap c)-freezeOccMap oc-  = do-      ocl <- Hash.toList oc-      traceChunk "OccMap" (show ocl)--      return . IntMap.fromList-             . map (\kvs -> (key (head kvs), kvs))-             . groupBy sameKey-             . map dropHeight-             $ ocl-  where-    key (StableASTName sn, _) = hashStableName sn-    sameKey kv1 kv2           = key kv1 == key kv2-    dropHeight (k, (cnt, _))  = (k, cnt)---- Look up the occurrence map keyed by array computations using a stable name.  If the key does--- not exist in the map, return an occurrence count of '1'.----lookupWithASTName :: OccMap c -> StableASTName c -> Int-lookupWithASTName oc sa@(StableASTName sn)-  = fromMaybe 1 $ IntMap.lookup (hashStableName sn) oc >>= Prelude.lookup sa---- Look up the occurrence map keyed by array computations using a sharing array computation.  If an--- the key does not exist in the map, return an occurrence count of '1'.----lookupWithSharingAcc :: OccMap Acc -> StableSharingAcc -> Int-lookupWithSharingAcc oc (StableSharingAcc (StableNameHeight sn _) _)-  = lookupWithASTName oc (StableASTName sn)---- Look up the occurrence map keyed by scalar expressions using a sharing expression.  If an--- the key does not exist in the map, return an occurrence count of '1'.----lookupWithSharingExp :: OccMap Exp -> StableSharingExp -> Int-lookupWithSharingExp oc (StableSharingExp (StableNameHeight sn _) _)-  = lookupWithASTName oc (StableASTName sn)----- Stable 'Acc' nodes--- ---------------------- Stable name for 'Acc' nodes including the height of the AST.----type StableAccName arrs = StableNameHeight (Acc arrs)---- Interleave sharing annotations into an array computation AST.  Subtrees can be marked as being--- represented by variable (binding a shared subtree) using 'AvarSharing' and as being prefixed by--- a let binding (for a shared subtree) using 'AletSharing'.----data SharingAcc acc exp arrs where-  AvarSharing :: Arrays arrs-              => StableAccName arrs                        -> SharingAcc acc exp arrs-  AletSharing :: StableSharingAcc -> acc arrs              -> SharingAcc acc exp arrs-  AccSharing  :: Arrays arrs-              => StableAccName arrs -> PreAcc acc exp arrs -> SharingAcc acc 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 UnscopedAcc t = UnscopedAcc [Int] (SharingAcc UnscopedAcc 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 ScopedAcc t = ScopedAcc [StableSharingAcc] (SharingAcc ScopedAcc ScopedExp t)---- Stable name for an array computation associated with its sharing-annotated version.----data StableSharingAcc where-  StableSharingAcc :: Arrays arrs-                   => StableAccName arrs-                   -> SharingAcc ScopedAcc ScopedExp arrs-                   -> StableSharingAcc--instance Show StableSharingAcc where-  show (StableSharingAcc sn _) = show $ hashStableNameHeight sn--instance Eq StableSharingAcc where-  StableSharingAcc sn1 _ == StableSharingAcc sn2 _-    | Just sn1' <- gcast sn1 = sn1' == sn2-    | otherwise              = False--higherSSA :: StableSharingAcc -> StableSharingAcc -> Bool-StableSharingAcc sn1 _ `higherSSA` StableSharingAcc sn2 _ = sn1 `higherSNH` sn2---- Test whether the given stable names matches an array computation with sharing.----matchStableAcc :: Typeable arrs => StableAccName arrs -> StableSharingAcc -> Bool-matchStableAcc sn1 (StableSharingAcc sn2 _)-  | Just sn1' <- gcast sn1 = sn1' == sn2-  | otherwise              = False---- Dummy entry for environments to be used for unused variables.----noStableAccName :: StableAccName arrs-noStableAccName = unsafePerformIO $ StableNameHeight <$> makeStableName undefined <*> pure 0---- Stable 'Exp' nodes--- ---------------------- Stable name for 'Exp' nodes including the height of the AST.----type StableExpName t = StableNameHeight (Exp t)---- Interleave sharing annotations into a scalar expressions AST in the same manner as 'SharingAcc'--- do for array computations.----data SharingExp (acc :: * -> *) exp t where-  VarSharing :: Elt 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---- Specifies a scalar expression AST with sharing annotations but no scoping; i.e. no LetSharing--- constructors. If the expression is rooted in a function, the list contains the tags of the--- variables bound by the immediate surrounding lambdas.-data UnscopedExp t = UnscopedExp [Int] (SharingExp UnscopedAcc UnscopedExp t)---- Specifies a scalar expression AST with sharing. For expressions rooted in functions the list--- holds a sorted environment corresponding to the variables bound in the immediate surounding--- lambdas.-data ScopedExp t = ScopedExp [StableSharingExp] (SharingExp ScopedAcc ScopedExp t)---- Expressions rooted in 'Acc' computations.------ * When counting occurrences, the root of every expression 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 RootExp t = RootExp (OccMap Exp) (UnscopedExp t)---- Stable name for an expression associated with its sharing-annotated version.----data StableSharingExp where-  StableSharingExp :: Elt t => StableExpName t -> SharingExp ScopedAcc ScopedExp t -> StableSharingExp--instance Show StableSharingExp where-  show (StableSharingExp sn _) = show $ hashStableNameHeight sn--instance Eq StableSharingExp where-  StableSharingExp sn1 _ == StableSharingExp sn2 _-    | Just sn1' <- gcast sn1 = sn1' == sn2-    | otherwise              = False--higherSSE :: StableSharingExp -> StableSharingExp -> Bool-StableSharingExp sn1 _ `higherSSE` StableSharingExp sn2 _ = sn1 `higherSNH` sn2---- Test whether the given stable names matches an expression with sharing.----matchStableExp :: Typeable t => StableExpName t -> StableSharingExp -> Bool-matchStableExp sn1 (StableSharingExp sn2 _)-  | Just sn1' <- gcast sn1 = sn1' == sn2-  | otherwise              = False---- Dummy entry for environments to be used for unused variables.----noStableExpName :: StableExpName t-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 '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--- sub-expression rooted in an 'Acc' operation.  This is as we cannot float 'Exp' subtrees across--- 'Acc' operations, but we can float 'Acc' subtrees out of 'Exp' expressions.------ Note [Traversing functions and side effects]--- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~--- We need to descent into function bodies to build the 'OccMap' with all occurrences in the--- function bodies.  Due to the side effects in the construction of the occurrence map and, more--- importantly, the dependence of the second phase on /global/ occurrence information, we may not--- delay the body traversals by putting them under a lambda.  Hence, we apply each function, to--- traverse its body and use a /dummy abstraction/ of the result.------ For example, given a function 'f', we traverse 'f (Tag 0)', which yields a transformed body 'e'.--- As the result of the traversal of the overall function, we use 'const e'.  Hence, it is crucial--- that the 'Tag' supplied during the initial traversal is already the one required by the HOAS to--- de Bruijn conversion in 'convertSharingAcc' — any subsequent application of 'const e' will only--- yield 'e' with the embedded 'Tag 0' of the original application.  During sharing recovery, we--- float /all/ free variables ('Atag' and 'Tag') out to construct the initial environment for--- producing de Bruijn indices, which replaces them by 'AvarSharing' or 'VarSharing' nodes.  Hence,--- the tag values only serve the purpose of determining the ordering in that initial environment.--- They are /not/ directly used to compute the de Brujin indices.----makeOccMapAcc-    :: Typeable arrs-    => Config-    -> Level-    -> Acc arrs-    -> IO (UnscopedAcc arrs, OccMap Acc)-makeOccMapAcc config lvl acc = do-  traceLine "makeOccMapAcc" "Enter"-  accOccMap             <- newASTHashTable-  (acc', _)             <- makeOccMapSharingAcc config accOccMap lvl acc-  frozenAccOccMap       <- freezeOccMap accOccMap-  traceLine "makeOccMapAcc" "Exit"-  return (acc', frozenAccOccMap)---makeOccMapSharingAcc-    :: Typeable arrs-    => Config-    -> OccMapHash Acc-    -> Level-    -> Acc arrs-    -> IO (UnscopedAcc arrs, Int)-makeOccMapSharingAcc config accOccMap = traverseAcc-  where-    traverseFun1 :: (Elt a, Typeable b) => Level -> (Exp a -> Exp b) -> IO (Exp a -> RootExp b, Int)-    traverseFun1 = makeOccMapFun1 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--    traverseAfun1 :: (Arrays a, Typeable b) => Level -> (Acc a -> Acc b) -> IO (Acc a -> UnscopedAcc b, Int)-    traverseAfun1 = makeOccMapAfun1 config accOccMap--    traverseExp :: Typeable e => Level -> Exp e -> IO (RootExp e, Int)-    traverseExp = makeOccMapExp config accOccMap--    traverseBoundary-        :: Level-        -> PreBoundary Acc Exp t-        -> IO (PreBoundary UnscopedAcc RootExp t, Int)-    traverseBoundary lvl bndy =-      case bndy of-        Clamp      -> return (Clamp, 0)-        Mirror     -> return (Mirror, 0)-        Wrap       -> return (Wrap, 0)-        Constant v -> return (Constant v, 0)-        Function f -> do-          (f', h) <- traverseFun1 lvl f-          return (Function f', h)--    -- 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-          -- Compute stable name and enter it into the occurrence map-          ---          sn                         <- makeStableAST acc-          heightIfRepeatedOccurrence <- enterOcc accOccMap (StableASTName sn) height--          traceLine (showPreAccOp pacc) $ 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 reconstruct :: Arrays arrs-                          => IO (PreAcc UnscopedAcc RootExp arrs, Int)-                          -> IO (UnscopedAcc arrs, Int)-              reconstruct newAcc-                = case heightIfRepeatedOccurrence of-                    Just height | recoverAccSharing config-                      -> return (UnscopedAcc [] (AvarSharing (StableNameHeight sn height)), height)-                    _ -> do (acc, height) <- newAcc-                            return (UnscopedAcc [] (AccSharing (StableNameHeight sn height) acc), height)--          case pacc of-            Atag i                      -> reconstruct $ return (Atag i, 0)           -- height is 0!-            Pipe afun1 afun2 acc        -> reconstruct $ do-                                             (afun1', h1) <- traverseAfun1 lvl afun1-                                             (afun2', h2) <- traverseAfun1 lvl afun2-                                             (acc', h3)   <- traverseAcc lvl acc-                                             return (Pipe afun1' afun2' acc'-                                                    , h1 `max` h2 `max` h3 + 1)-            Aforeign ff afun acc        -> reconstruct $ travA (Aforeign ff afun) acc-            Acond e acc1 acc2           -> reconstruct $ do-                                             (e'   , h1) <- traverseExp lvl e-                                             (acc1', h2) <- traverseAcc lvl acc1-                                             (acc2', h3) <- traverseAcc lvl acc2-                                             return (Acond e' acc1' acc2', h1 `max` h2 `max` h3 + 1)-            Awhile pred iter init       -> reconstruct $ do-                                             (pred', h1) <- traverseAfun1 lvl pred-                                             (iter', h2) <- traverseAfun1 lvl iter-                                             (init', h3) <- traverseAcc lvl init-                                             return (Awhile pred' iter' init'-                                                    , h1 `max` h2 `max` h3 + 1)--            Atuple tup                  -> reconstruct $ do-                                             (tup', h) <- travAtup tup-                                             return (Atuple tup', h)-            Aprj ix a                   -> reconstruct $ travA (Aprj ix) a--            Use arr                     -> reconstruct $ return (Use arr, 1)-            Unit e                      -> reconstruct $ do-                                             (e', h) <- traverseExp lvl e-                                             return (Unit e', h + 1)-            Generate e f                -> reconstruct $ do-                                             (e', h1) <- traverseExp lvl e-                                             (f', h2) <- traverseFun1 lvl f-                                             return (Generate e' f', h1 `max` h2 + 1)-            Reshape e acc               -> reconstruct $ travEA Reshape e acc-            Replicate e acc             -> reconstruct $ travEA Replicate e acc-            Slice acc e                 -> reconstruct $ travEA (flip Slice) e acc-            Map f acc                   -> reconstruct $ do-                                             (f'  , h1) <- traverseFun1 lvl f-                                             (acc', h2) <- traverseAcc lvl acc-                                             return (Map f' acc', h1 `max` h2 + 1)-            ZipWith f acc1 acc2         -> reconstruct $ travF2A2 ZipWith f acc1 acc2-            Fold f e acc                -> reconstruct $ travF2EA Fold f e acc-            Fold1 f acc                 -> reconstruct $ travF2A Fold1 f acc-            FoldSeg f e acc1 acc2       -> reconstruct $ do-                                             (f'   , h1) <- traverseFun2 lvl f-                                             (e'   , h2) <- traverseExp lvl e-                                             (acc1', h3) <- traverseAcc lvl acc1-                                             (acc2', h4) <- traverseAcc lvl acc2-                                             return (FoldSeg f' e' acc1' acc2',-                                                     h1 `max` h2 `max` h3 `max` h4 + 1)-            Fold1Seg f acc1 acc2        -> reconstruct $ travF2A2 Fold1Seg f acc1 acc2-            Scanl f e acc               -> reconstruct $ travF2EA Scanl f e acc-            Scanl' f e acc              -> reconstruct $ travF2EA Scanl' f e acc-            Scanl1 f acc                -> reconstruct $ travF2A Scanl1 f acc-            Scanr f e acc               -> reconstruct $ travF2EA Scanr f e acc-            Scanr' f e acc              -> reconstruct $ travF2EA Scanr' f e acc-            Scanr1 f acc                -> reconstruct $ travF2A Scanr1 f acc-            Permute c acc1 p acc2       -> reconstruct $ do-                                             (c'   , h1) <- traverseFun2 lvl c-                                             (p'   , h2) <- traverseFun1 lvl p-                                             (acc1', h3) <- traverseAcc lvl acc1-                                             (acc2', h4) <- traverseAcc lvl acc2-                                             return (Permute c' acc1' p' acc2',-                                                     h1 `max` h2 `max` h3 `max` h4 + 1)-            Backpermute e p acc         -> reconstruct $ do-                                             (e'  , h1) <- traverseExp lvl e-                                             (p'  , h2) <- traverseFun1 lvl p-                                             (acc', h3) <- traverseAcc lvl acc-                                             return (Backpermute e' p' acc', h1 `max` h2 `max` h3 + 1)-            Stencil s bnd acc           -> reconstruct $ do-                                             (s'  , h1) <- makeOccMapStencil1 config accOccMap acc lvl s-                                             (bnd', h2) <- traverseBoundary lvl bnd-                                             (acc', h3) <- traverseAcc lvl acc-                                             return (Stencil s' bnd' acc', h1 `max` h2 `max` h3 + 1)-            Stencil2 s bnd1 acc1-                       bnd2 acc2        -> reconstruct $ do-                                             (s'   , h1) <- makeOccMapStencil2 config accOccMap acc1 acc2 lvl s-                                             (bnd1', h2) <- traverseBoundary lvl bnd1-                                             (acc1', h3) <- traverseAcc lvl acc1-                                             (bnd2', h4) <- traverseBoundary lvl bnd2-                                             (acc2', h5) <- traverseAcc lvl acc2-                                             return (Stencil2 s' bnd1' acc1' bnd2' acc2',-                                                     h1 `max` h2 `max` h3 `max` h4 `max` h5 + 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)-              -> Acc arrs' -> IO (PreAcc UnscopedAcc RootExp arrs, Int)-        travA c acc-          = do-              (acc', h) <- traverseAcc lvl acc-              return (c acc', h + 1)--        travEA :: (Typeable b, Arrays arrs')-               => (RootExp b -> UnscopedAcc arrs' -> PreAcc UnscopedAcc RootExp arrs)-               -> Exp b -> Acc arrs' -> IO (PreAcc UnscopedAcc RootExp arrs, Int)-        travEA c exp acc-          = do-              (exp', h1) <- traverseExp lvl exp-              (acc', h2) <- traverseAcc lvl acc-              return (c exp' acc', h1 `max` h2 + 1)--        travF2A :: (Elt b, Elt c, Typeable d, Arrays arrs')-                => ((Exp b -> Exp c -> RootExp d) -> UnscopedAcc arrs'-                    -> PreAcc UnscopedAcc RootExp arrs)-                -> (Exp b -> Exp c -> Exp d) -> Acc arrs'-                -> IO (PreAcc UnscopedAcc RootExp arrs, Int)-        travF2A c fun acc-          = do-              (fun', h1) <- traverseFun2 lvl fun-              (acc', h2) <- traverseAcc lvl acc-              return (c fun' acc', h1 `max` h2 + 1)--        travF2EA :: (Elt b, Elt c, Typeable d, Typeable e, Arrays arrs')-                 => ((Exp b -> Exp c -> RootExp d) -> RootExp e -> UnscopedAcc arrs' -> PreAcc UnscopedAcc RootExp arrs)-                 -> (Exp b -> Exp c -> Exp d) -> Exp e -> Acc arrs'-                 -> IO (PreAcc UnscopedAcc RootExp arrs, Int)-        travF2EA c fun exp acc-          = do-              (fun', h1) <- traverseFun2 lvl fun-              (exp', h2) <- traverseExp lvl exp-              (acc', h3) <- traverseAcc lvl acc-              return (c fun' exp' acc', h1 `max` h2 `max` h3 + 1)--        travF2A2 :: (Elt b, Elt c, Typeable d, Arrays arrs1, Arrays arrs2)-                 => ((Exp b -> Exp c -> RootExp d) -> UnscopedAcc arrs1 -> UnscopedAcc arrs2 -> PreAcc UnscopedAcc RootExp arrs)-                 -> (Exp b -> Exp c -> Exp d) -> Acc arrs1 -> Acc arrs2-                 -> IO (PreAcc UnscopedAcc RootExp arrs, Int)-        travF2A2 c fun acc1 acc2-          = do-              (fun' , h1) <- traverseFun2 lvl fun-              (acc1', h2) <- traverseAcc lvl acc1-              (acc2', h3) <- traverseAcc lvl acc2-              return (c fun' acc1' acc2', h1 `max` h2 `max` h3 + 1)--        travAtup :: Atuple Acc a-                 -> IO (Atuple UnscopedAcc a, Int)-        travAtup NilAtup          = return (NilAtup, 1)-        travAtup (SnocAtup tup a) = do-          (tup', h1) <- travAtup tup-          (a',   h2) <- traverseAcc lvl a-          return (SnocAtup tup' a', h1 `max` h2 + 1)--makeOccMapAfun1 :: (Arrays a, Typeable b)-                => Config-                -> OccMapHash Acc-                -> Level-                -> (Acc a -> Acc b)-                -> IO (Acc a -> UnscopedAcc b, Int)-makeOccMapAfun1 config accOccMap lvl f = do-  let x = Acc (Atag lvl)-  ---  (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.------ See Note [Traversing functions and side effects]----makeOccMapExp-    :: Typeable e-    => Config-    -> OccMapHash Acc-    -> Level-    -> Exp e-    -> IO (RootExp e, Int)-makeOccMapExp config accOccMap lvl = makeOccMapRootExp config accOccMap lvl []--makeOccMapFun1-    :: (Elt a, Typeable b)-    => Config-    -> OccMapHash Acc-    -> Level-    -> (Exp a -> Exp b)-    -> IO (Exp a -> RootExp b, Int)-makeOccMapFun1 config accOccMap lvl f = do-  let x = Exp (Tag lvl)-  ---  (body, height) <- makeOccMapRootExp config accOccMap (lvl+1) [lvl] (f x)-  return (const body, height)--makeOccMapFun2-    :: (Elt a, Elt b, Typeable c)-    => Config-    -> OccMapHash Acc-    -> Level-    -> (Exp a -> Exp b -> Exp c)-    -> IO (Exp a -> Exp b -> RootExp c, Int)-makeOccMapFun2 config accOccMap lvl f = do-  let x = Exp (Tag (lvl+1))-      y = Exp (Tag lvl)-  ---  (body, height) <- makeOccMapRootExp config accOccMap (lvl+2) [lvl, lvl+1] (f x y)-  return (\_ _ -> body, height)--makeOccMapStencil1-    :: forall sh a b stencil. (Stencil sh a stencil, Typeable b)-    => Config-    -> OccMapHash Acc-    -> Acc (Array sh a)         {- dummy -}-    -> Level-    -> (stencil -> Exp b)-    -> IO (stencil -> RootExp b, Int)-makeOccMapStencil1 config accOccMap _ lvl stencil = do-  let x = Exp (Tag lvl)-      f = stencil . stencilPrj (undefined::sh) (undefined::a)-  ---  (body, height) <- makeOccMapRootExp config accOccMap (lvl+1) [lvl] (f x)-  return (const body, height)--makeOccMapStencil2-    :: forall sh a b c stencil1 stencil2. (Stencil sh a stencil1, Stencil sh b stencil2, Typeable c)-    => Config-    -> OccMapHash Acc-    -> Acc (Array sh a)         {- dummy -}-    -> Acc (Array sh b)         {- dummy -}-    -> Level-    -> (stencil1 -> stencil2 -> Exp c)-    -> IO (stencil1 -> stencil2 -> RootExp c, Int)-makeOccMapStencil2 config accOccMap _ _ lvl stencil = do-  let x         = Exp (Tag (lvl+1))-      y         = Exp (Tag lvl)-      f a b     = stencil (stencilPrj (undefined::sh) (undefined::a) a)-                          (stencilPrj (undefined::sh) (undefined::b) b)-  ---  (body, height) <- makeOccMapRootExp config accOccMap (lvl+2) [lvl, lvl+1] (f x y)-  return (\_ _ -> body, height)----- Generate sharing information for expressions embedded in Acc computations.--- Expressions are annotated with:------  1) the tags of free scalar variables (for scalar functions)---  2) a local occurrence map for that expression.----makeOccMapRootExp-    :: Typeable e-    => Config-    -> OccMapHash Acc-    -> Level                            -- The level of currently bound scalar variables-    -> [Int]                            -- The tags of newly introduced free scalar variables in this expression-    -> Exp e-    -> IO (RootExp e, Int)-makeOccMapRootExp config accOccMap lvl fvs exp = do-  traceLine "makeOccMapRootExp" "Enter"-  expOccMap                     <- newASTHashTable-  (UnscopedExp [] exp', height) <- makeOccMapSharingExp config accOccMap expOccMap lvl exp-  frozenExpOccMap               <- freezeOccMap expOccMap-  traceLine "makeOccMapRootExp" "Exit"-  return (RootExp frozenExpOccMap (UnscopedExp fvs exp'), height)----- Generate sharing information for an open scalar expression.----makeOccMapSharingExp-    :: Typeable e-    => Config-    -> OccMapHash Acc-    -> OccMapHash Exp-    -> Level                            -- The level of currently bound variables-    -> Exp e-    -> IO (UnscopedExp e, Int)-makeOccMapSharingExp config accOccMap expOccMap = travE-  where-    travE :: forall a. Typeable a => Level -> Exp a -> IO (UnscopedExp a, Int)-    travE lvl exp@(Exp pexp)-      = mfix $ \ ~(_, height) -> do-          -- Compute stable name and enter it into the occurrence map-          ---          sn                         <- makeStableAST exp-          heightIfRepeatedOccurrence <- enterOcc expOccMap (StableASTName sn) height--          traceLine (showPreExpOp pexp) $ 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 'newExp'.  See also 'enterOcc'.-          ---          -- NB: This function can only be used in the case alternatives below; outside of the-          --     case we cannot discharge the 'Elt a' constraint.-          ---          let reconstruct :: Elt a-                          => IO (PreExp UnscopedAcc UnscopedExp a, Int)-                          -> IO (UnscopedExp a, Int)-              reconstruct newExp-                = case heightIfRepeatedOccurrence of-                    Just height | recoverExpSharing config-                      -> return (UnscopedExp [] (VarSharing (StableNameHeight sn height)), height)-                    _ -> do (exp, height) <- newExp-                            return (UnscopedExp [] (ExpSharing (StableNameHeight sn height) exp), height)--          case pexp of-            Tag i               -> reconstruct $ return (Tag i, 0)      -- height is 0!-            Const c             -> reconstruct $ return (Const c, 1)-            Undef               -> reconstruct $ return (Undef, 1)-            Tuple tup           -> reconstruct $ do-                                     (tup', h) <- travTup tup-                                     return (Tuple tup', h)-            Prj i e             -> reconstruct $ travE1 (Prj i) e-            IndexNil            -> reconstruct $ return (IndexNil, 1)-            IndexCons ix i      -> reconstruct $ travE2 IndexCons ix i-            IndexHead i         -> reconstruct $ travE1 IndexHead i-            IndexTail ix        -> reconstruct $ travE1 IndexTail ix-            IndexAny            -> reconstruct $ return (IndexAny, 1)-            ToIndex sh ix       -> reconstruct $ travE2 ToIndex sh ix-            FromIndex sh e      -> reconstruct $ travE2 FromIndex sh e-            Cond e1 e2 e3       -> reconstruct $ travE3 Cond e1 e2 e3-            While p iter init   -> reconstruct $ do-                                     (p'   , h1) <- traverseFun1 lvl p-                                     (iter', h2) <- traverseFun1 lvl iter-                                     (init', h3) <- travE lvl init-                                     return (While p' iter' init', h1 `max` h2 `max` h3 + 1)-            PrimConst c         -> reconstruct $ return (PrimConst c, 1)-            PrimApp p e         -> reconstruct $ travE1 (PrimApp p) e-            Index a e           -> reconstruct $ travAE Index a e-            LinearIndex a i     -> reconstruct $ travAE LinearIndex a i-            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)-            Coerce e            -> reconstruct $ travE1 Coerce e--      where-        traverseAcc :: Typeable arrs => Level -> Acc arrs -> IO (UnscopedAcc arrs, Int)-        traverseAcc = makeOccMapSharingAcc config accOccMap--        traverseFun1 :: (Elt a, Typeable b)-                     => Level-                     -> (Exp a -> Exp b)-                     -> IO (Exp a -> UnscopedExp b, Int)-        traverseFun1 lvl f-          = do-              let x = Exp (Tag lvl)-              (UnscopedExp [] body, height) <- travE (lvl+1) (f x)-              return (const (UnscopedExp [lvl] body), height + 1)---        travE1 :: Typeable b => (UnscopedExp b -> PreExp UnscopedAcc UnscopedExp a) -> Exp b-               -> IO (PreExp UnscopedAcc UnscopedExp a, Int)-        travE1 c e-          = do-              (e', h) <- travE lvl e-              return (c e', h + 1)--        travE2 :: (Typeable b, Typeable c)-               => (UnscopedExp b -> UnscopedExp c -> PreExp UnscopedAcc UnscopedExp a)-               -> Exp b -> Exp c-               -> IO (PreExp UnscopedAcc UnscopedExp a, Int)-        travE2 c e1 e2-          = do-              (e1', h1) <- travE lvl e1-              (e2', h2) <- travE lvl e2-              return (c e1' e2', h1 `max` h2 + 1)--        travE3 :: (Typeable b, Typeable c, Typeable d)-               => (UnscopedExp b -> UnscopedExp c -> UnscopedExp d -> PreExp UnscopedAcc UnscopedExp a)-               -> Exp b -> Exp c -> Exp d-               -> IO (PreExp UnscopedAcc UnscopedExp a, Int)-        travE3 c e1 e2 e3-          = do-              (e1', h1) <- travE lvl e1-              (e2', h2) <- travE lvl e2-              (e3', h3) <- travE lvl e3-              return (c e1' e2' e3', h1 `max` h2 `max` h3 + 1)--        travA :: Typeable b => (UnscopedAcc b -> PreExp UnscopedAcc UnscopedExp a) -> Acc b-              -> IO (PreExp UnscopedAcc UnscopedExp a, Int)-        travA c acc-          = do-              (acc', h) <- traverseAcc lvl acc-              return (c acc', h + 1)--        travAE :: (Typeable b, Typeable c)-               => (UnscopedAcc b -> UnscopedExp c -> PreExp UnscopedAcc UnscopedExp a)-               -> Acc b -> Exp c-               -> IO (PreExp UnscopedAcc UnscopedExp a, Int)-        travAE c acc e-          = do-              (acc', h1) <- traverseAcc lvl acc-              (e'  , h2) <- travE lvl e-              return (c acc' e', h1 `max` h2 + 1)--        travTup :: Tuple Exp tup -> IO (Tuple UnscopedExp tup, Int)-        travTup NilTup          = return (NilTup, 1)-        travTup (SnocTup tup e) = do-                                    (tup', h1) <- travTup tup-                                    (e'  , h2) <- travE lvl e-                                    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.------   Invariants of the list:---   - If one shared term 's' is itself a subterm of another shared term 't', then 's' must occur---     *after* 't' in the list.---   - No shared term occurs twice.---   - 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. 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')--- is 0, whereas other leaves have height 1.  This guarantees that all free variables are at the end--- of the 'NodeCounts' list.------ The graph is represented as a map where a stable name 'a' is mapped to a set of stables names 'b'--- such that if there exists a edge from 'a' to 'c' that 'c' is contained within 'b'.------  Properties of the graph:---  - There exists an edge from 'a' to 'b' if the term 'a' names is a subterm of the term named by---    'b'.------ To ensure the list invariant and the graph properties are preserved over merging node counts from--- sibling subterms, the function '(+++)' must be used.----type NodeCounts = ([NodeCount], Map.HashMap NodeName (Set.HashSet NodeName))--data NodeName where-  NodeName :: Typeable a => StableName a -> NodeName--instance Eq NodeName where-  (NodeName sn1) == (NodeName sn2) | Just sn2' <- gcast sn2 = sn1 == sn2'-                                   | otherwise              = False--instance Hashable NodeName where-  hashWithSalt hash (NodeName sn1) = hash + hashStableName sn1--instance Show NodeName where-  show (NodeName sn) = show (hashStableName sn)--data NodeCount = AccNodeCount StableSharingAcc Int-               | ExpNodeCount StableSharingExp Int-               -- SeqNodeCount StableSharingSeq Int-               deriving Show---- Empty node counts----noNodeCounts :: NodeCounts-noNodeCounts = ([], Map.empty)---- Insert an Acc node into the node counts, assuming that it is a superterm of the all the existing--- nodes.------ TODO: Perform cycle detection here.-insertAccNode :: StableSharingAcc -> NodeCounts -> NodeCounts-insertAccNode ssa@(StableSharingAcc (StableNameHeight sn _) _) (subterms,g)-  = ([AccNodeCount 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]---- Insert an Exp node into the node counts, assuming that it is a superterm of the all the existing--- nodes.------ TODO: Perform cycle detection here.-insertExpNode :: StableSharingExp -> NodeCounts -> NodeCounts-insertExpNode ssa@(StableSharingExp (StableNameHeight sn _) _) (subterms,g)-  = ([ExpNodeCount 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]--{----- 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.-cleanCounts :: NodeCounts -> NodeCounts-cleanCounts (ns, g) = (ns, Map.fromList $ [(h, Set.filter (flip elem hs) (g Map.! h)) | h <- hs ])-  where-    hs = (map nodeName ns)--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.------ * We assume that the list invariant —subterms follow their parents— holds for both arguments and---   guarantee that it still holds for the result.--- * In the same manner, we assume that all 'Exp' node counts precede 'Acc' node counts and---   guarantee that this also hold for the result.------ RCE: The list combination should be able to be performed as a more efficient merge.----(+++) :: NodeCounts -> NodeCounts -> NodeCounts-(ns1,g1) +++ (ns2,g2) = (foldr insert ns1 ns2, Map.unionWith Set.union g1 g2)-  where-    insert x               []                         = [x]-    insert x@(AccNodeCount sa1 count1) ys@(y@(AccNodeCount sa2 count2) : ys')-      | sa1 == sa2          = AccNodeCount (sa1 `pickNoneAvar` sa2) (count1 + count2) : ys'-      | sa1 `higherSSA` sa2 = x : ys-      | otherwise           = y : insert x ys'-    insert x@(ExpNodeCount se1 count1) ys@(y@(ExpNodeCount se2 count2) : ys')-      | 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--    (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.)------ Bail out if any tag occurs multiple times as this indicates that the sharing of an argument--- variable was not preserved and we cannot build an appropriate initial environment (c.f., comments--- at 'determineScopesAcc'.----buildInitialEnvAcc :: [Level] -> [StableSharingAcc] -> [StableSharingAcc]-buildInitialEnvAcc tags sas = map (lookupSA sas) tags-  where-    lookupSA sas tag1-      = case filter hasTag sas of-          []   -> noStableSharing    -- tag is not used in the analysed expression-          [sa] -> sa                 -- tag has a unique occurrence-          sas2 -> $internalError "buildInitialEnvAcc"-                $ "Encountered duplicate 'ATag's\n  " ++ intercalate ", " (map showSA sas2)-      where-        hasTag (StableSharingAcc _ (AccSharing _ (Atag tag2))) = tag1 == tag2-        hasTag sa-          = $internalError "buildInitialEnvAcc"-          $ "Encountered a node that is not a plain 'Atag'\n  " ++ showSA sa--        noStableSharing :: StableSharingAcc-        noStableSharing = StableSharingAcc noStableAccName (undefined :: SharingAcc acc exp ())--    showSA (StableSharingAcc _ (AccSharing  sn acc)) = show (hashStableNameHeight sn) ++ ": " ++-                                                       showPreAccOp acc-    showSA (StableSharingAcc _ (AvarSharing sn))     = "AvarSharing " ++ show (hashStableNameHeight sn)-    showSA (StableSharingAcc _ (AletSharing sa _ ))  = "AletSharing " ++ show sa ++ "..."---- Build an initial environment for the tag values given in the first argument for traversing a--- scalar expression.  The 'StableSharingExp'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.)------ Bail out if any tag occurs multiple times as this indicates that the sharing of an argument--- variable was not preserved and we cannot build an appropriate initial environment (c.f., comments--- at 'determineScopesAcc'.----buildInitialEnvExp :: [Level] -> [StableSharingExp] -> [StableSharingExp]-buildInitialEnvExp tags ses = map (lookupSE ses) tags-  where-    lookupSE ses tag1-      = case filter hasTag ses of-          []   -> noStableSharing    -- tag is not used in the analysed expression-          [se] -> se                 -- tag has a unique occurrence-          ses2 -> $internalError "buildInitialEnvExp"-                    ("Encountered a duplicate 'Tag'\n  " ++ intercalate ", " (map showSE ses2))-      where-        hasTag (StableSharingExp _ (ExpSharing _ (Tag tag2))) = tag1 == tag2-        hasTag se-          = $internalError "buildInitialEnvExp"-              ("Encountered a node that is not a plain 'Tag'\n  " ++ showSE se)--        noStableSharing :: StableSharingExp-        noStableSharing = StableSharingExp noStableExpName (undefined :: SharingExp acc exp ())--    showSE (StableSharingExp _ (ExpSharing sn exp)) = show (hashStableNameHeight sn) ++ ": " ++-                                                      showPreExpOp exp-    showSE (StableSharingExp _ (VarSharing sn))     = "VarSharing " ++ show (hashStableNameHeight sn)-    showSE (StableSharingExp _ (LetSharing se _ ))  = "LetSharing " ++ show se ++ "..."---- Determine whether a 'NodeCount' is for an 'Atag' or 'Tag', which represent free variables.----isFreeVar :: NodeCount -> Bool-isFreeVar (AccNodeCount (StableSharingAcc _ (AccSharing _ (Atag _))) _) = True-isFreeVar (ExpNodeCount (StableSharingExp _ (ExpSharing _ (Tag  _))) _) = True-isFreeVar _                                                             = False----- Determine scope of shared subterms--- ==================================---- Determine the scopes of all variables representing shared subterms (Phase Two) in a bottom-up--- sweep.  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.------ In addition to the AST with sharing information, yield the 'StableSharingAcc's for all free--- variables of 'rootAcc', which are represented by 'Atag' leaves in the tree. They are in order of--- the tag values — i.e., in the same order that they need to appear in an environment to use the--- tag for indexing into that environment.------ Precondition: there are only 'AvarSharing' and 'AccSharing' nodes in the argument.----determineScopesAcc-    :: Typeable a-    => Config-    -> [Level]-    -> OccMap Acc-    -> UnscopedAcc a-    -> (ScopedAcc a, [StableSharingAcc])-determineScopesAcc config fvs accOccMap rootAcc-  = let (sharingAcc, (counts, _)) = determineScopesSharingAcc config accOccMap rootAcc-        unboundTrees              = filter (not . isFreeVar) counts-    in-    if all isFreeVar counts-       then (sharingAcc, buildInitialEnvAcc fvs [sa | AccNodeCount sa _ <- counts])-       else $internalError "determineScopesAcc" ("unbound shared subtrees" ++ show unboundTrees)---determineScopesSharingAcc-    :: Config-    -> OccMap Acc-    -> UnscopedAcc a-    -> (ScopedAcc a, NodeCounts)-determineScopesSharingAcc config accOccMap = scopesAcc-  where-    scopesAcc :: forall arrs. UnscopedAcc arrs -> (ScopedAcc arrs, NodeCounts)-    scopesAcc (UnscopedAcc _ (AletSharing _ _))-      = $internalError "determineScopesSharingAcc: scopesAcc" "unexpected 'AletSharing'"--    scopesAcc (UnscopedAcc _ (AvarSharing sn))-      = (ScopedAcc [] (AvarSharing sn), StableSharingAcc sn (AvarSharing sn) `insertAccNode` noNodeCounts)--    scopesAcc (UnscopedAcc _ (AccSharing sn pacc))-      = case pacc of-          Atag i                  -> reconstruct (Atag i) noNodeCounts-          Pipe afun1 afun2 acc    -> let-                                       (afun1', accCount1) = scopesAfun1 afun1-                                       (afun2', accCount2) = scopesAfun1 afun2-                                       (acc', accCount3)   = scopesAcc acc-                                     in-                                     reconstruct (Pipe afun1' afun2' acc')-                                                 (accCount1 +++ accCount2 +++ accCount3)--          Aforeign ff afun acc    -> let-                                       (acc', accCount) = scopesAcc acc-                                     in-                                     reconstruct (Aforeign ff afun acc') accCount-          Acond e acc1 acc2       -> let-                                       (e'   , accCount1) = scopesExp e-                                       (acc1', accCount2) = scopesAcc acc1-                                       (acc2', accCount3) = scopesAcc acc2-                                     in-                                     reconstruct (Acond e' acc1' acc2')-                                                 (accCount1 +++ accCount2 +++ accCount3)--          Awhile pred iter init   -> let-                                       (pred', accCount1) = scopesAfun1 pred-                                       (iter', accCount2) = scopesAfun1 iter-                                       (init', accCount3) = scopesAcc init-                                     in-                                     reconstruct (Awhile pred' iter' init')-                                                 (accCount1 +++ accCount2 +++ accCount3)--          Atuple tup              -> let (tup', accCount) = travAtup tup-                                     in  reconstruct (Atuple tup') accCount-          Aprj ix a               -> travA (Aprj ix) a--          Use arr                 -> reconstruct (Use arr) noNodeCounts-          Unit e                  -> let-                                       (e', accCount) = scopesExp e-                                     in-                                     reconstruct (Unit e') accCount-          Generate sh f           -> let-                                       (sh', accCount1) = scopesExp sh-                                       (f' , accCount2) = scopesFun1 f-                                     in-                                     reconstruct (Generate sh' f') (accCount1 +++ accCount2)-          Reshape sh acc          -> travEA Reshape sh acc-          Replicate n acc         -> travEA Replicate n acc-          Slice acc i             -> travEA (flip Slice) i acc-          Map f acc               -> let-                                       (f'  , accCount1) = scopesFun1 f-                                       (acc', accCount2) = scopesAcc  acc-                                     in-                                     reconstruct (Map f' acc') (accCount1 +++ accCount2)-          ZipWith f acc1 acc2     -> travF2A2 ZipWith f acc1 acc2-          Fold f z acc            -> travF2EA Fold f z acc-          Fold1 f acc             -> travF2A Fold1 f acc-          FoldSeg f z acc1 acc2   -> let-                                       (f'   , accCount1)  = scopesFun2 f-                                       (z'   , accCount2)  = scopesExp  z-                                       (acc1', accCount3)  = scopesAcc  acc1-                                       (acc2', accCount4)  = scopesAcc  acc2-                                     in-                                     reconstruct (FoldSeg f' z' acc1' acc2')-                                       (accCount1 +++ accCount2 +++ accCount3 +++ accCount4)-          Fold1Seg f acc1 acc2    -> travF2A2 Fold1Seg f acc1 acc2-          Scanl f z acc           -> travF2EA Scanl f z acc-          Scanl' f z acc          -> travF2EA Scanl' f z acc-          Scanl1 f acc            -> travF2A Scanl1 f acc-          Scanr f z acc           -> travF2EA Scanr f z acc-          Scanr' f z acc          -> travF2EA Scanr' f z acc-          Scanr1 f acc            -> travF2A Scanr1 f acc-          Permute fc acc1 fp acc2 -> let-                                       (fc'  , accCount1) = scopesFun2 fc-                                       (acc1', accCount2) = scopesAcc  acc1-                                       (fp'  , accCount3) = scopesFun1 fp-                                       (acc2', accCount4) = scopesAcc  acc2-                                     in-                                     reconstruct (Permute fc' acc1' fp' acc2')-                                       (accCount1 +++ accCount2 +++ accCount3 +++ accCount4)-          Backpermute sh fp acc   -> let-                                       (sh' , accCount1) = scopesExp  sh-                                       (fp' , accCount2) = scopesFun1 fp-                                       (acc', accCount3) = scopesAcc  acc-                                     in-                                     reconstruct (Backpermute sh' fp' acc')-                                       (accCount1 +++ accCount2 +++ accCount3)-          Stencil st bnd acc      -> let-                                       (st' , accCount1) = scopesStencil1 acc st-                                       (bnd', accCount2) = scopesBoundary bnd-                                       (acc', accCount3) = scopesAcc acc-                                     in-                                     reconstruct (Stencil st' bnd' acc') (accCount1 +++ accCount2 +++ accCount3)-          Stencil2 st bnd1 acc1 bnd2 acc2-                                  -> let-                                       (st'  , accCount1) = scopesStencil2 acc1 acc2 st-                                       (bnd1', accCount2) = scopesBoundary bnd1-                                       (acc1', accCount3) = scopesAcc acc1-                                       (bnd2', accCount4) = scopesBoundary bnd2-                                       (acc2', accCount5) = scopesAcc acc2-                                     in-                                     reconstruct (Stencil2 st' bnd1' acc1' bnd2' acc2')-                                       (accCount1 +++ accCount2 +++ accCount3 +++ accCount4 +++ accCount5)-          -- Collect seq             -> let-          --                              (seq', accCount1) = scopesSeq seq-          --                            in-          --                            reconstruct (Collect seq') accCount1--      where-        travEA :: (ScopedExp e -> ScopedAcc arrs' -> PreAcc ScopedAcc ScopedExp arrs)-               -> RootExp e-               -> UnscopedAcc arrs'-               -> (ScopedAcc arrs, NodeCounts)-        travEA c e acc = reconstruct (c e' acc') (accCount1 +++ accCount2)-          where-            (e'  , accCount1) = scopesExp e-            (acc', accCount2) = scopesAcc acc--        travF2A :: (Elt a, Elt b)-                => ((Exp a -> Exp b -> ScopedExp c) -> ScopedAcc arrs'-                    -> PreAcc ScopedAcc ScopedExp arrs)-                -> (Exp a -> Exp b -> RootExp c)-                -> UnscopedAcc arrs'-                -> (ScopedAcc arrs, NodeCounts)-        travF2A c f acc = reconstruct (c f' acc') (accCount1 +++ accCount2)-          where-            (f'  , accCount1) = scopesFun2 f-            (acc', accCount2) = scopesAcc  acc--        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)-                 -> RootExp e-                 -> UnscopedAcc arrs'-                 -> (ScopedAcc arrs, NodeCounts)-        travF2EA c f e acc = reconstruct (c f' e' acc') (accCount1 +++ accCount2 +++ accCount3)-          where-            (f'  , accCount1) = scopesFun2 f-            (e'  , accCount2) = scopesExp  e-            (acc', accCount3) = scopesAcc  acc--        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)-                 -> UnscopedAcc arrs1-                 -> UnscopedAcc arrs2-                 -> (ScopedAcc arrs, NodeCounts)-        travF2A2 c f acc1 acc2 = reconstruct (c f' acc1' acc2')-                                             (accCount1 +++ accCount2 +++ accCount3)-          where-            (f'   , accCount1) = scopesFun2 f-            (acc1', accCount2) = scopesAcc  acc1-            (acc2', accCount3) = scopesAcc  acc2--        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 :: (ScopedAcc arrs' -> PreAcc ScopedAcc ScopedExp arrs)-              -> UnscopedAcc arrs'-              -> (ScopedAcc arrs, NodeCounts)-        travA c acc = reconstruct (c acc') accCount-          where-            (acc', accCount) = scopesAcc acc--          -- Occurrence count of the currently processed node-        accOccCount = let StableNameHeight sn' _ = sn-                      in-                      lookupWithASTName accOccMap (StableASTName sn')--        -- Reconstruct the current tree node.-        ---        -- * If the current node is being shared ('accOccCount > 1'), replace it by a 'AvarSharing'-        --   node and float the shared subtree out wrapped in a 'NodeCounts' value.-        -- * If the current node is not shared, reconstruct it in place.-        -- * Special case for free variables ('Atag'): Replace the tree by a sharing variable and-        --   float the 'Atag' out in a 'NodeCounts' value.  This is independent of the number of-        --   occurrences.-        ---        -- In either case, any completed 'NodeCounts' are injected as bindings using 'AletSharing'-        -- node.-        ---        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-              -- occurrences-          = let thisCount = StableSharingAcc sn (AccSharing sn newAcc) `insertAccNode` noNodeCounts-            in-            tracePure "FREE" (show thisCount)-            (ScopedAcc [] (AvarSharing sn), thisCount)-        reconstruct newAcc subCount-              -- shared subtree => replace by a sharing variable (if 'recoverAccSharing' enabled)-          | accOccCount > 1 && recoverAccSharing config-          = let allCount = (StableSharingAcc sn sharingAcc `insertAccNode` newCount)-            in-            tracePure ("SHARED" ++ completed) (show allCount)-            (ScopedAcc [] (AvarSharing sn), allCount)-              -- neither shared nor free variable => leave it as it is-          | otherwise-          = tracePure ("Normal" ++ completed) (show newCount)-            (ScopedAcc [] sharingAcc, newCount)-          where-              -- Determine the bindings that need to be attached to the current node...-            (newCount, bindHere) = filterCompleted subCount--              -- ...and wrap them in 'AletSharing' constructors-            lets       = foldl (flip (.)) id . map (\x y -> AletSharing x (ScopedAcc [] y)) $ bindHere-            sharingAcc = lets $ AccSharing sn newAcc--              -- trace support-            completed | null bindHere = ""-                      | otherwise     = "(" ++ show (length bindHere) ++ " lets)"--        -- Extract *leading* nodes that have a complete node count (i.e., their node count is equal-        -- to the number of occurrences of that node in the overall expression).-        ---        -- Nodes with a completed node count should be let bound at the currently processed node.-        ---        -- NB: Only extract leading nodes (i.e., the longest run at the *front* of the list that is-        --     complete).  Otherwise, we would let-bind subterms before their parents, which leads-        --     scope errors.-        ---        filterCompleted :: NodeCounts -> (NodeCounts, [StableSharingAcc])-        filterCompleted (ns, graph)-          = let bindable     = map (isBindable bindable (map nodeName ns)) ns-                (bind, rest) = partition fst $ zip bindable ns-            in ((map snd rest, graph), [sa | AccNodeCount sa _ <- map snd bind])-          where-            -- a node is not yet complete while the node count 'n' is below the overall number-            -- of occurrences for that node in the whole program, with the exception that free-            -- variables are never complete-            isCompleted nc@(AccNodeCount sa n) | not . isFreeVar $ nc = lookupWithSharingAcc accOccMap sa == n-            isCompleted _                                             = False--            isBindable :: [Bool] -> [NodeName] -> NodeCount -> Bool-            isBindable bindable nodes nc@(AccNodeCount _ _) =-              let superTerms = Set.toList $ graph Map.! nodeName nc-                  unbound    = mapMaybe (`elemIndex` nodes) superTerms-              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--    -- 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--    -- The lambda bound variable is at this point already irrelevant; for details, see-    -- Note [Traversing functions and side effects]-    ---    scopesFun1 :: Elt e1 => (Exp e1 -> RootExp e2) -> (Exp e1 -> ScopedExp e2, NodeCounts)-    scopesFun1 f = (const body, counts)-      where-        (body, counts) = scopesExp (f undefined)--    -- The lambda bound variable is at this point already irrelevant; for details, see-    -- Note [Traversing functions and side effects]-    ---    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]-    ---    scopesStencil1 :: forall sh e1 e2 stencil. Stencil sh e1 stencil-                   => UnscopedAcc (Array sh e1){-dummy-}-                   -> (stencil -> RootExp e2)-                   -> (stencil -> ScopedExp e2, NodeCounts)-    scopesStencil1 _ stencilFun = (const body, counts)-      where-        (body, counts) = scopesExp (stencilFun undefined)--    -- The lambda bound variable is at this point already irrelevant; for details, see-    -- Note [Traversing functions and side effects]-    ---    scopesStencil2 :: forall sh e1 e2 e3 stencil1 stencil2.-                      (Stencil sh e1 stencil1, Stencil sh e2 stencil2)-                   => UnscopedAcc (Array sh e1){-dummy-}-                   -> UnscopedAcc (Array sh e2){-dummy-}-                   -> (stencil1 -> stencil2 -> RootExp e3)-                   -> (stencil1 -> stencil2 -> ScopedExp e3, NodeCounts)-    scopesStencil2 _ _ stencilFun = (\_ _ -> body, counts)-      where-        (body, counts) = scopesExp (stencilFun undefined undefined)--    scopesBoundary :: PreBoundary UnscopedAcc RootExp t-                   -> (PreBoundary ScopedAcc ScopedExp t, NodeCounts)-    scopesBoundary bndy =-      case bndy of-        Clamp      -> (Clamp, noNodeCounts)-        Mirror     -> (Mirror, noNodeCounts)-        Wrap       -> (Wrap, noNodeCounts)-        Constant v -> (Constant v, noNodeCounts)-        Function f -> let (body, counts) = scopesFun1 f-                      in  (Function body, counts)---determineScopesExp-    :: Config-    -> OccMap Acc-    -> RootExp t-    -> (ScopedExp t, NodeCounts)          -- Root (closed) expression plus Acc node counts-determineScopesExp config accOccMap (RootExp expOccMap exp@(UnscopedExp fvs _))-  = let-        ((ScopedExp [] expWithScopes), (nodeCounts,graph)) = determineScopesSharingExp config accOccMap expOccMap exp-        (expCounts, accCounts)          = partition isExpNodeCount nodeCounts--        isExpNodeCount ExpNodeCount{}   = True-        isExpNodeCount _                = False-    in-    (ScopedExp (buildInitialEnvExp fvs [se | ExpNodeCount se _ <- expCounts]) expWithScopes, cleanCounts (accCounts,graph))---determineScopesSharingExp-    :: Config-    -> OccMap Acc-    -> OccMap Exp-    -> UnscopedExp t-    -> (ScopedExp t, NodeCounts)-determineScopesSharingExp config accOccMap expOccMap = scopesExp-  where-    scopesAcc :: UnscopedAcc a -> (ScopedAcc a, NodeCounts)-    scopesAcc = determineScopesSharingAcc config accOccMap--    scopesFun1 :: (Exp a -> UnscopedExp b) -> (Exp a -> ScopedExp b, NodeCounts)-    scopesFun1 f = tracePure ("LAMBDA " ++ (show ssa)) (show counts) (const (ScopedExp ssa body'), (counts',graph))-      where-        body@(UnscopedExp fvs _) = f undefined-        ((ScopedExp [] body'), (counts, graph)) = scopesExp body-        ssa     = buildInitialEnvExp fvs [se | ExpNodeCount se _ <- freeCounts]-        (freeCounts, counts') = partition isBoundHere counts--        isBoundHere (ExpNodeCount (StableSharingExp _ (ExpSharing _ (Tag i))) _) = i `elem` fvs-        isBoundHere _                                                            = False---    scopesExp :: forall t. UnscopedExp t -> (ScopedExp t, NodeCounts)-    scopesExp (UnscopedExp _ (LetSharing _ _))-      = $internalError "determineScopesSharingExp: scopesExp" "unexpected 'LetSharing'"--    scopesExp (UnscopedExp _ (VarSharing sn))-      = (ScopedExp [] (VarSharing sn), StableSharingExp sn (VarSharing sn) `insertExpNode` noNodeCounts)--    scopesExp (UnscopedExp _ (ExpSharing sn pexp))-      = case pexp of-          Tag i                 -> reconstruct (Tag i) noNodeCounts-          Const c               -> reconstruct (Const c) noNodeCounts-          Undef                 -> reconstruct Undef noNodeCounts-          Tuple tup             -> let (tup', accCount) = travTup tup-                                   in-                                   reconstruct (Tuple tup') accCount-          Prj i e               -> travE1 (Prj i) e-          IndexNil              -> reconstruct IndexNil noNodeCounts-          IndexCons ix i        -> travE2 IndexCons ix i-          IndexHead i           -> travE1 IndexHead i-          IndexTail ix          -> travE1 IndexTail ix-          IndexAny              -> reconstruct IndexAny noNodeCounts-          ToIndex sh ix         -> travE2 ToIndex sh ix-          FromIndex sh e        -> travE2 FromIndex sh e-          Cond e1 e2 e3         -> travE3 Cond e1 e2 e3-          While p it i          -> let-                                     (p' , accCount1) = scopesFun1 p-                                     (it', accCount2) = scopesFun1 it-                                     (i' , accCount3) = scopesExp i-                                   in reconstruct (While p' it' i') (accCount1 +++ accCount2 +++ accCount3)-          PrimConst c           -> reconstruct (PrimConst c) noNodeCounts-          PrimApp p e           -> travE1 (PrimApp p) e-          Index a e             -> travAE Index a e-          LinearIndex a e       -> travAE LinearIndex a e-          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-          Coerce e              -> travE1 Coerce e-      where-        travTup :: Tuple UnscopedExp tup -> (Tuple ScopedExp tup, NodeCounts)-        travTup NilTup          = (NilTup, noNodeCounts)-        travTup (SnocTup tup e) = let-                                    (tup', accCountT) = travTup tup-                                    (e'  , accCountE) = scopesExp e-                                  in-                                  (SnocTup tup' e', accCountT +++ accCountE)--        travE1 :: (ScopedExp a -> PreExp ScopedAcc ScopedExp t) -> UnscopedExp a-               -> (ScopedExp t, NodeCounts)-        travE1 c e = reconstruct (c e') accCount-          where-            (e', accCount) = scopesExp e--        travE2 :: (ScopedExp a -> ScopedExp b -> PreExp ScopedAcc ScopedExp t)-               -> UnscopedExp a-               -> UnscopedExp b-               -> (ScopedExp t, NodeCounts)-        travE2 c e1 e2 = reconstruct (c e1' e2') (accCount1 +++ accCount2)-          where-            (e1', accCount1) = scopesExp e1-            (e2', accCount2) = scopesExp e2--        travE3 :: (ScopedExp a -> ScopedExp b -> ScopedExp c -> PreExp ScopedAcc ScopedExp t)-               -> UnscopedExp a-               -> UnscopedExp b-               -> UnscopedExp c-               -> (ScopedExp t, NodeCounts)-        travE3 c e1 e2 e3 = reconstruct (c e1' e2' e3') (accCount1 +++ accCount2 +++ accCount3)-          where-            (e1', accCount1) = scopesExp e1-            (e2', accCount2) = scopesExp e2-            (e3', accCount3) = scopesExp e3--        travA :: (ScopedAcc a -> PreExp ScopedAcc ScopedExp t) -> UnscopedAcc a-              -> (ScopedExp t, NodeCounts)-        travA c acc = maybeFloatOutAcc c acc' accCount-          where-            (acc', accCount)  = scopesAcc acc--        travAE :: (ScopedAcc a -> ScopedExp b -> PreExp ScopedAcc ScopedExp t)-               -> UnscopedAcc a-               -> UnscopedExp b-               -> (ScopedExp t, NodeCounts)-        travAE c acc e = maybeFloatOutAcc (`c` e') acc' (accCountA +++ accCountE)-          where-            (acc', accCountA) = scopesAcc acc-            (e'  , accCountE) = scopesExp e--        maybeFloatOutAcc :: (ScopedAcc a -> PreExp ScopedAcc ScopedExp t)-                         -> ScopedAcc a-                         -> NodeCounts-                         -> (ScopedExp t, NodeCounts)-        maybeFloatOutAcc c acc@(ScopedAcc _ (AvarSharing _)) accCount        -- nothing to float out-          = reconstruct (c acc) accCount-        maybeFloatOutAcc c acc                 accCount-          | floatOutAcc config = reconstruct (c var) ((stableAcc `insertAccNode` noNodeCounts) +++ accCount)-          | otherwise          = reconstruct (c acc) accCount-          where-             (var, stableAcc) = abstract acc (\(ScopedAcc _ s) -> s)--        abstract :: ScopedAcc a -> (ScopedAcc a -> SharingAcc ScopedAcc ScopedExp a)-                 -> (ScopedAcc a, StableSharingAcc)-        abstract (ScopedAcc _ (AvarSharing _))       _      = $internalError "sharingAccToVar" "AvarSharing"-        abstract (ScopedAcc ssa (AletSharing sa acc))  lets = abstract acc (lets . (\x -> ScopedAcc ssa (AletSharing sa x)))-        abstract acc@(ScopedAcc ssa (AccSharing sn _)) lets = (ScopedAcc ssa (AvarSharing sn), StableSharingAcc sn (lets acc))--        -- Occurrence count of the currently processed node-        expOccCount = let StableNameHeight sn' _ = sn-                      in-                      lookupWithASTName expOccMap (StableASTName sn')--        -- Reconstruct the current tree node.-        ---        -- * If the current node is being shared ('expOccCount > 1'), replace it by a 'VarSharing'-        --   node and float the shared subtree out wrapped in a 'NodeCounts' value.-        -- * If the current node is not shared, reconstruct it in place.-        -- * Special case for free variables ('Tag'): Replace the tree by a sharing variable and-        --   float the 'Tag' out in a 'NodeCounts' value.  This is independent of the number of-        --   occurrences.-        ---        -- In either case, any completed 'NodeCounts' are injected as bindings using 'LetSharing'-        -- node.-        ---        reconstruct :: PreExp ScopedAcc ScopedExp t -> NodeCounts-                    -> (ScopedExp t, NodeCounts)-        reconstruct newExp@(Tag _) _subCount-              -- free variable => replace by a sharing variable regardless of the number of-              -- occurrences-          = let thisCount = StableSharingExp sn (ExpSharing sn newExp) `insertExpNode` noNodeCounts-            in-            tracePure "FREE" (show thisCount)-            (ScopedExp [] (VarSharing sn), thisCount)-        reconstruct newExp subCount-              -- shared subtree => replace by a sharing variable (if 'recoverExpSharing' enabled)-          | expOccCount > 1 && recoverExpSharing config-          = let allCount = StableSharingExp sn sharingExp `insertExpNode` newCount-            in-            tracePure ("SHARED" ++ completed) (show allCount)-            (ScopedExp [] (VarSharing sn), allCount)-              -- neither shared nor free variable => leave it as it is-          | otherwise-          = tracePure ("Normal" ++ completed) (show newCount)-            (ScopedExp [] sharingExp, newCount)-          where-              -- Determine the bindings that need to be attached to the current node...-            (newCount, bindHere) = filterCompleted subCount--              -- ...and wrap them in 'LetSharing' constructors-            lets       = foldl (flip (.)) id . map (\x y -> LetSharing x (ScopedExp [] y)) $ bindHere-            sharingExp = lets $ ExpSharing sn newExp--              -- trace support-            completed | null bindHere = ""-                      | otherwise     = "(" ++ show (length bindHere) ++ " lets)"--        -- Extract *leading* nodes that have a complete node count (i.e., their node count is equal-        -- to the number of occurrences of that node in the overall expression).-        ---        -- Nodes with a completed node count should be let bound at the currently processed node.-        ---        -- NB: Only extract leading nodes (i.e., the longest run at the *front* of the list that is-        --     complete).  Otherwise, we would let-bind subterms before their parents, which leads-        --     scope errors.-        ---        filterCompleted :: NodeCounts -> (NodeCounts, [StableSharingExp])-        filterCompleted (ns,graph)-          = let bindable       = map (isBindable bindable (map nodeName ns)) ns-                (bind, unbind) = partition fst $ zip bindable ns-            in ((map snd unbind, graph), [se | ExpNodeCount se _ <- map snd bind])-          where-            -- a node is not yet complete while the node count 'n' is below the overall number-            -- of occurrences for that node in the whole program, with the exception that free-            -- variables are never complete-            isCompleted nc@(ExpNodeCount sa n) | not . isFreeVar $ nc = lookupWithSharingExp expOccMap sa == n-            isCompleted _                                             = False--            isBindable :: [Bool] -> [NodeName] -> NodeCount -> Bool-            isBindable bindable nodes nc@(ExpNodeCount _ _) =-              let superTerms = Set.toList $ graph Map.! nodeName nc-                  unbound    = mapMaybe (`elemIndex` nodes) superTerms-              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.------ Also returns the 'StableSharingAcc's of all 'Atag' leaves in environment order — they represent--- the free variables of the AST.------ NB: Strictly speaking, this function is not deterministic, as it uses stable pointers to---     determine the sharing of subterms.  The stable pointer API does not guarantee its---     completeness; i.e., it may miss some equalities, which implies that we may fail to discover---     some sharing.  However, sharing does not affect the denotational meaning of an array---     computation; hence, we do not compromise denotational correctness.------     There is one caveat: We currently rely on the 'Atag' and 'Tag' leaves representing free---     variables to be shared if any of them is used more than once.  If one is duplicated, the---     environment for de Bruijn conversion will have a duplicate entry, and hence, be of the wrong---     size, which is fatal. (The 'buildInitialEnv*' functions will already bail out.)----{-# NOINLINE recoverSharingAcc #-}-recoverSharingAcc-    :: Typeable a-    => Config-    -> Level            -- The level of currently bound array variables-    -> [Level]          -- The tags of newly introduced free array variables-    -> Acc a-    -> (ScopedAcc a, [StableSharingAcc])-recoverSharingAcc config alvl avars acc-  = let (acc', occMap)-          = unsafePerformIO             -- to enable stable pointers; this is safe as explained above-          $ makeOccMapAcc config alvl acc-    in-    determineScopesAcc config avars occMap acc'---{-# NOINLINE recoverSharingExp #-}-recoverSharingExp-    :: Typeable e-    => Config-    -> Level            -- The level of currently bound scalar variables-    -> [Level]          -- The tags of newly introduced free scalar variables-    -> Exp e-    -> (ScopedExp e, [StableSharingExp])-recoverSharingExp config lvl fvar exp-  = let-        (rootExp, accOccMap) = unsafePerformIO $ do-          accOccMap       <- newASTHashTable-          (exp', _)       <- makeOccMapRootExp config accOccMap lvl fvar exp-          frozenAccOccMap <- freezeOccMap accOccMap--          return (exp', frozenAccOccMap)--        (ScopedExp sse sharingExp, _) =-          determineScopesExp config accOccMap rootExp-    in-    (ScopedExp [] sharingExp, sse)---{---{-# NOINLINE recoverSharingSeq #-}-recoverSharingSeq-    :: Typeable e-    => Config+{-# LANGUAGE AllowAmbiguousTypes #-}+{-# LANGUAGE BangPatterns        #-}+{-# LANGUAGE FlexibleContexts    #-}+{-# LANGUAGE FlexibleInstances   #-}+{-# LANGUAGE GADTs               #-}+{-# LANGUAGE LambdaCase          #-}+{-# LANGUAGE OverloadedLists     #-}+{-# LANGUAGE PatternGuards       #-}+{-# LANGUAGE RankNTypes          #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE StandaloneDeriving  #-}+{-# LANGUAGE TupleSections       #-}+{-# LANGUAGE TypeApplications    #-}+{-# LANGUAGE TypeFamilies        #-}+{-# LANGUAGE TypeOperators       #-}+{-# OPTIONS_GHC -fno-warn-name-shadowing #-}+{-# OPTIONS_HADDOCK hide #-}+-- |+-- Module      : Data.Array.Accelerate.Trafo.Sharing+-- Copyright   : [2008..2020] The Accelerate Team+-- License     : BSD3+--+-- Maintainer  : Trevor L. McDonell <trevor.mcdonell@gmail.com>+-- Stability   : experimental+-- Portability : non-portable (GHC extensions)+--+-- This module implements HOAS to de Bruijn conversion of array expressions+-- while incorporating sharing information.+--++module Data.Array.Accelerate.Trafo.Sharing (++  -- * HOAS to de Bruijn conversion+  convertAcc, convertAccWith,++  Afunction, AfunctionR, ArraysFunctionR, AfunctionRepr(..), afunctionRepr,+  convertAfun, convertAfunWith,++  Function, FunctionR, EltFunctionR, FunctionRepr(..), functionRepr,+  convertExp, convertExpWith,+  convertFun, convertFunWith,++  -- convertSeq++) where++import Data.Array.Accelerate.AST                                    hiding ( PreOpenAcc(..), OpenAcc(..), Acc, OpenExp(..), Exp, Boundary(..), HasArraysR(..), showPreAccOp )+import Data.Array.Accelerate.AST.Environment+import Data.Array.Accelerate.AST.Idx+import Data.Array.Accelerate.AST.LeftHandSide+import Data.Array.Accelerate.AST.Var+import Data.Array.Accelerate.Analysis.Match+import Data.Array.Accelerate.Debug.Flags                            as Debug+import Data.Array.Accelerate.Debug.Trace                            as Debug+import Data.Array.Accelerate.Error+import Data.Array.Accelerate.Representation.Array                   ( Array, ArraysR, ArrayR(..), showArraysR )+import Data.Array.Accelerate.Representation.Shape                   hiding ( zip )+import Data.Array.Accelerate.Representation.Stencil+import Data.Array.Accelerate.Representation.Tag+import Data.Array.Accelerate.Representation.Type+import Data.Array.Accelerate.Smart                                  as Smart hiding ( StencilR )+import Data.Array.Accelerate.Sugar.Array                            hiding ( Array, ArraysR, (!!) )+import Data.Array.Accelerate.Sugar.Elt+import Data.Array.Accelerate.Trafo.Config+import Data.Array.Accelerate.Trafo.Substitution+import Data.Array.Accelerate.Trafo.Var+import Data.Array.Accelerate.Type+import Data.BitSet                                                  ( (\\), member )+import qualified Data.Array.Accelerate.AST                          as AST+import qualified Data.Array.Accelerate.Representation.Stencil       as R+import qualified Data.Array.Accelerate.Sugar.Array                  as Sugar++import Control.Applicative                                          hiding ( Const )+import Control.Lens                                                 ( over, mapped, _1, _2 )+import Control.Monad.Fix+import Data.Function                                                ( on )+import Data.Hashable+import Data.List                                                    ( elemIndex, findIndex, groupBy, intercalate, partition )+import Data.Maybe+import Data.Monoid                                                  ( Any(..) )+import System.IO.Unsafe                                             ( unsafePerformIO )+import System.Mem.StableName+import Text.Printf+import qualified Data.HashMap.Strict                                as Map+import qualified Data.HashSet                                       as Set+import qualified Data.HashTable.IO                                  as Hash+import qualified Data.IntMap                                        as IntMap+import Prelude+++-- Layouts+-- -------++-- A layout of an environment has an entry for each entry of the environment.+-- Each entry in the layout holds the de Bruijn index that refers to the+-- corresponding entry in the environment.+--+data Layout s env env' where+  EmptyLayout :: Layout s env ()+  PushLayout  :: Layout s env env1+              -> LeftHandSide s t env1 env2+              -> Vars s env t+              -> Layout s env env2++type ELayout = Layout ScalarType+type ArrayLayout = Layout ArrayR+++-- Project the nth index out of an environment layout.+--+-- The first argument provides context information for error messages in the+-- case of failure.+--+prjIdx :: forall s t env env1. HasCallStack+       => String+       -> (forall t'. TupR s t' -> ShowS)+       -> (forall u v. TupR s u -> TupR s v -> Maybe (u :~: v))+       -> TupR s t+       -> Int+       -> Layout s env env1+       -> Vars s env t+prjIdx context showTp matchTp tp = go+  where+    go :: forall env'. HasCallStack => Int -> Layout s env env' -> Vars s env t+    go _ EmptyLayout                        = no "environment does not contain index"+    go 0 (PushLayout _ lhs vars)+      | Just Refl <- matchTp tp tp'         = vars+      | otherwise                           = no $ printf "couldn't match expected type `%s' with actual type `%s'"+                                                          (showTp tp  "")+                                                          (showTp tp' "")+      where+        tp' = lhsToTupR lhs+    go n (PushLayout l _ _)                 = go (n-1) l++    no :: HasCallStack => String -> a+    no reason = internalError (printf "%s\nin the context: %s" reason context)++-- Add an entry to a layout, incrementing all indices+--+incLayout :: env1 :> env2 -> Layout s env1 env' -> Layout s env2 env'+incLayout _ EmptyLayout            = EmptyLayout+incLayout k (PushLayout lyt lhs v) = PushLayout (incLayout k lyt) lhs (weakenVars k v)++sizeLayout :: Layout s env env' -> Int+sizeLayout EmptyLayout          = 0+sizeLayout (PushLayout lyt _ _) = 1 + sizeLayout lyt++-- Conversion from HOAS to de Bruijn computation AST+-- =================================================++-- Array computations+-- ------------------++-- | Convert a closed array expression to de Bruijn form while also incorporating sharing+-- information.+--+convertAcc :: HasCallStack => Acc arrs -> AST.Acc (Sugar.ArraysR arrs)+convertAcc = convertAccWith defaultOptions++convertAccWith :: HasCallStack => Config -> Acc arrs -> AST.Acc (Sugar.ArraysR arrs)+convertAccWith config (Acc acc) = convertOpenAcc config EmptyLayout acc+++-- | Convert a closed function over array computations, while incorporating+-- sharing information.+--+convertAfun :: HasCallStack => Afunction f => f -> AST.Afun (ArraysFunctionR f)+convertAfun = convertAfunWith defaultOptions++convertAfunWith :: HasCallStack => Afunction f => Config -> f -> AST.Afun (ArraysFunctionR f)+convertAfunWith config = convertOpenAfun config EmptyLayout++data AfunctionRepr f ar areprr where+  AfunctionReprBody+    :: Arrays b => AfunctionRepr (Acc b) b (Sugar.ArraysR b)++  AfunctionReprLam+    :: Arrays a+    => AfunctionRepr b br breprr+    -> AfunctionRepr (Acc a -> b) (a -> br) (Sugar.ArraysR a -> breprr)++-- Convert a HOAS fragment into de Bruijn form, binding variables into the typed+-- environment layout one binder at a time.+--+-- NOTE: Because we convert one binder at a time left-to-right, the bound+--       variables ('vars') will have de Bruijn index _zero_ as the outermost+--       binding, and thus go to the end of the list.+--+class Afunction f where+  type AfunctionR f+  type ArraysFunctionR f+  afunctionRepr   :: HasCallStack => AfunctionRepr f (AfunctionR f) (ArraysFunctionR f)+  convertOpenAfun :: HasCallStack => Config -> ArrayLayout aenv aenv -> f -> AST.OpenAfun aenv (ArraysFunctionR f)++instance (Arrays a, Afunction r) => Afunction (Acc a -> r) where+  type AfunctionR      (Acc a -> r) = a -> AfunctionR r+  type ArraysFunctionR (Acc a -> r) = Sugar.ArraysR a -> ArraysFunctionR r++  afunctionRepr = AfunctionReprLam $ afunctionRepr @r+  convertOpenAfun config alyt f+    | repr <- Sugar.arraysR @a+    , DeclareVars lhs k value <- declareVars repr+    = let+        a     = Acc $ SmartAcc $ Atag repr $ sizeLayout alyt+        alyt' = PushLayout (incLayout k alyt) lhs (value weakenId)+      in+        Alam lhs $ convertOpenAfun config alyt' $ f a++instance Arrays b => Afunction (Acc b) where+  type AfunctionR      (Acc b) = b+  type ArraysFunctionR (Acc b) = Sugar.ArraysR b+  afunctionRepr = AfunctionReprBody+  convertOpenAfun config alyt (Acc body) = Abody $ convertOpenAcc config alyt body++convertSmartAfun1+    :: HasCallStack+    => Config+    -> ArraysR a+    -> (SmartAcc a -> SmartAcc b)+    -> AST.Afun (a -> b)+convertSmartAfun1 config repr f+  | DeclareVars lhs _ value <- declareVars repr+  = let+      a     = SmartAcc $ Atag repr 0+      alyt' = PushLayout EmptyLayout lhs (value weakenId)+    in+      Alam lhs $ Abody $ convertOpenAcc config alyt' $ f a++-- | Convert an open array expression to de Bruijn form while also incorporating sharing+-- information.+--+convertOpenAcc+    :: HasCallStack+    => Config+    -> ArrayLayout aenv aenv+    -> SmartAcc arrs+    -> AST.OpenAcc aenv arrs+convertOpenAcc config alyt acc =+  let lvl                      = sizeLayout alyt+      fvs                      = [lvl-1, lvl-2 .. 0]+      (sharingAcc, initialEnv) = recoverSharingAcc config lvl fvs acc+  in+  convertSharingAcc config alyt initialEnv sharingAcc+++-- | Convert an array expression with given array environment layout and sharing information into+-- de Bruijn form while recovering sharing at the same time (by introducing appropriate let+-- bindings).  The latter implements the third phase of sharing recovery.+--+-- The sharing environment 'env' keeps track of all currently bound sharing variables, keeping them+-- in reverse chronological order (outermost variable is at the end of the list).+--+convertSharingAcc+    :: forall aenv arrs. HasCallStack+    => Config+    -> ArrayLayout aenv aenv+    -> [StableSharingAcc]+    -> ScopedAcc arrs+    -> AST.OpenAcc aenv arrs+convertSharingAcc _ alyt aenv (ScopedAcc lams (AvarSharing sa repr))+  | Just i <- findIndex (matchStableAcc sa) aenv'+  = avarsIn AST.OpenAcc+  $ prjIdx (ctxt ++ "; i = " ++ show i) showArraysR matchArraysR repr i alyt+  | null aenv'+  = error $ "Cyclic definition of a value of type 'Acc' (sa = " ++ show (hashStableNameHeight sa) ++ ")"+  | otherwise+  = internalError err+  where+    aenv' = lams ++ aenv+    ctxt = "shared 'Acc' tree with stable name " ++ show (hashStableNameHeight sa)+    err  = "inconsistent valuation @ " ++ ctxt ++ ";\n  aenv = " ++ show aenv'++convertSharingAcc config alyt aenv (ScopedAcc lams (AletSharing sa@(StableSharingAcc (_ :: StableAccName as) boundAcc) bodyAcc))+  = case declareVars $ AST.arraysR bound of+      DeclareVars lhs k value ->+        let+          alyt' = PushLayout (incLayout k alyt) lhs (value weakenId)+        in+          AST.OpenAcc $ AST.Alet+            lhs+            bound+            (convertSharingAcc config alyt' (sa:aenv') bodyAcc)+  where+    aenv' = lams ++ aenv+    bound = convertSharingAcc config alyt aenv' (ScopedAcc [] boundAcc)++convertSharingAcc config alyt aenv (ScopedAcc lams (AccSharing _ preAcc))+  = AST.OpenAcc+  $ let aenv' = lams ++ aenv++        cvtA :: ScopedAcc a -> AST.OpenAcc aenv a+        cvtA = convertSharingAcc config alyt aenv'++        cvtE :: ScopedExp t -> AST.Exp aenv t+        cvtE = convertSharingExp config EmptyLayout alyt [] aenv'++        cvtF1 :: TypeR a -> (SmartExp a -> ScopedExp b) -> AST.Fun aenv (a -> b)+        cvtF1 = convertSharingFun1 config alyt aenv'++        cvtF2 :: TypeR a -> TypeR b -> (SmartExp a -> SmartExp b -> ScopedExp c) -> AST.Fun aenv (a -> b -> c)+        cvtF2 = convertSharingFun2 config alyt aenv'++        cvtAfun1 :: ArraysR a -> (SmartAcc a -> ScopedAcc b) -> AST.OpenAfun aenv (a -> b)+        cvtAfun1 = convertSharingAfun1 config alyt aenv'++        cvtAprj :: forall a b c. PairIdx (a, b) c -> ScopedAcc (a, b) -> AST.OpenAcc aenv c+        cvtAprj ix a = cvtAprj' ix $ cvtA a++        cvtAprj' :: forall a b c aenv1. PairIdx (a, b) c -> AST.OpenAcc aenv1 (a, b) -> AST.OpenAcc aenv1 c+        cvtAprj' PairIdxLeft  (AST.OpenAcc (AST.Apair a _)) = a+        cvtAprj' PairIdxRight (AST.OpenAcc (AST.Apair _ b)) = b+        cvtAprj' ix a = case declareVars $ AST.arraysR a of+          DeclareVars lhs _ value ->+            AST.OpenAcc $ AST.Alet lhs a $ cvtAprj' ix $ avarsIn AST.OpenAcc $ value weakenId+    in+    case preAcc of++      Atag repr i+        -> let AST.OpenAcc a = avarsIn AST.OpenAcc $ prjIdx ("de Bruijn conversion tag " ++ show i) showArraysR matchArraysR repr i alyt+           in  a++      Pipe reprA reprB reprC (afun1 :: SmartAcc as -> ScopedAcc bs) (afun2 :: SmartAcc bs -> ScopedAcc cs) acc+        | DeclareVars lhs k value <- declareVars reprB ->+          let+            noStableSharing = StableSharingAcc noStableAccName (undefined :: SharingAcc acc exp ())+            boundAcc = AST.Apply reprB (cvtAfun1 reprA afun1) (cvtA acc)+            alyt'   = PushLayout (incLayout k alyt) lhs (value weakenId)+            bodyAcc = AST.Apply reprC+                        (convertSharingAfun1 config alyt' (noStableSharing : aenv') reprB afun2)+                        (avarsIn AST.OpenAcc $ value weakenId)+          in AST.Alet lhs (AST.OpenAcc boundAcc) (AST.OpenAcc bodyAcc)++      Aforeign repr ff afun acc+        -> AST.Aforeign repr ff (convertSmartAfun1 config (Smart.arraysR acc) afun) (cvtA acc)++      Acond b acc1 acc2           -> AST.Acond (cvtE b) (cvtA acc1) (cvtA acc2)+      Awhile reprA pred iter init -> AST.Awhile (cvtAfun1 reprA pred) (cvtAfun1 reprA iter) (cvtA init)+      Anil                        -> AST.Anil+      Apair acc1 acc2             -> AST.Apair (cvtA acc1) (cvtA acc2)+      Aprj ix a                   -> let AST.OpenAcc a' = cvtAprj ix a+                                     in a'+      Use repr array              -> AST.Use repr array+      Unit tp e                   -> AST.Unit tp (cvtE e)+      Generate repr@(ArrayR shr _) sh f+                                  -> AST.Generate repr (cvtE sh) (cvtF1 (shapeType shr) f)+      Reshape shr e acc           -> AST.Reshape shr (cvtE e) (cvtA acc)+      Replicate si ix acc         -> AST.Replicate si (cvtE ix) (cvtA acc)+      Slice si acc ix             -> AST.Slice si (cvtA acc) (cvtE ix)+      Map t1 t2 f acc             -> AST.Map t2 (cvtF1 t1 f) (cvtA acc)+      ZipWith t1 t2 t3 f acc1 acc2+                                  -> AST.ZipWith t3 (cvtF2 t1 t2 f) (cvtA acc1) (cvtA acc2)+      Fold tp f e acc             -> AST.Fold (cvtF2 tp tp f) (cvtE <$> e) (cvtA acc)+      FoldSeg i tp f e acc1 acc2  -> AST.FoldSeg i (cvtF2 tp tp f) (cvtE <$> e) (cvtA acc1) (cvtA acc2)+      Scan  d tp f e acc          -> AST.Scan  d (cvtF2 tp tp f) (cvtE <$> e) (cvtA acc)+      Scan' d tp f e acc          -> AST.Scan' d (cvtF2 tp tp f) (cvtE e)     (cvtA acc)+      Permute (ArrayR shr tp) f dftAcc perm acc+                                  -> AST.Permute (cvtF2 tp tp f) (cvtA dftAcc) (cvtF1 (shapeType shr) perm) (cvtA acc)+      Backpermute shr newDim perm acc+                                  -> AST.Backpermute shr (cvtE newDim) (cvtF1 (shapeType shr) perm) (cvtA acc)+      Stencil stencil tp f boundary acc+        -> AST.Stencil stencil+                       tp+                       (convertSharingStencilFun1 config alyt aenv' stencil f)+                       (convertSharingBoundary config alyt aenv' (stencilShapeR stencil) boundary)+                       (cvtA acc)+      Stencil2 stencil1 stencil2 tp f bndy1 acc1 bndy2 acc2+        | shr <- stencilShapeR stencil1+        -> AST.Stencil2 stencil1+                        stencil2+                        tp+                        (convertSharingStencilFun2 config alyt aenv' stencil1 stencil2 f)+                        (convertSharingBoundary config alyt aenv' shr bndy1)+                        (cvtA acc1)+                        (convertSharingBoundary config alyt aenv' shr 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 :: (HasCallStack, 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. HasCallStack+    => Config+    -> ArrayLayout aenv aenv+    -> [StableSharingAcc]+    -> ArraysR a+    -> (SmartAcc a -> ScopedAcc b)+    -> OpenAfun aenv (a -> b)+convertSharingAfun1 config alyt aenv reprA f+  | DeclareVars lhs k value <- declareVars reprA+  = let+      alyt' = PushLayout (incLayout k alyt) lhs (value weakenId)+      body = f undefined+    in+      Alam lhs (Abody (convertSharingAcc config alyt' aenv body))++-- | Convert a boundary condition+--+convertSharingBoundary+    :: forall aenv sh e. HasCallStack+    => Config+    -> ArrayLayout aenv aenv+    -> [StableSharingAcc]+    -> ShapeR sh+    -> PreBoundary ScopedAcc ScopedExp (Array sh e)+    -> AST.Boundary aenv (Array sh e)+convertSharingBoundary config alyt aenv shr = cvt+  where+    cvt :: PreBoundary ScopedAcc ScopedExp (Array sh e) -> AST.Boundary aenv (Array sh e)+    cvt bndy =+      case bndy of+        Clamp       -> AST.Clamp+        Mirror      -> AST.Mirror+        Wrap        -> AST.Wrap+        Constant v  -> AST.Constant v+        Function f  -> AST.Function $ convertSharingFun1 config alyt aenv (shapeType shr) f+++-- 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+-- ----------------++-- | Convert a closed scalar function to de Bruijn form while incorporating+-- sharing information.+--+-- The current design requires all free variables to be bound at the outermost+-- level --- we have no general apply term, and so lambdas are always outermost.+-- In higher-order abstract syntax, this represents an n-ary, polyvariadic+-- function.+--+convertFun :: (HasCallStack, Function f) => f -> AST.Fun () (EltFunctionR f)+convertFun+  = convertFunWith+  $ defaultOptions { options = options defaultOptions \\ [seq_sharing, acc_sharing] }++convertFunWith :: (HasCallStack, Function f) => Config -> f -> AST.Fun () (EltFunctionR f)+convertFunWith config = convertOpenFun config EmptyLayout++data FunctionRepr f r reprr where+  FunctionReprBody+    :: Elt b => FunctionRepr (Exp b) b (EltR b)++  FunctionReprLam+    :: Elt a+    => FunctionRepr b br breprr+    -> FunctionRepr (Exp a -> b) (a -> br) (EltR a -> breprr)++class Function f where+  type FunctionR f+  type EltFunctionR f++  functionRepr   :: HasCallStack => FunctionRepr f (FunctionR f) (EltFunctionR f)+  convertOpenFun :: HasCallStack => Config -> ELayout env env -> f -> AST.OpenFun env () (EltFunctionR f)++instance (Elt a, Function r) => Function (Exp a -> r) where+  type FunctionR (Exp a -> r) = a -> FunctionR r+  type EltFunctionR (Exp a -> r) = EltR a -> EltFunctionR r++  functionRepr = FunctionReprLam $ functionRepr @r+  convertOpenFun config lyt f+    | tp <- eltR @a+    , DeclareVars lhs k value <- declareVars tp+    = let+        e    = Exp $ SmartExp $ Tag tp $ sizeLayout lyt+        lyt' = PushLayout (incLayout k lyt) lhs (value weakenId)+      in+        Lam lhs $ convertOpenFun config lyt' $ f e++instance Elt b => Function (Exp b) where+  type FunctionR (Exp b) = b+  type EltFunctionR (Exp b) = EltR b++  functionRepr = FunctionReprBody+  convertOpenFun config lyt (Exp body) = Body $ convertOpenExp config lyt body++convertSmartFun+    :: HasCallStack+    => Config+    -> TypeR a+    -> (SmartExp a -> SmartExp b)+    -> AST.Fun () (a -> b)+convertSmartFun config tp f+  | DeclareVars lhs _ value <- declareVars tp+  = let+      e    = SmartExp $ Tag tp 0+      lyt' = PushLayout EmptyLayout lhs (value weakenId)+    in+      Lam lhs $ Body $ convertOpenExp config lyt' $ f e++-- Scalar expressions+-- ------------------++-- | Convert a closed scalar expression to de Bruijn form while incorporating+-- sharing information.+--+convertExp+    :: HasCallStack+    => Exp e+    -> AST.Exp () (EltR e)+convertExp+  = convertExpWith+  $ defaultOptions { options = options defaultOptions \\ [seq_sharing, acc_sharing] }++convertExpWith+      :: HasCallStack+      => Config+      -> Exp e+      -> AST.Exp () (EltR e)+convertExpWith config (Exp e) = convertOpenExp config EmptyLayout e++convertOpenExp+    :: HasCallStack+    => Config+    -> ELayout env env+    -> SmartExp e+    -> AST.OpenExp env () e+convertOpenExp config lyt exp =+  let lvl                      = sizeLayout lyt+      fvs                      = [lvl-1, lvl-2 .. 0]+      (sharingExp, initialEnv) = recoverSharingExp config lvl fvs exp+  in+  convertSharingExp config lyt EmptyLayout initialEnv [] sharingExp+++-- | Convert an open expression with given environment layouts and sharing information into+-- de Bruijn form while recovering sharing at the same time (by introducing appropriate let+-- bindings).  The latter implements the third phase of sharing recovery.+--+-- The sharing environments 'env' and 'aenv' keep track of all currently bound sharing variables,+-- keeping them in reverse chronological order (outermost variable is at the end of the list).+--+convertSharingExp+    :: forall t env aenv. HasCallStack+    => Config+    -> ELayout env env          -- scalar environment+    -> ArrayLayout aenv aenv    -- array environment+    -> [StableSharingExp]       -- currently bound sharing variables of expressions+    -> [StableSharingAcc]       -- currently bound sharing variables of array computations+    -> ScopedExp t              -- expression to be converted+    -> AST.OpenExp env aenv t+convertSharingExp config lyt alyt env aenv exp@(ScopedExp lams _) = cvt exp+  where+    -- scalar environment with any lambda bound variables this expression is rooted in+    env' = lams ++ env++    cvt :: HasCallStack => ScopedExp t' -> AST.OpenExp env aenv t'+    cvt (ScopedExp _ (VarSharing se tp))+      | Just i <- findIndex (matchStableExp se) env' = expVars (prjIdx (ctx i) shows matchTypeR tp i lyt)+      | otherwise                                    = internalError msg+      where+        ctx i = printf "shared 'Exp' tree with stable name %d; i=%d" (hashStableNameHeight se) i+        msg   = unlines+          [ if null env'+               then printf "cyclic definition of a value of type 'Exp' (sa=%d)" (hashStableNameHeight se)+               else printf "inconsistent valuation at shared 'Exp' tree (sa=%d; env=%s)" (hashStableNameHeight se) (show env')+          , ""+          , "Note that this error usually arises due to the presence of nested data"+          , "parallelism; when a parallel computation attempts to initiate new parallel"+          , "work _which depends on_ a scalar variable given by the first computation."+          , ""+          , "For example, suppose we wish to sum the columns of a two-dimensional array."+          , "You might think to do this in the following (incorrect) way: by constructing"+          , "a vector using 'generate' where at each index we 'slice' out the"+          , "corresponding column of the matrix and 'sum' it:"+          , ""+          , "> sum_columns_ndp :: Num a => Acc (Matrix a) -> Acc (Vector a)"+          , "> sum_columns_ndp mat ="+          , ">   let I2 rows cols = shape mat"+          , ">   in  generate (I1 cols)"+          , ">                (\\(I1 col) -> the $ sum (slice mat (lift (Z :. All :. col))))"+          , ""+          , "However, since both 'generate' and 'slice' are data-parallel operators, and"+          , "moreover that 'slice' _depends on_ the argument 'col' given to it by the"+          , "'generate' function, this operation requires nested parallelism and is thus"+          , "not (at this time) permitted. The clue that this definition is invalid is"+          , "that in order to create a program which will be accepted by the type checker,"+          , "we had to use the function 'the' to retrieve the result of the parallel"+          , "'sum', effectively concealing that this is a collective operation in order to"+          , "match the type expected by 'generate'."+          , ""+          , "To solve this particular example, we can make use of the fact that (most)"+          , "collective operations in Accelerate are _rank polymorphic_. The 'sum'"+          , "operation reduces along the innermost dimension of an array of arbitrary"+          , "rank, reducing the dimensionality of the array by one. To reduce the array"+          , "column-wise then, we first need to simply 'transpose' the array:"+          , ""+          , "> sum_columns :: Num a => Acc (Matrix a) -> Acc (Vector a)"+          , "> sum_columns = sum . transpose"+          , ""+          , "If you feel like this is not the cause of your error, or you would like some"+          , "advice locating the problem and perhaps with a workaround, feel free to"+          , "submit an issue at the above URL."+          ]++    cvt (ScopedExp _ (LetSharing se@(StableSharingExp _ boundExp) bodyExp))+      | DeclareVars lhs k value <- declareVars $ typeR boundExp+      = let+          lyt' = PushLayout (incLayout k lyt) lhs (value weakenId)+        in+          AST.Let lhs (cvt (ScopedExp [] boundExp)) (convertSharingExp config lyt' alyt (se:env') aenv bodyExp)+    cvt (ScopedExp _ (ExpSharing _ pexp))+      = case pexp of+          Tag tp i              -> expVars $ prjIdx ("de Bruijn conversion tag " ++ show i) shows matchTypeR tp i lyt+          Match _ e             -> cvt e  -- XXX: this should probably be an error+          Const tp v            -> AST.Const tp v+          Undef tp              -> AST.Undef tp+          Prj idx e             -> cvtPrj idx (cvt e)+          Nil                   -> AST.Nil+          Pair e1 e2            -> AST.Pair (cvt e1) (cvt e2)+          VecPack   vec e       -> AST.VecPack   vec (cvt e)+          VecUnpack vec e       -> AST.VecUnpack vec (cvt e)+          ToIndex shr sh ix     -> AST.ToIndex shr (cvt sh) (cvt ix)+          FromIndex shr sh e    -> AST.FromIndex shr (cvt sh) (cvt e)+          Case e rhs            -> cvtCase (cvt e) (over (mapped . _2) cvt rhs)+          Cond e1 e2 e3         -> AST.Cond (cvt e1) (cvt e2) (cvt e3)+          While tp p it i       -> AST.While (cvtFun1 tp p) (cvtFun1 tp it) (cvt i)+          PrimConst c           -> AST.PrimConst c+          PrimApp f e           -> cvtPrimFun f (cvt e)+          Index _ a e           -> AST.Index (cvtAvar a) (cvt e)+          LinearIndex _ a i     -> AST.LinearIndex (cvtAvar a) (cvt i)+          Shape _ a             -> AST.Shape (cvtAvar a)+          ShapeSize shr e       -> AST.ShapeSize shr (cvt e)+          Foreign repr ff f e   -> AST.Foreign repr ff (convertSmartFun config (typeR e) f) (cvt e)+          Coerce t1 t2 e        -> AST.Coerce t1 t2 (cvt e)++    cvtPrj :: forall a b c env1 aenv1. PairIdx (a, b) c -> AST.OpenExp env1 aenv1 (a, b) -> AST.OpenExp env1 aenv1 c+    cvtPrj PairIdxLeft  (AST.Pair a _) = a+    cvtPrj PairIdxRight (AST.Pair _ b) = b+    cvtPrj ix a+      | DeclareVars lhs _ value <- declareVars $ AST.expType a+      = AST.Let lhs a (cvtPrj ix (expVars (value weakenId)))++    cvtA :: HasCallStack => ScopedAcc a -> AST.OpenAcc aenv a+    cvtA = convertSharingAcc config alyt aenv++    cvtAvar :: HasCallStack => ScopedAcc a -> AST.ArrayVar aenv a+    cvtAvar a = case cvtA a of+      AST.OpenAcc (AST.Avar var) -> var+      _                          -> internalError "Expected array computation in expression to be floated out"++    cvtFun1 :: HasCallStack => TypeR a -> (SmartExp a -> ScopedExp b) -> AST.OpenFun env aenv (a -> b)+    cvtFun1 tp f+      | DeclareVars lhs k value <- declareVars tp+      = let+          lyt' = PushLayout (incLayout k lyt) lhs (value weakenId)+          body = f undefined+        in+          Lam lhs $ Body $ convertSharingExp config lyt' alyt env' aenv body++    -- Push primitive function applications down through let bindings so that+    -- they are adjacent to their arguments. It looks a bit nicer this way.+    --+    cvtPrimFun :: HasCallStack => AST.PrimFun (a -> r) -> AST.OpenExp env' aenv' a -> AST.OpenExp env' aenv' r+    cvtPrimFun f e = case e of+      AST.Let lhs bnd body -> AST.Let lhs bnd (cvtPrimFun f body)+      x                    -> AST.PrimApp f x++    -- Convert the flat list of equations into nested case statement+    -- directly on the tag variables.+    --+    cvtCase :: HasCallStack => AST.OpenExp env' aenv' a -> [(TagR a, AST.OpenExp env' aenv' b)] -> AST.OpenExp env' aenv' b+    cvtCase s es+      | AST.Pair{} <- s+      = nested s es+      | DeclareVars lhs _ value <- declareVars (AST.expType s)+      = AST.Let lhs s $ nested (expVars (value weakenId)) (over (mapped . _2) (weakenE (weakenWithLHS lhs)) es)+      where+        nested :: HasCallStack => AST.OpenExp env' aenv' a -> [(TagR a, AST.OpenExp env' aenv' b)] -> AST.OpenExp env' aenv' b+        nested _ [(_,r)] = r+        nested s rs      =+          let groups = groupBy (eqT `on` fst) rs+              tags   = map (firstT . fst . head) groups+              e      = prjT (fst (head rs)) s+              rhs    = map (nested s . map (over _1 ignore)) groups+          in+          AST.Case e (zip tags rhs) Nothing++        -- Extract the variable representing this particular tag from the+        -- scrutinee. This is safe because we let-bind the argument first.+        prjT :: TagR a -> AST.OpenExp env' aenv' a -> AST.OpenExp env' aenv' TAG+        prjT = fromJust $$ go+          where+            go :: TagR a -> AST.OpenExp env' aenv' a -> Maybe (AST.OpenExp env' aenv' TAG)+            go TagRtag{}        (AST.Pair l _) = Just l+            go (TagRpair ta tb) (AST.Pair l r) =+              case go ta l of+                Just t  -> Just t+                Nothing -> go tb r+            go _ _ = Nothing++        -- Equality up to the first constructor tag encountered+        eqT :: TagR a -> TagR a -> Bool+        eqT a b = snd $ go a b+          where+            go :: TagR a -> TagR a -> (Any, Bool)+            go TagRunit          TagRunit          = no True+            go TagRsingle{}      TagRsingle{}      = no True+            go TagRundef{}       TagRundef{}       = no True+            go (TagRtag v1 _)    (TagRtag v2 _)    = yes (v1 == v2)+            go (TagRpair a1 b1)  (TagRpair a2 b2)  =+              let (Any r, s) = go a1 a2+               in case r of+                    True  -> yes s+                    False -> go b1 b2+            go _ _ = no False++        firstT :: TagR a -> TAG+        firstT = fromJust . go+          where+            go :: TagR a -> Maybe TAG+            go (TagRtag v _)  = Just v+            go (TagRpair a b) =+              case go a of+                Just t  -> Just t+                Nothing -> go b+            go _ = Nothing++        -- Replace the first constructor tag encountered with a regular+        -- scalar tag, so that that tag will be ignored in the recursive+        -- case.+        ignore = snd . go+          where+            go :: TagR a -> (Any, TagR a)+            go TagRunit         = no  $ TagRunit+            go (TagRsingle t)   = no  $ TagRsingle t+            go (TagRundef t)    = no  $ TagRundef t+            go (TagRtag _ a)    = yes $ TagRpair (TagRundef scalarType) a+            go (TagRpair a1 a2) =+              let (Any r, a1') = go a1+               in case r of+                    True  -> yes $ TagRpair a1' a2+                    False -> TagRpair a1' <$> go a2++        yes :: x -> (Any, x)+        yes e = (Any True, e)++        no :: x -> (Any, x)+        no = pure+++-- | Convert a unary functions+--+convertSharingFun1+    :: HasCallStack+    => Config+    -> ArrayLayout aenv aenv+    -> [StableSharingAcc]       -- currently bound array sharing-variables+    -> TypeR a+    -> (SmartExp a -> ScopedExp b)+    -> AST.Fun aenv (a -> b)+convertSharingFun1 config alyt aenv tp f+  | DeclareVars lhs _ value <- declareVars tp+  = let+      a               = SmartExp undefined             -- the 'tag' was already embedded in Phase 1+      lyt             = PushLayout EmptyLayout lhs (value weakenId)+      openF           = convertSharingExp config lyt alyt [] aenv (f a)+    in+      Lam lhs (Body openF)++-- | Convert a binary functions+--+convertSharingFun2+    :: HasCallStack+    => Config+    -> ArrayLayout aenv aenv+    -> [StableSharingAcc]       -- currently bound array sharing-variables+    -> TypeR a+    -> TypeR b+    -> (SmartExp a -> SmartExp b -> ScopedExp c)+    -> AST.Fun aenv (a -> b -> c)+convertSharingFun2 config alyt aenv ta tb f+  | DeclareVars lhs1 _  value1 <- declareVars ta+  , DeclareVars lhs2 k2 value2 <- declareVars tb+  = let+      a               = SmartExp undefined+      b               = SmartExp undefined+      lyt1            = PushLayout EmptyLayout lhs1 (value1 k2)+      lyt2            = PushLayout lyt1        lhs2 (value2 weakenId)+      openF           = convertSharingExp config lyt2 alyt [] aenv (f a b)+    in+      Lam lhs1 $ Lam lhs2 $ Body openF++-- | Convert a unary stencil function+--+convertSharingStencilFun1+    :: HasCallStack+    => Config+    -> ArrayLayout aenv aenv+    -> [StableSharingAcc]               -- currently bound array sharing-variables+    -> R.StencilR sh a stencil+    -> (SmartExp stencil -> ScopedExp b)+    -> AST.Fun aenv (stencil -> b)+convertSharingStencilFun1 config alyt aenv sR1 stencil =+  convertSharingFun1 config alyt aenv (R.stencilR sR1) stencil++-- | Convert a binary stencil function+--+convertSharingStencilFun2+    :: HasCallStack+    => Config+    -> ArrayLayout aenv aenv+    -> [StableSharingAcc]               -- currently bound array sharing-variables+    -> R.StencilR sh a stencil1+    -> R.StencilR sh b stencil2+    -> (SmartExp stencil1 -> SmartExp stencil2 -> ScopedExp c)+    -> AST.Fun aenv (stencil1 -> stencil2 -> c)+convertSharingStencilFun2 config alyt aenv sR1 sR2 stencil =+  convertSharingFun2 config alyt aenv (R.stencilR sR1) (R.stencilR sR2) stencil+++-- Sharing recovery+-- ================++-- Sharing recovery proceeds in two phases:+--+-- /Phase One: build the occurrence map/+--+-- This is a top-down traversal of the AST that computes a map from AST nodes to the number of+-- occurrences of that AST node in the overall Accelerate program.  An occurrences count of two or+-- more indicates sharing.+--+-- IMPORTANT: To avoid unfolding the sharing, we do not descent into subtrees that we have+--   previously encountered.  Hence, the complexity is proportional to the number of nodes in the+--   tree /with/ sharing.  Consequently, the occurrence count is that in the tree with sharing+--   as well.+--+-- During computation of the occurrences, the tree is annotated with stable names on every node+-- using 'AccSharing' constructors and all but the first occurrence of shared subtrees are pruned+-- using 'AvarSharing' constructors (see 'SharingAcc' below).  This phase is impure as it is based+-- on stable names.+--+-- We use a hash table (instead of 'Data.Map') as computing stable names forces us to live in IO+-- anyway.  Once, the computation of occurrence counts is complete, we freeze the hash table into+-- a 'Data.Map'.+--+-- (Implemented by 'makeOccMap*'.)+--+-- /Phase Two: determine scopes and inject sharing information/+--+-- This is a bottom-up traversal that determines the scope for every binding to be introduced+-- to share a subterm.  It uses the occurrence map to determine, for every shared subtree, the+-- lowest AST node at which the binding for that shared subtree can be placed (using a+-- 'AletSharing' constructor)— it's the meet of all the shared subtree occurrences.+--+-- The second phase is also replacing the first occurrence of each shared subtree with a+-- 'AvarSharing' node and floats the shared subtree up to its binding point.+--+--  (Implemented by 'determineScopes*'.)+--+-- /Sharing recovery for expressions/+--+-- We recover sharing for each expression (including function bodies) independently of any other+-- expression — i.e., we cannot share scalar expressions across array computations.  Hence, during+-- Phase One, we mark all scalar expression nodes with a stable name and compute one occurrence map+-- for every scalar expression (including functions) that occurs in an array computation.  These+-- occurrence maps are added to the root of scalar expressions using 'RootExp'.+--+-- NB: We do not need to worry sharing recovery will try to float a shared subexpression past a+--     binder that occurs in that subexpression.  Why?  Otherwise, the binder would already occur+--     out of scope in the original source program.+--+-- /Lambda bound variables/+--+-- During sharing recovery, lambda bound variables appear in the form of 'Atag' and 'Tag' data+-- constructors.  The tag values are determined during Phase One of sharing recovery by computing+-- the /level/ of each variable at its binding occurrence.  The level at the root of the AST is 0+-- and increases by one with each lambda on each path through the AST.++-- Stable names+-- ------------++-- Opaque stable name for AST nodes — used to key the occurrence map.+--+data StableASTName c where+  StableASTName :: StableName (c t) -> StableASTName c++instance Show (StableASTName c) where+  show (StableASTName sn) = show $ hashStableName sn++instance Eq (StableASTName c) where+  StableASTName sn1 == StableASTName sn2 = eqStableName sn1 sn2++instance Hashable (StableASTName c) where+  hashWithSalt s (StableASTName sn) = hashWithSalt s sn++makeStableAST :: c t -> IO (StableName (c t))+makeStableAST e = e `seq` makeStableName e++-- Stable name for an AST node including the height of the AST representing the array computation.+--+data StableNameHeight t = StableNameHeight (StableName t) Int++instance Eq (StableNameHeight t) where+  (StableNameHeight sn1 _) == (StableNameHeight sn2 _) = eqStableName sn1 sn2++higherSNH :: StableNameHeight t1 -> StableNameHeight t2 -> Bool+StableNameHeight _ h1 `higherSNH` StableNameHeight _ h2 = h1 > h2++hashStableNameHeight :: StableNameHeight t -> Int+hashStableNameHeight (StableNameHeight sn _) = hashStableName sn++-- Mutable occurrence map+-- ----------------------++-- Hash table keyed on the stable names of array computations.+--+type HashTable key val = Hash.BasicHashTable key val+type ASTHashTable c v  = HashTable (StableASTName c) v++-- Mutable hashtable version of the occurrence map, which associates each AST node with an+-- occurrence count and the height of the AST.+--+type OccMapHash c = ASTHashTable c (Int, Int)++-- Create a new hash table keyed on AST nodes.+--+newASTHashTable :: IO (ASTHashTable c v)+newASTHashTable = Hash.new++-- Enter one AST node occurrence into an occurrence map.  Returns 'Just h' if this is a repeated+-- occurrence and the height of the repeatedly occurring AST is 'h'.+--+-- If this is the first occurrence, the 'height' *argument* must provide the height of the AST;+-- otherwise, the height will be *extracted* from the occurrence map.  In the latter case, this+-- function yields the AST height.+--+enterOcc :: OccMapHash c -> StableASTName c -> Int -> IO (Maybe Int)+enterOcc occMap sa height+  = Hash.mutate occMap sa+  $ \case+      Nothing           -> (Just (1,   height),  Nothing)+      Just (n, heightS) -> (Just (n+1, heightS), Just heightS)+++-- Immutable occurrence map+-- ------------------------++-- Immutable version of the occurrence map (storing the occurrence count only, not the height).  We+-- use the 'StableName' hash to index an 'IntMap' and disambiguate 'StableName's with identical+-- hashes explicitly, storing them in a list in the 'IntMap'.+--+type OccMap c = IntMap.IntMap [(StableASTName c, Int)]++-- Turn a mutable into an immutable occurrence map.+--+freezeOccMap :: OccMapHash c -> IO (OccMap c)+freezeOccMap oc+  = do+      ocl <- Hash.toList oc+      traceChunk "OccMap" (show ocl)++      return . IntMap.fromList+             . map (\kvs -> (key (head kvs), kvs))+             . groupBy sameKey+             . map dropHeight+             $ ocl+  where+    key (StableASTName sn, _) = hashStableName sn+    sameKey kv1 kv2           = key kv1 == key kv2+    dropHeight (k, (cnt, _))  = (k, cnt)++-- Look up the occurrence map keyed by array computations using a stable name.  If the key does+-- not exist in the map, return an occurrence count of '1'.+--+lookupWithASTName :: OccMap c -> StableASTName c -> Int+lookupWithASTName oc sa@(StableASTName sn)+  = fromMaybe 1 $ IntMap.lookup (hashStableName sn) oc >>= Prelude.lookup sa++-- Look up the occurrence map keyed by array computations using a sharing array computation.  If an+-- the key does not exist in the map, return an occurrence count of '1'.+--+lookupWithSharingAcc :: OccMap SmartAcc -> StableSharingAcc -> Int+lookupWithSharingAcc oc (StableSharingAcc (StableNameHeight sn _) _)+  = lookupWithASTName oc (StableASTName sn)++-- Look up the occurrence map keyed by scalar expressions using a sharing expression.  If an+-- the key does not exist in the map, return an occurrence count of '1'.+--+lookupWithSharingExp :: OccMap SmartExp -> StableSharingExp -> Int+lookupWithSharingExp oc (StableSharingExp (StableNameHeight sn _) _)+  = lookupWithASTName oc (StableASTName sn)+++-- Stable 'SmartAcc' nodes+-- ------------------++-- Stable name for 'SmartAcc' nodes including the height of the AST.+--+type StableAccName t = StableNameHeight (SmartAcc t)++-- Interleave sharing annotations into an array computation AST.  Subtrees can be marked as being+-- represented by variable (binding a shared subtree) using 'AvarSharing' and as being prefixed by+-- a let binding (for a shared subtree) using 'AletSharing'.+--+data SharingAcc acc exp arrs where+  AvarSharing :: StableAccName arrs -> ArraysR arrs             -> SharingAcc acc exp arrs+  AletSharing :: StableSharingAcc -> acc arrs                   -> SharingAcc acc exp arrs+  AccSharing  :: StableAccName arrs -> PreSmartAcc acc exp arrs -> SharingAcc acc exp arrs++instance HasArraysR acc => HasArraysR (SharingAcc acc exp) where+  arraysR (AvarSharing _ repr) = repr+  arraysR (AletSharing _ acc)  = Smart.arraysR acc+  arraysR (AccSharing  _ acc)  = Smart.arraysR acc+++-- 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 UnscopedAcc t = UnscopedAcc [Int] (SharingAcc UnscopedAcc RootExp t)++instance HasArraysR UnscopedAcc where+  arraysR (UnscopedAcc _ acc) = Smart.arraysR acc+++-- 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 ScopedAcc t = ScopedAcc [StableSharingAcc] (SharingAcc ScopedAcc ScopedExp t)++instance HasArraysR ScopedAcc where+  arraysR (ScopedAcc _ acc) = Smart.arraysR acc+++-- Stable name for an array computation associated with its sharing-annotated version.+--+data StableSharingAcc where+  StableSharingAcc :: StableAccName arrs+                   -> SharingAcc ScopedAcc ScopedExp arrs+                   -> StableSharingAcc++instance Show StableSharingAcc where+  show (StableSharingAcc sn _) = show $ hashStableNameHeight sn++instance Eq StableSharingAcc where+  StableSharingAcc (StableNameHeight sn1 _) _ == StableSharingAcc (StableNameHeight sn2 _) _+    = eqStableName sn1 sn2++higherSSA :: StableSharingAcc -> StableSharingAcc -> Bool+StableSharingAcc sn1 _ `higherSSA` StableSharingAcc sn2 _ = sn1 `higherSNH` sn2++-- Test whether the given stable names matches an array computation with sharing.+--+matchStableAcc :: StableAccName arrs -> StableSharingAcc -> Bool+matchStableAcc (StableNameHeight sn1 _) (StableSharingAcc (StableNameHeight sn2 _) _)+  = eqStableName sn1 sn2++-- Dummy entry for environments to be used for unused variables.+--+{-# NOINLINE noStableAccName #-}+noStableAccName :: StableAccName arrs+noStableAccName = unsafePerformIO $ StableNameHeight <$> makeStableName undefined <*> pure 0++-- Stable 'Exp' nodes+-- ------------------++-- Stable name for 'Exp' nodes including the height of the AST.+--+type StableExpName t = StableNameHeight (SmartExp t)++-- Interleave sharing annotations into a scalar expressions AST in the same manner as 'SharingAcc'+-- do for array computations.+--+data SharingExp acc exp t where+  VarSharing :: StableExpName t -> TypeR t               -> SharingExp acc exp t+  LetSharing :: StableSharingExp -> exp t                -> SharingExp acc exp t+  ExpSharing :: StableExpName t -> PreSmartExp acc exp t -> SharingExp acc exp t++instance HasTypeR exp => HasTypeR (SharingExp acc exp) where+  typeR (VarSharing _ tp)  = tp+  typeR (LetSharing _ exp) = Smart.typeR exp+  typeR (ExpSharing _ exp) = Smart.typeR exp++-- Specifies a scalar expression AST with sharing annotations but no scoping; i.e. no LetSharing+-- constructors. If the expression is rooted in a function, the list contains the tags of the+-- variables bound by the immediate surrounding lambdas.+data UnscopedExp t = UnscopedExp [Int] (SharingExp UnscopedAcc UnscopedExp t)++instance HasTypeR UnscopedExp where+  typeR (UnscopedExp _ exp) = Smart.typeR exp++-- Specifies a scalar expression AST with sharing. For expressions rooted in functions the list+-- holds a sorted environment corresponding to the variables bound in the immediate surounding+-- lambdas.+data ScopedExp t = ScopedExp [StableSharingExp] (SharingExp ScopedAcc ScopedExp t)++instance HasTypeR ScopedExp where+  typeR (ScopedExp _ exp) = Smart.typeR exp++-- Expressions rooted in 'SmartAcc' computations.+--+-- * When counting occurrences, the root of every expression embedded in an 'SmartAcc' is annotated by+--   an occurrence map for that one expression (excluding any subterms that are rooted in embedded+--   'SmartAcc's.)+--+data RootExp t = RootExp (OccMap SmartExp) (UnscopedExp t)++-- Stable name for an expression associated with its sharing-annotated version.+--+data StableSharingExp where+  StableSharingExp :: StableExpName t -> SharingExp ScopedAcc ScopedExp t -> StableSharingExp++instance Show StableSharingExp where+  show (StableSharingExp sn _) = show $ hashStableNameHeight sn++instance Eq StableSharingExp where+  StableSharingExp (StableNameHeight sn1 _) _ == StableSharingExp (StableNameHeight sn2 _) _ =+    eqStableName sn1 sn2++higherSSE :: StableSharingExp -> StableSharingExp -> Bool+StableSharingExp sn1 _ `higherSSE` StableSharingExp sn2 _ = sn1 `higherSNH` sn2++-- Test whether the given stable names matches an expression with sharing.+--+matchStableExp :: StableExpName t -> StableSharingExp -> Bool+matchStableExp (StableNameHeight sn1 _) (StableSharingExp (StableNameHeight sn2 _) _) = eqStableName sn1 sn2++-- Dummy entry for environments to be used for unused variables.+--+{-# NOINLINE noStableExpName #-}+noStableExpName :: StableExpName t+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 'SmartAcc' occurrence map, marks all nodes (both 'Seq' and 'Exp' nodes) with stable names,+-- and drop repeated occurrences of shared 'SmartAcc' and 'Exp' subtrees (Phase One).+--+-- We compute a single 'SmartAcc' occurrence map for the whole AST, but one 'Exp' occurrence map for each+-- sub-expression rooted in an 'SmartAcc' operation.  This is as we cannot float 'Exp' subtrees across+-- 'SmartAcc' operations, but we can float 'SmartAcc' subtrees out of 'Exp' expressions.+--+-- Note [Traversing functions and side effects]+-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+-- We need to descent into function bodies to build the 'OccMap' with all occurrences in the+-- function bodies.  Due to the side effects in the construction of the occurrence map and, more+-- importantly, the dependence of the second phase on /global/ occurrence information, we may not+-- delay the body traversals by putting them under a lambda.  Hence, we apply each function, to+-- traverse its body and use a /dummy abstraction/ of the result.+--+-- For example, given a function 'f', we traverse 'f (Tag 0)', which yields a transformed body 'e'.+-- As the result of the traversal of the overall function, we use 'const e'.  Hence, it is crucial+-- that the 'Tag' supplied during the initial traversal is already the one required by the HOAS to+-- de Bruijn conversion in 'convertSharingAcc' — any subsequent application of 'const e' will only+-- yield 'e' with the embedded 'Tag 0' of the original application.  During sharing recovery, we+-- float /all/ free variables ('Atag' and 'Tag') out to construct the initial environment for+-- producing de Bruijn indices, which replaces them by 'AvarSharing' or 'VarSharing' nodes.  Hence,+-- the tag values only serve the purpose of determining the ordering in that initial environment.+-- They are /not/ directly used to compute the de Brujin indices.+--+makeOccMapAcc+    :: HasCallStack+    => Config+    -> Level+    -> SmartAcc arrs+    -> IO (UnscopedAcc arrs, OccMap SmartAcc)+makeOccMapAcc config lvl acc = do+  traceLine "makeOccMapAcc" "Enter"+  accOccMap             <- newASTHashTable+  (acc', _)             <- makeOccMapSharingAcc config accOccMap lvl acc+  frozenAccOccMap       <- freezeOccMap accOccMap+  traceLine "makeOccMapAcc" "Exit"+  return (acc', frozenAccOccMap)+++makeOccMapSharingAcc+    :: HasCallStack+    => Config+    -> OccMapHash SmartAcc+    -> Level+    -> SmartAcc arrs+    -> IO (UnscopedAcc arrs, Int)+makeOccMapSharingAcc config accOccMap = traverseAcc+  where+    traverseFun1+        :: HasCallStack+        => Level+        -> TypeR a+        -> (SmartExp a -> SmartExp b)+        -> IO (SmartExp a -> RootExp b, Int)+    traverseFun1 = makeOccMapFun1 config accOccMap++    traverseFun2+        :: HasCallStack+        => Level+        -> TypeR a+        -> TypeR b+        -> (SmartExp a -> SmartExp b -> SmartExp c)+        -> IO (SmartExp a -> SmartExp b -> RootExp c, Int)+    traverseFun2 = makeOccMapFun2 config accOccMap++    traverseAfun1+        :: HasCallStack+        => Level+        -> ArraysR a+        -> (SmartAcc a -> SmartAcc b)+        -> IO (SmartAcc a -> UnscopedAcc b, Int)+    traverseAfun1 = makeOccMapAfun1 config accOccMap++    traverseExp+      :: HasCallStack+      => Level+      -> SmartExp e+      -> IO (RootExp e, Int)+    traverseExp = makeOccMapExp config accOccMap++    traverseBoundary+        :: HasCallStack+        => Level+        -> ShapeR sh+        -> PreBoundary SmartAcc SmartExp (Array sh e)+        -> IO (PreBoundary UnscopedAcc RootExp (Array sh e), Int)+    traverseBoundary lvl shr bndy =+      case bndy of+        Clamp      -> return (Clamp, 0)+        Mirror     -> return (Mirror, 0)+        Wrap       -> return (Wrap, 0)+        Constant v -> return (Constant v, 0)+        Function f -> do+          (f', h) <- traverseFun1 lvl (shapeType shr) f+          return (Function f', h)++    -- traverseSeq :: forall arrs. Typeable arrs+    --             => Level -> Seq arrs+    --             -> IO (RootSeq arrs, Int)+    -- traverseSeq = makeOccMapRootSeq config accOccMap++    traverseAcc+        :: forall arrs. HasCallStack+        => Level+        -> SmartAcc arrs+        -> IO (UnscopedAcc arrs, Int)+    traverseAcc lvl acc@(SmartAcc pacc)+      = mfix $ \ ~(_, height) -> do+          -- Compute stable name and enter it into the occurrence map+          --+          sn                         <- makeStableAST acc+          heightIfRepeatedOccurrence <- enterOcc accOccMap (StableASTName sn) height++          traceLine (showPreAccOp pacc) $ 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'.+          --+          let reconstruct :: IO (PreSmartAcc UnscopedAcc RootExp arrs, Int)+                          -> IO (UnscopedAcc arrs, Int)+              reconstruct newAcc+                = case heightIfRepeatedOccurrence of+                    Just height | acc_sharing `member` options config+                      -> return (UnscopedAcc [] (AvarSharing (StableNameHeight sn height) (Smart.arraysR pacc)), height)+                    _ -> do (acc, height) <- newAcc+                            return (UnscopedAcc [] (AccSharing (StableNameHeight sn height) acc), height)++          reconstruct $ case pacc of+            Atag repr i                 -> return (Atag repr i, 0)           -- height is 0!+            Pipe repr1 repr2 repr3 afun1 afun2 acc+                                        -> do+                                             (afun1', h1) <- traverseAfun1 lvl repr1 afun1+                                             (afun2', h2) <- traverseAfun1 lvl repr2 afun2+                                             (acc', h3)   <- traverseAcc lvl acc+                                             return (Pipe repr1 repr2 repr3 afun1' afun2' acc'+                                                    , h1 `max` h2 `max` h3 + 1)+            Aforeign repr ff afun acc   -> travA (Aforeign repr ff afun) acc+            Acond e acc1 acc2           -> do+                                             (e'   , h1) <- traverseExp lvl e+                                             (acc1', h2) <- traverseAcc lvl acc1+                                             (acc2', h3) <- traverseAcc lvl acc2+                                             return (Acond e' acc1' acc2', h1 `max` h2 `max` h3 + 1)+            Awhile repr pred iter init  -> do+                                             (pred', h1) <- traverseAfun1 lvl repr pred+                                             (iter', h2) <- traverseAfun1 lvl repr iter+                                             (init', h3) <- traverseAcc lvl init+                                             return (Awhile repr pred' iter' init'+                                                    , h1 `max` h2 `max` h3 + 1)++            Anil                        -> return (Anil, 0)+            Apair acc1 acc2             -> do+                                             (a', h1) <- traverseAcc lvl acc1+                                             (b', h2) <- traverseAcc lvl acc2+                                             return (Apair a' b', h1 `max` h2 + 1)+            Aprj ix a                   -> travA (Aprj ix) a++            Use repr arr                -> return (Use repr arr, 1)+            Unit tp e                   -> do+                                             (e', h) <- traverseExp lvl e+                                             return (Unit tp e', h + 1)+            Generate repr@(ArrayR shr _) e f+                                        -> do+                                             (e', h1) <- traverseExp lvl e+                                             (f', h2) <- traverseFun1 lvl (shapeType shr) f+                                             return (Generate repr e' f', h1 `max` h2 + 1)+            Reshape shr e acc           -> travEA (Reshape shr) e acc+            Replicate si e acc          -> travEA (Replicate si) e acc+            Slice si acc e              -> travEA (flip $ Slice si) e acc+            Map t1 t2 f acc             -> do+                                             (f'  , h1) <- traverseFun1 lvl t1 f+                                             (acc', h2) <- traverseAcc lvl acc+                                             return (Map t1 t2 f' acc', h1 `max` h2 + 1)+            ZipWith t1 t2 t3 f acc1 acc2+                                        -> travF2A2 (ZipWith t1 t2 t3) t1 t2 f acc1 acc2+            Fold tp f e acc             -> travF2MEA (Fold tp) tp tp f e acc+            FoldSeg i tp f e acc1 acc2  -> do+                                             (f'   , h1) <- traverseFun2 lvl tp tp f+                                             (e'   , h2) <- travME e+                                             (acc1', h3) <- traverseAcc lvl acc1+                                             (acc2', h4) <- traverseAcc lvl acc2+                                             return (FoldSeg i tp f' e' acc1' acc2',+                                                     h1 `max` h2 `max` h3 `max` h4 + 1)+            Scan  d tp f e acc          -> travF2MEA (Scan  d tp) tp tp f e acc+            Scan' d tp f e acc          -> travF2EA (Scan' d tp) tp tp f e acc+            Permute repr@(ArrayR shr tp) c acc1 p acc2+                                        -> do+                                             (c'   , h1) <- traverseFun2 lvl tp tp c+                                             (p'   , h2) <- traverseFun1 lvl (shapeType shr) p+                                             (acc1', h3) <- traverseAcc lvl acc1+                                             (acc2', h4) <- traverseAcc lvl acc2+                                             return (Permute repr c' acc1' p' acc2',+                                                     h1 `max` h2 `max` h3 `max` h4 + 1)+            Backpermute shr e p acc     -> do+                                             (e'  , h1) <- traverseExp lvl e+                                             (p'  , h2) <- traverseFun1 lvl (shapeType shr) p+                                             (acc', h3) <- traverseAcc lvl acc+                                             return (Backpermute shr e' p' acc', h1 `max` h2 `max` h3 + 1)+            Stencil s tp f bnd acc      -> do+                                             (f'  , h1) <- makeOccMapStencil1 config accOccMap s lvl f+                                             (bnd', h2) <- traverseBoundary lvl (stencilShapeR s) bnd+                                             (acc', h3) <- traverseAcc lvl acc+                                             return (Stencil s tp f' bnd' acc', h1 `max` h2 `max` h3 + 1)+            Stencil2 s1 s2 tp f bnd1 acc1+                              bnd2 acc2 -> do+                                             let shr = stencilShapeR s1+                                             (f'   , h1) <- makeOccMapStencil2 config accOccMap s1 s2 lvl f+                                             (bnd1', h2) <- traverseBoundary lvl shr bnd1+                                             (acc1', h3) <- traverseAcc lvl acc1+                                             (bnd2', h4) <- traverseBoundary lvl shr bnd2+                                             (acc2', h5) <- traverseAcc lvl acc2+                                             return (Stencil2 s1 s2 tp f' bnd1' acc1' bnd2' acc2',+                                                     h1 `max` h2 `max` h3 `max` h4 `max` h5 + 1)+            -- Collect s                   -> do+            --                                  (s', h) <- traverseSeq lvl s+            --                                  return (Collect s', h + 1)+++      where+        travA :: HasCallStack+              => (UnscopedAcc arrs' -> PreSmartAcc UnscopedAcc RootExp arrs)+              -> SmartAcc arrs'+              -> IO (PreSmartAcc UnscopedAcc RootExp arrs, Int)+        travA c acc+          = do+              (acc', h) <- traverseAcc lvl acc+              return (c acc', h + 1)++        travEA :: HasCallStack+               => (RootExp b -> UnscopedAcc arrs' -> PreSmartAcc UnscopedAcc RootExp arrs)+               -> SmartExp b+               -> SmartAcc arrs'+               -> IO (PreSmartAcc UnscopedAcc RootExp arrs, Int)+        travEA c exp acc+          = do+              (exp', h1) <- traverseExp lvl exp+              (acc', h2) <- traverseAcc lvl acc+              return (c exp' acc', h1 `max` h2 + 1)++        travF2EA+            :: HasCallStack+            => ((SmartExp b -> SmartExp c -> RootExp d) -> RootExp e -> UnscopedAcc arrs' -> PreSmartAcc UnscopedAcc RootExp arrs)+            -> TypeR b+            -> TypeR c+            -> (SmartExp b -> SmartExp c -> SmartExp d)+            -> SmartExp e+            -> SmartAcc arrs'+            -> IO (PreSmartAcc UnscopedAcc RootExp arrs, Int)+        travF2EA c t1 t2 fun exp acc+          = do+              (fun', h1) <- traverseFun2 lvl t1 t2 fun+              (exp', h2) <- traverseExp lvl exp+              (acc', h3) <- traverseAcc lvl acc+              return (c fun' exp' acc', h1 `max` h2 `max` h3 + 1)++        travF2MEA+            :: HasCallStack+            => ((SmartExp b -> SmartExp c -> RootExp d) -> Maybe (RootExp e) -> UnscopedAcc arrs' -> PreSmartAcc UnscopedAcc RootExp arrs)+            -> TypeR b+            -> TypeR c+            -> (SmartExp b -> SmartExp c -> SmartExp d)+            -> Maybe (SmartExp e)+            -> SmartAcc arrs'+            -> IO (PreSmartAcc UnscopedAcc RootExp arrs, Int)+        travF2MEA c t1 t2 fun exp acc+          = do+              (fun', h1) <- traverseFun2 lvl t1 t2 fun+              (exp', h2) <- travME exp+              (acc', h3) <- traverseAcc lvl acc+              return (c fun' exp' acc', h1 `max` h2 `max` h3 + 1)++        travME :: HasCallStack => Maybe (SmartExp t) -> IO (Maybe (RootExp t), Int)+        travME Nothing  = return (Nothing, 0)+        travME (Just e) = do+          (e', c) <- traverseExp lvl e+          return (Just e', c)++        travF2A2+            :: HasCallStack+            => ((SmartExp b -> SmartExp c -> RootExp d) -> UnscopedAcc arrs1 -> UnscopedAcc arrs2 -> PreSmartAcc UnscopedAcc RootExp arrs)+            -> TypeR b+            -> TypeR c+            -> (SmartExp b -> SmartExp c -> SmartExp d)+            -> SmartAcc arrs1+            -> SmartAcc arrs2+            -> IO (PreSmartAcc UnscopedAcc RootExp arrs, Int)+        travF2A2 c t1 t2 fun acc1 acc2+          = do+              (fun' , h1) <- traverseFun2 lvl t1 t2 fun+              (acc1', h2) <- traverseAcc lvl acc1+              (acc2', h3) <- traverseAcc lvl acc2+              return (c fun' acc1' acc2', h1 `max` h2 `max` h3 + 1)++makeOccMapAfun1+    :: HasCallStack+    => Config+    -> OccMapHash SmartAcc+    -> Level+    -> ArraysR a+    -> (SmartAcc a -> SmartAcc b)+    -> IO (SmartAcc a -> UnscopedAcc b, Int)+makeOccMapAfun1 config accOccMap lvl repr f = do+  let x = SmartAcc (Atag repr lvl)+  --+  (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.+--+-- See Note [Traversing functions and side effects]+--+makeOccMapExp+    :: HasCallStack+    => Config+    -> OccMapHash SmartAcc+    -> Level+    -> SmartExp e+    -> IO (RootExp e, Int)+makeOccMapExp config accOccMap lvl = makeOccMapRootExp config accOccMap lvl []++makeOccMapFun1+    :: HasCallStack+    => Config+    -> OccMapHash SmartAcc+    -> Level+    -> TypeR a+    -> (SmartExp a -> SmartExp b)+    -> IO (SmartExp a -> RootExp b, Int)+makeOccMapFun1 config accOccMap lvl tp f = do+  let x = SmartExp (Tag tp lvl)+  --+  (body, height) <- makeOccMapRootExp config accOccMap (lvl+1) [lvl] (f x)+  return (const body, height)++makeOccMapFun2+    :: HasCallStack+    => Config+    -> OccMapHash SmartAcc+    -> Level+    -> TypeR a+    -> TypeR b+    -> (SmartExp a -> SmartExp b -> SmartExp c)+    -> IO (SmartExp a -> SmartExp b -> RootExp c, Int)+makeOccMapFun2 config accOccMap lvl t1 t2 f = do+  let x = SmartExp (Tag t1 (lvl+1))+      y = SmartExp (Tag t2 lvl)+  --+  (body, height) <- makeOccMapRootExp config accOccMap (lvl+2) [lvl, lvl+1] (f x y)+  return (\_ _ -> body, height)++makeOccMapStencil1+    :: forall sh a b stencil. HasCallStack+    => Config+    -> OccMapHash SmartAcc+    -> R.StencilR sh a stencil+    -> Level+    -> (SmartExp stencil -> SmartExp b)+    -> IO (SmartExp stencil -> RootExp b, Int)+makeOccMapStencil1 config accOccMap s lvl stencil = do+  let x = SmartExp (Tag (R.stencilR s) lvl)+  --+  (body, height) <- makeOccMapRootExp config accOccMap (lvl+1) [lvl] (stencil x)+  return (const body, height)++makeOccMapStencil2+    :: forall sh a b c stencil1 stencil2. HasCallStack+    => Config+    -> OccMapHash SmartAcc+    -> R.StencilR sh a stencil1+    -> R.StencilR sh b stencil2+    -> Level+    -> (SmartExp stencil1 -> SmartExp stencil2 -> SmartExp c)+    -> IO (SmartExp stencil1 -> SmartExp stencil2 -> RootExp c, Int)+makeOccMapStencil2 config accOccMap sR1 sR2 lvl stencil = do+  let x = SmartExp (Tag (R.stencilR sR1) (lvl+1))+      y = SmartExp (Tag (R.stencilR sR2) lvl)+  --+  (body, height) <- makeOccMapRootExp config accOccMap (lvl+2) [lvl, lvl+1] (stencil x y)+  return (\_ _ -> body, height)+++-- Generate sharing information for expressions embedded in Acc computations.+-- Expressions are annotated with:+--+--  1) the tags of free scalar variables (for scalar functions)+--  2) a local occurrence map for that expression.+--+makeOccMapRootExp+    :: HasCallStack+    => Config+    -> OccMapHash SmartAcc+    -> Level                            -- The level of currently bound scalar variables+    -> [Int]                            -- The tags of newly introduced free scalar variables in this expression+    -> SmartExp e+    -> IO (RootExp e, Int)+makeOccMapRootExp config accOccMap lvl fvs exp = do+  traceLine "makeOccMapRootExp" "Enter"+  expOccMap                     <- newASTHashTable+  (UnscopedExp [] exp', height) <- makeOccMapSharingExp config accOccMap expOccMap lvl exp+  frozenExpOccMap               <- freezeOccMap expOccMap+  traceLine "makeOccMapRootExp" "Exit"+  return (RootExp frozenExpOccMap (UnscopedExp fvs exp'), height)+++-- Generate sharing information for an open scalar expression.+--+makeOccMapSharingExp+    :: HasCallStack+    => Config+    -> OccMapHash SmartAcc+    -> OccMapHash SmartExp+    -> Level                            -- The level of currently bound variables+    -> SmartExp e+    -> IO (UnscopedExp e, Int)+makeOccMapSharingExp config accOccMap expOccMap = travE+  where+    travE :: forall a. HasCallStack => Level -> SmartExp a -> IO (UnscopedExp a, Int)+    travE lvl exp@(SmartExp pexp)+      = mfix $ \ ~(_, height) -> do+          -- Compute stable name and enter it into the occurrence map+          --+          sn                         <- makeStableAST exp+          heightIfRepeatedOccurrence <- enterOcc expOccMap (StableASTName sn) height++          traceLine (showPreExpOp pexp) $ 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 'newExp'.  See also 'enterOcc'.+          --+          let reconstruct :: IO (PreSmartExp UnscopedAcc UnscopedExp a, Int)+                          -> IO (UnscopedExp a, Int)+              reconstruct newExp+                = case heightIfRepeatedOccurrence of+                    Just height | exp_sharing `member` options config+                      -> return (UnscopedExp [] (VarSharing (StableNameHeight sn height) (typeR pexp)), height)+                    _ -> do (exp, height) <- newExp+                            return (UnscopedExp [] (ExpSharing (StableNameHeight sn height) exp), height)++          reconstruct $ case pexp of+            Tag tp i            -> return (Tag tp i, 0)      -- height is 0!+            Const tp c          -> return (Const tp c, 1)+            Undef tp            -> return (Undef tp, 1)+            Nil                 -> return (Nil, 1)+            Pair e1 e2          -> travE2 Pair e1 e2+            Prj i e             -> travE1 (Prj i) e+            VecPack   vec e     -> travE1 (VecPack   vec) e+            VecUnpack vec e     -> travE1 (VecUnpack vec) e+            ToIndex shr sh ix   -> travE2 (ToIndex shr) sh ix+            FromIndex shr sh e  -> travE2 (FromIndex shr) sh e+            Match t e           -> travE1 (Match t) e+            Case e rhs          -> do+                                     (e',   h1) <- travE lvl e+                                     (rhs', h2) <- unzip <$> sequence [ travE1 (t,) c | (t,c) <- rhs ]+                                     return (Case e' rhs', h1 `max` maximum h2 + 1)+            Cond e1 e2 e3       -> travE3 Cond e1 e2 e3+            While t p iter init -> do+                                     (p'   , h1) <- traverseFun1 lvl t p+                                     (iter', h2) <- traverseFun1 lvl t iter+                                     (init', h3) <- travE lvl init+                                     return (While t p' iter' init', h1 `max` h2 `max` h3 + 1)+            PrimConst c         -> return (PrimConst c, 1)+            PrimApp p e         -> travE1 (PrimApp p) e+            Index tp a e        -> travAE (Index tp) a e+            LinearIndex tp a i  -> travAE (LinearIndex tp) a i+            Shape shr a         -> travA (Shape shr) a+            ShapeSize shr e     -> travE1 (ShapeSize shr) e+            Foreign tp ff f e   -> do+                                      (e', h) <- travE lvl e+                                      return  (Foreign tp ff f e', h+1)+            Coerce t1 t2 e      -> travE1 (Coerce t1 t2) e++      where+        traverseAcc :: HasCallStack => Level -> SmartAcc arrs -> IO (UnscopedAcc arrs, Int)+        traverseAcc = makeOccMapSharingAcc config accOccMap++        traverseFun1+            :: HasCallStack+            => Level+            -> TypeR a+            -> (SmartExp a -> SmartExp b)+            -> IO (SmartExp a -> UnscopedExp b, Int)+        traverseFun1 lvl tp f+          = do+              let x = SmartExp (Tag tp lvl)+              (UnscopedExp [] body, height) <- travE (lvl+1) (f x)+              return (const (UnscopedExp [lvl] body), height + 1)+++        travE1 :: HasCallStack => (UnscopedExp b -> r) -> SmartExp b -> IO (r, Int)+        travE1 c e+          = do+              (e', h) <- travE lvl e+              return (c e', h + 1)++        travE2 :: HasCallStack+               => (UnscopedExp b -> UnscopedExp c -> r)+               -> SmartExp b+               -> SmartExp c+               -> IO (r, Int)+        travE2 c e1 e2+          = do+              (e1', h1) <- travE lvl e1+              (e2', h2) <- travE lvl e2+              return (c e1' e2', h1 `max` h2 + 1)++        travE3 :: HasCallStack+               => (UnscopedExp b -> UnscopedExp c -> UnscopedExp d -> r)+               -> SmartExp b+               -> SmartExp c+               -> SmartExp d+               -> IO (r, Int)+        travE3 c e1 e2 e3+          = do+              (e1', h1) <- travE lvl e1+              (e2', h2) <- travE lvl e2+              (e3', h3) <- travE lvl e3+              return (c e1' e2' e3', h1 `max` h2 `max` h3 + 1)++        travA :: HasCallStack => (UnscopedAcc b -> r) -> SmartAcc b -> IO (r, Int)+        travA c acc+          = do+              (acc', h) <- traverseAcc lvl acc+              return (c acc', h + 1)++        travAE :: HasCallStack+               => (UnscopedAcc b -> UnscopedExp c -> r)+               -> SmartAcc b+               -> SmartExp c+               -> IO (r, Int)+        travAE c acc e+          = do+              (acc', h1) <- traverseAcc lvl acc+              (e'  , h2) <- travE lvl e+              return (c acc' 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.+--+--   Invariants of the list:+--   - If one shared term 's' is itself a subterm of another shared term 't', then 's' must occur+--     *after* 't' in the list.+--   - No shared term occurs twice.+--   - 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 'SmartAcc' node counts as we don't share 'Exp' nodes across 'SmartAcc'+--     nodes. Similarly, all 'Seq' nodes precede 'SmartAcc' 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')+-- is 0, whereas other leaves have height 1.  This guarantees that all free variables are at the end+-- of the 'NodeCounts' list.+--+-- The graph is represented as a map where a stable name 'a' is mapped to a set of stables names 'b'+-- such that if there exists a edge from 'a' to 'c' that 'c' is contained within 'b'.+--+--  Properties of the graph:+--  - There exists an edge from 'a' to 'b' if the term 'a' names is a subterm of the term named by+--    'b'.+--+-- To ensure the list invariant and the graph properties are preserved over merging node counts from+-- sibling subterms, the function '(+++)' must be used.+--+type NodeCounts = ([NodeCount], Map.HashMap NodeName (Set.HashSet NodeName))++data NodeName where+  NodeName :: StableName a -> NodeName++instance Eq NodeName where+  (NodeName sn1) == (NodeName sn2) = eqStableName sn1 sn2++instance Hashable NodeName where+  hashWithSalt hash (NodeName sn1) = hash + hashStableName sn1++instance Show NodeName where+  show (NodeName sn) = show (hashStableName sn)++data NodeCount = AccNodeCount StableSharingAcc Int+               | ExpNodeCount StableSharingExp Int+               -- SeqNodeCount StableSharingSeq Int+               deriving Show++-- Empty node counts+--+noNodeCounts :: NodeCounts+noNodeCounts = ([], Map.empty)++-- Insert an Acc node into the node counts, assuming that it is a superterm of the all the existing+-- nodes.+--+-- TODO: Perform cycle detection here.+--+insertAccNode :: StableSharingAcc -> NodeCounts -> NodeCounts+insertAccNode ssa@(StableSharingAcc (StableNameHeight sn _) _) (subterms,g)+  = ([AccNodeCount 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]++-- Insert an Exp node into the node counts, assuming that it is a superterm of the all the existing+-- nodes.+--+-- TODO: Perform cycle detection here.+--+insertExpNode :: StableSharingExp -> NodeCounts -> NodeCounts+insertExpNode ssa@(StableSharingExp (StableNameHeight sn _) _) (subterms,g)+  = ([ExpNodeCount 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]++{--+-- 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.+--+cleanCounts :: NodeCounts -> NodeCounts+cleanCounts (ns, g) = (ns, Map.fromList [(h, Set.filter (flip elem hs) (g Map.! h)) | h <- hs ])+  where+    hs = map nodeName ns++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.+--+-- * We assume that the list invariant —subterms follow their parents— holds for both arguments and+--   guarantee that it still holds for the result.+--+-- * In the same manner, we assume that all 'Exp' node counts precede 'SmartAcc' node counts and+--   guarantee that this also hold for the result.+--+(+++) :: NodeCounts -> NodeCounts -> NodeCounts+(ns1, g1) +++ (ns2, g2) = (cleanup $ merge ns1 ns2, Map.unionWith Set.union g1 g2)+  where+    merge [] x = x+    merge x [] = x+    merge (x@(AccNodeCount sa1 count1):xs) (y@(AccNodeCount sa2 count2):ys)+     | sa1 == sa2          = AccNodeCount (sa1 `pickNoneAvar` sa2) (count1 + count2) : merge xs ys+     | sa1 `higherSSA` sa2 = x : merge xs (y:ys)+     | otherwise           = y : merge (x:xs) ys+    merge (x@(ExpNodeCount se1 count1):xs) (y@(ExpNodeCount se2 count2):ys)+     | se1 == se2          = ExpNodeCount (se1 `pickNoneVar` se2) (count1 + count2) : merge xs ys+     | se1 `higherSSE` se2 = x : merge xs (y:ys)+     | otherwise           = y : merge (x:xs) ys+    merge (x@(AccNodeCount _ _):xs) (y@(ExpNodeCount _ _):ys) = y : merge (x:xs) ys+    merge (x@(ExpNodeCount _ _):xs) (y@(AccNodeCount _ _):ys) = x : merge xs (y:ys)++    (StableSharingAcc _ (AvarSharing _ _)) `pickNoneAvar` sa2  = sa2+    sa1                                    `pickNoneAvar` _sa2 = sa1++    (StableSharingExp _ (VarSharing _ _))  `pickNoneVar`  sa2  = sa2+    sa1                                    `pickNoneVar`  _sa2 = sa1++    -- As the StableSharingAccs do not pose a strict ordering, this cleanup+    -- step is needed. In this step, all pairs of AccNodes and ExpNodes+    -- that are of the same height are compared against each other. Without+    -- this step, duplicates may arise.+    --+    -- Note that while (+++) is morally symmetric, replacing `merge [x] y'+    -- with `merge y [x]' inside of `cleanup' won't check all required+    -- possibilities.+    --+    cleanup = concatMap (foldr (\x y -> merge [x] y) []) . groupBy sameHeight+    sameHeight (AccNodeCount sa1 _) (AccNodeCount sa2 _) = not (sa1 `higherSSA` sa2) && not (sa2 `higherSSA` sa1)+    sameHeight (ExpNodeCount se1 _) (ExpNodeCount se2 _) = not (se1 `higherSSE` se2) && not (se2 `higherSSE` se1)+    sameHeight _ _ = False+++-- 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.)+--+-- Bail out if any tag occurs multiple times as this indicates that the sharing of an argument+-- variable was not preserved and we cannot build an appropriate initial environment (c.f., comments+-- at 'determineScopesAcc'.+--+buildInitialEnvAcc+    :: HasCallStack+    => [Level]+    -> [StableSharingAcc]+    -> [StableSharingAcc]+buildInitialEnvAcc tags sas = map (lookupSA sas) tags+  where+    lookupSA sas tag1+      = case filter hasTag sas of+          []   -> noStableSharing    -- tag is not used in the analysed expression+          [sa] -> sa                 -- tag has a unique occurrence+          sas2 -> internalError ("Encountered duplicate 'ATag's\n  " ++ intercalate ", " (map showSA sas2))+      where+        hasTag (StableSharingAcc _ (AccSharing _ (Atag _ tag2))) = tag1 == tag2+        hasTag sa+          = internalError ("Encountered a node that is not a plain 'Atag'\n  " ++ showSA sa)++        noStableSharing :: StableSharingAcc+        noStableSharing = StableSharingAcc noStableAccName (undefined :: SharingAcc acc exp ())++    showSA (StableSharingAcc _ (AccSharing  sn acc)) = show (hashStableNameHeight sn) ++ ": " +++                                                       showPreAccOp acc+    showSA (StableSharingAcc _ (AvarSharing sn _))   = "AvarSharing " ++ show (hashStableNameHeight sn)+    showSA (StableSharingAcc _ (AletSharing sa _))   = "AletSharing " ++ show sa ++ "..."++-- Build an initial environment for the tag values given in the first argument for traversing a+-- scalar expression.  The 'StableSharingExp'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.)+--+-- Bail out if any tag occurs multiple times as this indicates that the sharing of an argument+-- variable was not preserved and we cannot build an appropriate initial environment (c.f., comments+-- at 'determineScopesAcc'.+--+buildInitialEnvExp+    :: HasCallStack+    => [Level]+    -> [StableSharingExp]+    -> [StableSharingExp]+buildInitialEnvExp tags ses = map (lookupSE ses) tags+  where+    lookupSE ses tag1+      = case filter hasTag ses of+          []   -> noStableSharing    -- tag is not used in the analysed expression+          [se] -> se                 -- tag has a unique occurrence+          ses2 -> internalError ("Encountered a duplicate 'Tag'\n  " ++ intercalate ", " (map showSE ses2))+      where+        hasTag (StableSharingExp _ (ExpSharing _ (Tag _ tag2))) = tag1 == tag2+        hasTag se+          = internalError ("Encountered a node that is not a plain 'Tag'\n  " ++ showSE se)++        noStableSharing :: StableSharingExp+        noStableSharing = StableSharingExp noStableExpName (undefined :: SharingExp acc exp ())++    showSE (StableSharingExp _ (ExpSharing sn exp)) = show (hashStableNameHeight sn) ++ ": " +++                                                      showPreExpOp exp+    showSE (StableSharingExp _ (VarSharing sn _ ))  = "VarSharing " ++ show (hashStableNameHeight sn)+    showSE (StableSharingExp _ (LetSharing se _ ))  = "LetSharing " ++ show se ++ "..."++-- Determine whether a 'NodeCount' is for an 'Atag' or 'Tag', which represent free variables.+--+isFreeVar :: NodeCount -> Bool+isFreeVar (AccNodeCount (StableSharingAcc _ (AccSharing _ (Atag _ _))) _) = True+isFreeVar (ExpNodeCount (StableSharingExp _ (ExpSharing _ (Tag  _ _))) _) = True+isFreeVar _                                                               = False+++-- Determine scope of shared subterms+-- ==================================++-- Determine the scopes of all variables representing shared subterms (Phase Two) in a bottom-up+-- sweep.  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.+--+-- In addition to the AST with sharing information, yield the 'StableSharingAcc's for all free+-- variables of 'rootAcc', which are represented by 'Atag' leaves in the tree. They are in order of+-- the tag values — i.e., in the same order that they need to appear in an environment to use the+-- tag for indexing into that environment.+--+-- Precondition: there are only 'AvarSharing' and 'AccSharing' nodes in the argument.+--+determineScopesAcc+    :: HasCallStack+    => Config+    -> [Level]+    -> OccMap SmartAcc+    -> UnscopedAcc a+    -> (ScopedAcc a, [StableSharingAcc])+determineScopesAcc config fvs accOccMap rootAcc+  = let (sharingAcc, (counts, _)) = determineScopesSharingAcc config accOccMap rootAcc+        unboundTrees              = filter (not . isFreeVar) counts+    in+    if all isFreeVar counts+       then (sharingAcc, buildInitialEnvAcc fvs [sa | AccNodeCount sa _ <- counts])+       else internalError ("unbound shared subtrees" ++ show unboundTrees)+++determineScopesSharingAcc+    :: HasCallStack+    => Config+    -> OccMap SmartAcc+    -> UnscopedAcc a+    -> (ScopedAcc a, NodeCounts)+determineScopesSharingAcc config accOccMap = scopesAcc+  where+    scopesAcc :: forall arrs. HasCallStack => UnscopedAcc arrs -> (ScopedAcc arrs, NodeCounts)+    scopesAcc (UnscopedAcc _ (AletSharing _ _))+      = internalError "unexpected 'AletSharing'"++    scopesAcc (UnscopedAcc _ (AvarSharing sn tp))+      = (ScopedAcc [] (AvarSharing sn tp), StableSharingAcc sn (AvarSharing sn tp) `insertAccNode` noNodeCounts)++    scopesAcc (UnscopedAcc _ (AccSharing sn pacc))+      = case pacc of+          Atag tp i               -> reconstruct (Atag tp i) noNodeCounts+          Pipe repr1 repr2 repr3 afun1 afun2 acc+                                  -> let+                                       (afun1', accCount1) = scopesAfun1 afun1+                                       (afun2', accCount2) = scopesAfun1 afun2+                                       (acc', accCount3)   = scopesAcc acc+                                     in+                                     reconstruct (Pipe repr1 repr2 repr3 afun1' afun2' acc')+                                                 (accCount1 +++ accCount2 +++ accCount3)++          Aforeign r ff afun acc  -> let+                                       (acc', accCount) = scopesAcc acc+                                     in+                                     reconstruct (Aforeign r ff afun acc') accCount+          Acond e acc1 acc2       -> let+                                       (e'   , accCount1) = scopesExp e+                                       (acc1', accCount2) = scopesAcc acc1+                                       (acc2', accCount3) = scopesAcc acc2+                                     in+                                     reconstruct (Acond e' acc1' acc2')+                                                 (accCount1 +++ accCount2 +++ accCount3)++          Awhile repr pred iter init+                                  -> let+                                       (pred', accCount1) = scopesAfun1 pred+                                       (iter', accCount2) = scopesAfun1 iter+                                       (init', accCount3) = scopesAcc init+                                     in+                                     reconstruct (Awhile repr pred' iter' init')+                                                 (accCount1 +++ accCount2 +++ accCount3)++          Anil                    -> reconstruct Anil noNodeCounts+          Apair a1 a2             -> let+                                       (a1', accCount1) = scopesAcc a1+                                       (a2', accCount2) = scopesAcc a2+                                     in+                                       reconstruct (Apair a1' a2') (accCount1 +++ accCount2)+          Aprj ix a               -> travA (Aprj ix) a++          Use repr arr            -> reconstruct (Use repr arr) noNodeCounts+          Unit tp e               -> let+                                       (e', accCount) = scopesExp e+                                     in+                                     reconstruct (Unit tp e') accCount+          Generate repr sh f      -> let+                                       (sh', accCount1) = scopesExp sh+                                       (f' , accCount2) = scopesFun1 f+                                     in+                                     reconstruct (Generate repr sh' f') (accCount1 +++ accCount2)+          Reshape shr sh acc      -> travEA (Reshape shr) sh acc+          Replicate si n acc      -> travEA (Replicate si) n acc+          Slice si acc i          -> travEA (flip $ Slice si) i acc+          Map t1 t2 f acc         -> let+                                       (f'  , accCount1) = scopesFun1 f+                                       (acc', accCount2) = scopesAcc  acc+                                     in+                                     reconstruct (Map t1 t2 f' acc') (accCount1 +++ accCount2)+          ZipWith t1 t2 t3 f acc1 acc2+                                  -> travF2A2 (ZipWith t1 t2 t3) f acc1 acc2+          Fold tp f z acc         -> travF2MEA (Fold tp) f z acc+          FoldSeg i tp f z acc1 acc2 -> let+                                       (f'   , accCount1)  = scopesFun2 f+                                       (z'   , accCount2)  = travME z+                                       (acc1', accCount3)  = scopesAcc  acc1+                                       (acc2', accCount4)  = scopesAcc  acc2+                                     in+                                     reconstruct (FoldSeg i tp f' z' acc1' acc2')+                                       (accCount1 +++ accCount2 +++ accCount3 +++ accCount4)+          Scan d tp f z acc       -> travF2MEA (Scan d tp) f z acc+          Scan' d tp f z acc      -> travF2EA (Scan' d tp) f z acc+          Permute repr fc acc1 fp acc2+                                  -> let+                                       (fc'  , accCount1) = scopesFun2 fc+                                       (acc1', accCount2) = scopesAcc  acc1+                                       (fp'  , accCount3) = scopesFun1 fp+                                       (acc2', accCount4) = scopesAcc  acc2+                                     in+                                     reconstruct (Permute repr fc' acc1' fp' acc2')+                                       (accCount1 +++ accCount2 +++ accCount3 +++ accCount4)+          Backpermute shr sh fp acc+                                  -> let+                                       (sh' , accCount1) = scopesExp  sh+                                       (fp' , accCount2) = scopesFun1 fp+                                       (acc', accCount3) = scopesAcc  acc+                                     in+                                     reconstruct (Backpermute shr sh' fp' acc')+                                       (accCount1 +++ accCount2 +++ accCount3)+          Stencil sr tp st bnd acc      -> let+                                       (st' , accCount1) = scopesStencil1 acc st+                                       (bnd', accCount2) = scopesBoundary bnd+                                       (acc', accCount3) = scopesAcc acc+                                     in+                                     reconstruct (Stencil sr tp st' bnd' acc') (accCount1 +++ accCount2 +++ accCount3)+          Stencil2 s1 s2 tp st bnd1 acc1 bnd2 acc2+                                  -> let+                                       (st'  , accCount1) = scopesStencil2 acc1 acc2 st+                                       (bnd1', accCount2) = scopesBoundary bnd1+                                       (acc1', accCount3) = scopesAcc acc1+                                       (bnd2', accCount4) = scopesBoundary bnd2+                                       (acc2', accCount5) = scopesAcc acc2+                                     in+                                     reconstruct (Stencil2 s1 s2 tp st' bnd1' acc1' bnd2' acc2')+                                       (accCount1 +++ accCount2 +++ accCount3 +++ accCount4 +++ accCount5)+          -- Collect seq             -> let+          --                              (seq', accCount1) = scopesSeq seq+          --                            in+          --                            reconstruct (Collect seq') accCount1++      where+        travEA :: HasCallStack+               => (ScopedExp e -> ScopedAcc arrs' -> PreSmartAcc ScopedAcc ScopedExp arrs)+               -> RootExp e+               -> UnscopedAcc arrs'+               -> (ScopedAcc arrs, NodeCounts)+        travEA c e acc = reconstruct (c e' acc') (accCount1 +++ accCount2)+          where+            (e'  , accCount1) = scopesExp e+            (acc', accCount2) = scopesAcc acc++        travF2EA+            :: HasCallStack+            => ((SmartExp a -> SmartExp b -> ScopedExp c) -> ScopedExp e -> ScopedAcc arrs' -> PreSmartAcc ScopedAcc ScopedExp arrs)+            -> (SmartExp a -> SmartExp b -> RootExp c)+            -> RootExp e+            -> UnscopedAcc arrs'+            -> (ScopedAcc arrs, NodeCounts)+        travF2EA c f e acc = reconstruct (c f' e' acc') (accCount1 +++ accCount2 +++ accCount3)+          where+            (f'  , accCount1) = scopesFun2 f+            (e'  , accCount2) = scopesExp  e+            (acc', accCount3) = scopesAcc  acc++        travF2MEA+            :: HasCallStack+            => ((SmartExp a -> SmartExp b -> ScopedExp c) -> Maybe (ScopedExp e) -> ScopedAcc arrs' -> PreSmartAcc ScopedAcc ScopedExp arrs)+            -> (SmartExp a -> SmartExp b -> RootExp c)+            -> Maybe (RootExp e)+            -> UnscopedAcc arrs'+            -> (ScopedAcc arrs, NodeCounts)+        travF2MEA c f e acc = reconstruct (c f' e' acc') (accCount1 +++ accCount2 +++ accCount3)+          where+            (f'  , accCount1) = scopesFun2 f+            (e'  , accCount2) = travME e+            (acc', accCount3) = scopesAcc  acc++        travME :: HasCallStack => Maybe (RootExp e) -> (Maybe (ScopedExp e), NodeCounts)+        travME Nothing  = (Nothing, noNodeCounts)+        travME (Just e) = (Just e', c)+          where (e', c) = scopesExp e++        travF2A2+            :: HasCallStack+            => ((SmartExp a -> SmartExp b -> ScopedExp c) -> ScopedAcc arrs1 -> ScopedAcc arrs2 -> PreSmartAcc ScopedAcc ScopedExp arrs)+            -> (SmartExp a -> SmartExp b -> RootExp c)+            -> UnscopedAcc arrs1+            -> UnscopedAcc arrs2+            -> (ScopedAcc arrs, NodeCounts)+        travF2A2 c f acc1 acc2 = reconstruct (c f' acc1' acc2')+                                             (accCount1 +++ accCount2 +++ accCount3)+          where+            (f'   , accCount1) = scopesFun2 f+            (acc1', accCount2) = scopesAcc  acc1+            (acc2', accCount3) = scopesAcc  acc2++        travA :: HasCallStack+              => (ScopedAcc arrs' -> PreSmartAcc ScopedAcc ScopedExp arrs)+              -> UnscopedAcc arrs'+              -> (ScopedAcc arrs, NodeCounts)+        travA c acc = reconstruct (c acc') accCount+          where+            (acc', accCount) = scopesAcc acc++          -- Occurrence count of the currently processed node+        accOccCount = let StableNameHeight sn' _ = sn+                      in+                      lookupWithASTName accOccMap (StableASTName sn')++        -- Reconstruct the current tree node.+        --+        -- * If the current node is being shared ('accOccCount > 1'), replace it by a 'AvarSharing'+        --   node and float the shared subtree out wrapped in a 'NodeCounts' value.+        -- * If the current node is not shared, reconstruct it in place.+        -- * Special case for free variables ('Atag'): Replace the tree by a sharing variable and+        --   float the 'Atag' out in a 'NodeCounts' value.  This is independent of the number of+        --   occurrences.+        --+        -- In either case, any completed 'NodeCounts' are injected as bindings using 'AletSharing'+        -- node.+        --+        reconstruct+            :: HasCallStack+            => PreSmartAcc ScopedAcc ScopedExp arrs+            -> NodeCounts+            -> (ScopedAcc arrs, NodeCounts)+        reconstruct newAcc@(Atag tp _) _subCount+              -- free variable => replace by a sharing variable regardless of the number of+              -- occurrences+          = let thisCount = StableSharingAcc sn (AccSharing sn newAcc) `insertAccNode` noNodeCounts+            in+            tracePure "FREE" (show thisCount)+            (ScopedAcc [] (AvarSharing sn tp), thisCount)+        reconstruct newAcc subCount+              -- shared subtree => replace by a sharing variable (if 'recoverAccSharing' enabled)+          | accOccCount > 1 && acc_sharing `member` options config+          = let allCount = (StableSharingAcc sn sharingAcc `insertAccNode` newCount)+            in+            tracePure ("SHARED" ++ completed) (show allCount)+            (ScopedAcc [] (AvarSharing sn $ Smart.arraysR newAcc), allCount)+              -- neither shared nor free variable => leave it as it is+          | otherwise+          = tracePure ("Normal" ++ completed) (show newCount)+            (ScopedAcc [] sharingAcc, newCount)+          where+              -- Determine the bindings that need to be attached to the current node...+            (newCount, bindHere) = filterCompleted subCount++              -- ...and wrap them in 'AletSharing' constructors+            lets       = foldl (flip (.)) id . map (\x y -> AletSharing x (ScopedAcc [] y)) $ bindHere+            sharingAcc = lets $ AccSharing sn newAcc++              -- trace support+            completed | null bindHere = ""+                      | otherwise     = "(" ++ show (length bindHere) ++ " lets)"++        -- Extract *leading* nodes that have a complete node count (i.e., their node count is equal+        -- to the number of occurrences of that node in the overall expression).+        --+        -- Nodes with a completed node count should be let bound at the currently processed node.+        --+        -- NB: Only extract leading nodes (i.e., the longest run at the *front* of the list that is+        --     complete).  Otherwise, we would let-bind subterms before their parents, which leads+        --     scope errors.+        --+        filterCompleted :: NodeCounts -> (NodeCounts, [StableSharingAcc])+        filterCompleted (ns, graph)+          = let bindable     = map (isBindable bindable (map nodeName ns)) ns+                (bind, rest) = partition fst $ zip bindable ns+            in ((map snd rest, graph), [sa | AccNodeCount sa _ <- map snd bind])+          where+            -- a node is not yet complete while the node count 'n' is below the overall number+            -- of occurrences for that node in the whole program, with the exception that free+            -- variables are never complete+            isCompleted nc@(AccNodeCount sa n) | not . isFreeVar $ nc = lookupWithSharingAcc accOccMap sa == n+            isCompleted _                                             = False++            isBindable :: [Bool] -> [NodeName] -> NodeCount -> Bool+            isBindable bindable nodes nc@(AccNodeCount _ _) =+              let superTerms = Set.toList $ graph Map.! nodeName nc+                  unbound    = mapMaybe (`elemIndex` nodes) superTerms+              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+        :: HasCallStack+        => RootExp t+        -> (ScopedExp t, NodeCounts)+    scopesExp = determineScopesExp config accOccMap++    -- The lambda bound variable is at this point already irrelevant; for details, see+    -- Note [Traversing functions and side effects]+    --+    scopesAfun1+        :: HasCallStack+        => (SmartAcc a1 -> UnscopedAcc a2)+        -> (SmartAcc a1 -> ScopedAcc a2, NodeCounts)+    scopesAfun1 f = (const (ScopedAcc ssa body'), (counts', graph))+      where+        body@(UnscopedAcc fvs _)             = f undefined+        (ScopedAcc [] body', (counts,graph)) = scopesAcc body+        (freeCounts, counts')                = partition isBoundHere counts+        ssa                                  = buildInitialEnvAcc fvs [sa | AccNodeCount sa _ <- freeCounts]++        isBoundHere (AccNodeCount (StableSharingAcc _ (AccSharing _ (Atag _ i))) _) = i `elem` fvs+        isBoundHere _                                                               = False++    -- The lambda bound variable is at this point already irrelevant; for details, see+    -- Note [Traversing functions and side effects]+    --+    scopesFun1+        :: HasCallStack+        => (SmartExp e1 -> RootExp e2)+        -> (SmartExp e1 -> ScopedExp e2, NodeCounts)+    scopesFun1 f = (const body, counts)+      where+        (body, counts) = scopesExp (f undefined)++    -- The lambda bound variable is at this point already irrelevant; for details, see+    -- Note [Traversing functions and side effects]+    --+    scopesFun2+        :: HasCallStack+        => (SmartExp e1 -> SmartExp e2 -> RootExp e3)+        -> (SmartExp e1 -> SmartExp 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]+    --+    scopesStencil1+        :: forall sh e1 e2 stencil. HasCallStack+        => UnscopedAcc (Array sh e1){-dummy-}+        -> (stencil -> RootExp e2)+        -> (stencil -> ScopedExp e2, NodeCounts)+    scopesStencil1 _ stencilFun = (const body, counts)+      where+        (body, counts) = scopesExp (stencilFun undefined)++    -- The lambda bound variable is at this point already irrelevant; for details, see+    -- Note [Traversing functions and side effects]+    --+    scopesStencil2+        :: forall sh e1 e2 e3 stencil1 stencil2. HasCallStack+        => UnscopedAcc (Array sh e1){-dummy-}+        -> UnscopedAcc (Array sh e2){-dummy-}+        -> (stencil1 -> stencil2 -> RootExp e3)+        -> (stencil1 -> stencil2 -> ScopedExp e3, NodeCounts)+    scopesStencil2 _ _ stencilFun = (\_ _ -> body, counts)+      where+        (body, counts) = scopesExp (stencilFun undefined undefined)++    scopesBoundary+        :: HasCallStack+        => PreBoundary UnscopedAcc RootExp t+        -> (PreBoundary ScopedAcc ScopedExp t, NodeCounts)+    scopesBoundary bndy =+      case bndy of+        Clamp      -> (Clamp, noNodeCounts)+        Mirror     -> (Mirror, noNodeCounts)+        Wrap       -> (Wrap, noNodeCounts)+        Constant v -> (Constant v, noNodeCounts)+        Function f -> let (body, counts) = scopesFun1 f+                      in  (Function body, counts)+++determineScopesExp+    :: HasCallStack+    => Config+    -> OccMap SmartAcc+    -> RootExp t+    -> (ScopedExp t, NodeCounts)          -- Root (closed) expression plus Acc node counts+determineScopesExp config accOccMap (RootExp expOccMap exp@(UnscopedExp fvs _))+  = let+        (ScopedExp [] expWithScopes, (nodeCounts,graph)) = determineScopesSharingExp config accOccMap expOccMap exp+        (expCounts, accCounts)                           = partition isExpNodeCount nodeCounts++        isExpNodeCount ExpNodeCount{} = True+        isExpNodeCount _              = False+    in+    (ScopedExp (buildInitialEnvExp fvs [se | ExpNodeCount se _ <- expCounts]) expWithScopes, cleanCounts (accCounts,graph))+++determineScopesSharingExp+    :: HasCallStack+    => Config+    -> OccMap SmartAcc+    -> OccMap SmartExp+    -> UnscopedExp t+    -> (ScopedExp t, NodeCounts)+determineScopesSharingExp config accOccMap expOccMap = scopesExp+  where+    scopesAcc+        :: HasCallStack+        => UnscopedAcc a+        -> (ScopedAcc a, NodeCounts)+    scopesAcc = determineScopesSharingAcc config accOccMap++    scopesFun1+        :: HasCallStack+        => (SmartExp a -> UnscopedExp b)+        -> (SmartExp a -> ScopedExp b, NodeCounts)+    scopesFun1 f = tracePure ("LAMBDA " ++ show ssa) (show counts) (const (ScopedExp ssa body'), (counts',graph))+      where+        body@(UnscopedExp fvs _)              = f undefined+        (ScopedExp [] body', (counts, graph)) = scopesExp body+        (freeCounts, counts')                 = partition isBoundHere counts+        ssa                                   = buildInitialEnvExp fvs [se | ExpNodeCount se _ <- freeCounts]++        isBoundHere (ExpNodeCount (StableSharingExp _ (ExpSharing _ (Tag _ i))) _) = i `elem` fvs+        isBoundHere _                                                              = False++    scopesExp+        :: forall t. HasCallStack+        => UnscopedExp t+        -> (ScopedExp t, NodeCounts)+    scopesExp (UnscopedExp _ (LetSharing _ _))+      = internalError "unexpected 'LetSharing'"++    scopesExp (UnscopedExp _ (VarSharing sn tp))+      = (ScopedExp [] (VarSharing sn tp), StableSharingExp sn (VarSharing sn tp) `insertExpNode` noNodeCounts)++    scopesExp (UnscopedExp _ (ExpSharing sn pexp))+      = case pexp of+          Tag tp i              -> reconstruct (Tag tp i) noNodeCounts+          Const tp c            -> reconstruct (Const tp c) noNodeCounts+          Undef tp              -> reconstruct (Undef tp) noNodeCounts+          Pair e1 e2            -> travE2 Pair e1 e2+          Nil                   -> reconstruct Nil noNodeCounts+          Prj i e               -> travE1 (Prj i) e+          VecPack   vec e       -> travE1 (VecPack   vec) e+          VecUnpack vec e       -> travE1 (VecUnpack vec) e+          ToIndex shr sh ix     -> travE2 (ToIndex shr) sh ix+          FromIndex shr sh e    -> travE2 (FromIndex shr) sh e+          Match t e             -> travE1 (Match t) e+          Case e rhs            -> let (e',   accCount1) = scopesExp e+                                       (rhs', accCount2) = unzip [ ((t,c'), counts)| (t,c) <- rhs, let (c', counts) = scopesExp c ]+                                    in reconstruct (Case e' rhs') (foldr (+++) accCount1 accCount2)+          Cond e1 e2 e3         -> travE3 Cond e1 e2 e3+          While tp p it i       -> let (p' , accCount1) = scopesFun1 p+                                       (it', accCount2) = scopesFun1 it+                                       (i' , accCount3) = scopesExp i+                                    in reconstruct (While tp p' it' i') (accCount1 +++ accCount2 +++ accCount3)+          PrimConst c           -> reconstruct (PrimConst c) noNodeCounts+          PrimApp p e           -> travE1 (PrimApp p) e+          Index tp a e          -> travAE (Index tp) a e+          LinearIndex tp a e    -> travAE (LinearIndex tp) a e+          Shape shr a           -> travA (Shape shr) a+          ShapeSize shr e       -> travE1 (ShapeSize shr) e+          Foreign tp ff f e     -> travE1 (Foreign tp ff f) e+          Coerce t1 t2 e        -> travE1 (Coerce t1 t2) e+      where+        travE1 :: HasCallStack+               => (ScopedExp a -> PreSmartExp ScopedAcc ScopedExp t)+               -> UnscopedExp a+               -> (ScopedExp t, NodeCounts)+        travE1 c e = reconstruct (c e') accCount+          where+            (e', accCount) = scopesExp e++        travE2 :: HasCallStack+               => (ScopedExp a -> ScopedExp b -> PreSmartExp ScopedAcc ScopedExp t)+               -> UnscopedExp a+               -> UnscopedExp b+               -> (ScopedExp t, NodeCounts)+        travE2 c e1 e2 = reconstruct (c e1' e2') (accCount1 +++ accCount2)+          where+            (e1', accCount1) = scopesExp e1+            (e2', accCount2) = scopesExp e2++        travE3 :: HasCallStack+               => (ScopedExp a -> ScopedExp b -> ScopedExp c -> PreSmartExp ScopedAcc ScopedExp t)+               -> UnscopedExp a+               -> UnscopedExp b+               -> UnscopedExp c+               -> (ScopedExp t, NodeCounts)+        travE3 c e1 e2 e3 = reconstruct (c e1' e2' e3') (accCount1 +++ accCount2 +++ accCount3)+          where+            (e1', accCount1) = scopesExp e1+            (e2', accCount2) = scopesExp e2+            (e3', accCount3) = scopesExp e3++        travA :: HasCallStack+              => (ScopedAcc a -> PreSmartExp ScopedAcc ScopedExp t) -> UnscopedAcc a+              -> (ScopedExp t, NodeCounts)+        travA c acc = floatOutAcc c acc' accCount+          where+            (acc', accCount)  = scopesAcc acc++        travAE :: HasCallStack+               => (ScopedAcc a -> ScopedExp b -> PreSmartExp ScopedAcc ScopedExp t)+               -> UnscopedAcc a+               -> UnscopedExp b+               -> (ScopedExp t, NodeCounts)+        travAE c acc e = floatOutAcc (`c` e') acc' (accCountA +++ accCountE)+          where+            (acc', accCountA) = scopesAcc acc+            (e'  , accCountE) = scopesExp e++        floatOutAcc+            :: HasCallStack+            => (ScopedAcc a -> PreSmartExp ScopedAcc ScopedExp t)+            -> ScopedAcc a+            -> NodeCounts+            -> (ScopedExp t, NodeCounts)+        floatOutAcc c acc@(ScopedAcc _ (AvarSharing _ _)) accCount        -- nothing to float out+          = reconstruct (c acc) accCount+        floatOutAcc c acc accCount+          = reconstruct (c var) ((stableAcc `insertAccNode` noNodeCounts) +++ accCount)+          where+             (var, stableAcc) = abstract acc (\(ScopedAcc _ s) -> s)++        abstract+            :: HasCallStack+            => ScopedAcc a+            -> (ScopedAcc a -> SharingAcc ScopedAcc ScopedExp a)+            -> (ScopedAcc a, StableSharingAcc)+        abstract (ScopedAcc _   (AvarSharing _ _))     _    = internalError "AvarSharing"+        abstract (ScopedAcc ssa (AletSharing sa acc))  lets = abstract acc (lets . ScopedAcc ssa . AletSharing sa)+        abstract acc@(ScopedAcc ssa (AccSharing sn a)) lets = (ScopedAcc ssa (AvarSharing sn $ Smart.arraysR a), StableSharingAcc sn (lets acc))++        -- Occurrence count of the currently processed node+        expOccCount = let StableNameHeight sn' _ = sn+                       in lookupWithASTName expOccMap (StableASTName sn')++        -- Reconstruct the current tree node.+        --+        -- * If the current node is being shared ('expOccCount > 1'), replace it by a 'VarSharing'+        --   node and float the shared subtree out wrapped in a 'NodeCounts' value.+        -- * If the current node is not shared, reconstruct it in place.+        -- * Special case for free variables ('Tag'): Replace the tree by a sharing variable and+        --   float the 'Tag' out in a 'NodeCounts' value.  This is independent of the number of+        --   occurrences.+        --+        -- In either case, any completed 'NodeCounts' are injected as bindings using 'LetSharing'+        -- node.+        --+        reconstruct+            :: HasCallStack+            => PreSmartExp ScopedAcc ScopedExp t+            -> NodeCounts+            -> (ScopedExp t, NodeCounts)+        reconstruct newExp@(Tag tp _) _subCount+              -- free variable => replace by a sharing variable regardless of the number of+              -- occurrences+          = let thisCount = StableSharingExp sn (ExpSharing sn newExp) `insertExpNode` noNodeCounts+            in+            tracePure "FREE" (show thisCount)+            (ScopedExp [] (VarSharing sn tp), thisCount)+        reconstruct newExp subCount+              -- shared subtree => replace by a sharing variable (if 'recoverExpSharing' enabled)+          | expOccCount > 1 && exp_sharing `member` options config+          = let allCount = StableSharingExp sn sharingExp `insertExpNode` newCount+            in+            tracePure ("SHARED" ++ completed) (show allCount)+            (ScopedExp [] (VarSharing sn $ typeR newExp), allCount)+              -- neither shared nor free variable => leave it as it is+          | otherwise+          = tracePure ("Normal" ++ completed) (show newCount)+            (ScopedExp [] sharingExp, newCount)+          where+              -- Determine the bindings that need to be attached to the current node...+            (newCount, bindHere) = filterCompleted subCount++              -- ...and wrap them in 'LetSharing' constructors+            lets       = foldl (flip (.)) id . map (\x y -> LetSharing x (ScopedExp [] y)) $ bindHere+            sharingExp = lets $ ExpSharing sn newExp++              -- trace support+            completed | null bindHere = ""+                      | otherwise     = "(" ++ show (length bindHere) ++ " lets)"++        -- Extract *leading* nodes that have a complete node count (i.e., their node count is equal+        -- to the number of occurrences of that node in the overall expression).+        --+        -- Nodes with a completed node count should be let bound at the currently processed node.+        --+        -- NB: Only extract leading nodes (i.e., the longest run at the *front* of the list that is+        --     complete).  Otherwise, we would let-bind subterms before their parents, which leads+        --     scope errors.+        --+        filterCompleted :: HasCallStack => NodeCounts -> (NodeCounts, [StableSharingExp])+        filterCompleted (ns,graph)+          = let bindable       = map (isBindable bindable (map nodeName ns)) ns+                (bind, unbind) = partition fst $ zip bindable ns+            in ((map snd unbind, graph), [se | ExpNodeCount se _ <- map snd bind])+          where+            -- a node is not yet complete while the node count 'n' is below the overall number+            -- of occurrences for that node in the whole program, with the exception that free+            -- variables are never complete+            isCompleted nc@(ExpNodeCount sa n) | not . isFreeVar $ nc = lookupWithSharingExp expOccMap sa == n+            isCompleted _                                             = False++            isBindable :: [Bool] -> [NodeName] -> NodeCount -> Bool+            isBindable bindable nodes nc@(ExpNodeCount _ _) =+              let superTerms = Set.toList $ graph Map.! nodeName nc+                  unbound    = mapMaybe (`elemIndex` nodes) superTerms+              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.+--+-- Also returns the 'StableSharingAcc's of all 'Atag' leaves in environment order — they represent+-- the free variables of the AST.+--+-- NB: Strictly speaking, this function is not deterministic, as it uses stable pointers to+--     determine the sharing of subterms.  The stable pointer API does not guarantee its+--     completeness; i.e., it may miss some equalities, which implies that we may fail to discover+--     some sharing.  However, sharing does not affect the denotational meaning of an array+--     computation; hence, we do not compromise denotational correctness.+--+--     There is one caveat: We currently rely on the 'Atag' and 'Tag' leaves representing free+--     variables to be shared if any of them is used more than once.  If one is duplicated, the+--     environment for de Bruijn conversion will have a duplicate entry, and hence, be of the wrong+--     size, which is fatal. (The 'buildInitialEnv*' functions will already bail out.)+--+{-# NOINLINE recoverSharingAcc #-}+recoverSharingAcc+    :: HasCallStack+    => Config+    -> Level            -- The level of currently bound array variables+    -> [Level]          -- The tags of newly introduced free array variables+    -> SmartAcc a+    -> (ScopedAcc a, [StableSharingAcc])+recoverSharingAcc config alvl avars acc+  = let (acc', occMap)+          = unsafePerformIO             -- to enable stable pointers; this is safe as explained above+          $ makeOccMapAcc config alvl acc+    in+    determineScopesAcc config avars occMap acc'+++{-# NOINLINE recoverSharingExp #-}+recoverSharingExp+    :: HasCallStack+    => Config+    -> Level            -- The level of currently bound scalar variables+    -> [Level]          -- The tags of newly introduced free scalar variables+    -> SmartExp e+    -> (ScopedExp e, [StableSharingExp])+recoverSharingExp config lvl fvar exp+  = let+        (rootExp, accOccMap) = unsafePerformIO $ do+          accOccMap       <- newASTHashTable+          (exp', _)       <- makeOccMapRootExp config accOccMap lvl fvar exp+          frozenAccOccMap <- freezeOccMap accOccMap++          return (exp', frozenAccOccMap)++        (ScopedExp sse sharingExp, _) =+          determineScopesExp config accOccMap rootExp+    in+    (ScopedExp [] sharingExp, sse)+++{--+{-# NOINLINE recoverSharingSeq #-}+recoverSharingSeq+    :: Config     -> Seq e     -> (ScopedSeq e, [StableSharingSeq]) recoverSharingSeq config seq
src/Data/Array/Accelerate/Trafo/Shrink.hs view
@@ -1,14 +1,20 @@+{-# LANGUAGE TupleSections       #-}+{-# LANGUAGE CPP                 #-} {-# LANGUAGE GADTs               #-}+{-# LANGUAGE OverloadedStrings   #-} {-# LANGUAGE PatternGuards       #-} {-# LANGUAGE RankNTypes          #-} {-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TemplateHaskell     #-}+{-# LANGUAGE TypeApplications    #-}+{-# LANGUAGE TypeOperators       #-} {-# LANGUAGE ViewPatterns        #-} -- | -- Module      : Data.Array.Accelerate.Trafo.Shrink--- Copyright   : [2012..2017] Manuel M T Chakravarty, Gabriele Keller, Trevor L. McDonell+-- Copyright   : [2012..2020] The Accelerate Team -- License     : BSD3 ----- Maintainer  : Trevor L. McDonell <tmcdonell@cse.unsw.edu.au>+-- Maintainer  : Trevor L. McDonell <trevor.mcdonell@gmail.com> -- Stability   : experimental -- Portability : non-portable (GHC extensions) --@@ -28,41 +34,194 @@ module Data.Array.Accelerate.Trafo.Shrink (    -- Shrinking-  Shrink(..),-  ShrinkAcc, shrinkPreAcc, basicReduceAcc,+  ShrinkAcc,+  shrinkExp,+  shrinkFun,    -- Occurrence counting   UsesOfAcc, usesOfPreAcc, usesOfExp,  ) where --- standard library-import Data.Monoid-import Control.Applicative                              hiding ( Const )-import Prelude                                          hiding ( exp, seq )---- friends import Data.Array.Accelerate.AST-import Data.Array.Accelerate.Array.Sugar               hiding ( Any )-import Data.Array.Accelerate.Trafo.Base+import Data.Array.Accelerate.AST.Environment+import Data.Array.Accelerate.AST.Idx+import Data.Array.Accelerate.AST.LeftHandSide+import Data.Array.Accelerate.AST.Var+import Data.Array.Accelerate.Analysis.Match+import Data.Array.Accelerate.Error+import Data.Array.Accelerate.Representation.Type import Data.Array.Accelerate.Trafo.Substitution -import qualified Data.Array.Accelerate.Debug            as Stats+import qualified Data.Array.Accelerate.Debug.Stats                  as Stats +import Control.Applicative                                          hiding ( Const )+import Data.Maybe                                                   ( isJust )+import Data.Monoid+import Data.Semigroup+import Prelude                                                      hiding ( exp, seq ) -class Shrink f where-  shrink  :: f -> f-  shrink' :: f -> (Bool, f) -  shrink = snd . shrink'+data VarsRange env =+  VarsRange !(Exists (Idx env))     -- rightmost variable+            {-# UNPACK #-} !Int     -- count+            !(Maybe RangeTuple)     -- tuple -instance Kit acc => Shrink (PreOpenExp acc env aenv e) where-  shrink' = shrinkExp+data RangeTuple+  = RTNil+  | RTSingle+  | RTPair !RangeTuple !RangeTuple -instance Kit acc => Shrink (PreOpenFun acc env aenv f) where-  shrink' = shrinkFun+lhsVarsRange :: LeftHandSide s v env env' -> Either (env :~: env') (VarsRange env')+lhsVarsRange lhs = case rightIx lhs of+  Left eq -> Left eq+  Right ix -> let (n, rt) = go lhs+              in  Right $ VarsRange ix n rt+  where+    rightIx :: LeftHandSide s v env env' -> Either (env :~: env') (Exists (Idx env'))+    rightIx (LeftHandSideWildcard _) = Left Refl+    rightIx (LeftHandSideSingle _)   = Right $ Exists ZeroIdx+    rightIx (LeftHandSidePair l1 l2) = case rightIx l2 of+      Right ix  -> Right ix+      Left Refl -> rightIx l1 +    go :: LeftHandSide s v env env' -> (Int, Maybe (RangeTuple))+    go (LeftHandSideWildcard TupRunit)   = (0,       Just RTNil)+    go (LeftHandSideWildcard _)          = (0,       Nothing)+    go (LeftHandSideSingle _)            = (1,       Just RTSingle)+    go (LeftHandSidePair l1 l2)          = (n1 + n2, RTPair <$> t1 <*> t2)+      where+        (n1, t1) = go l1+        (n2, t2) = go l2 +weakenVarsRange :: LeftHandSide s v env env' -> VarsRange env -> VarsRange env'+weakenVarsRange lhs (VarsRange ix n t) = VarsRange (go lhs ix) n t+  where+    go :: LeftHandSide s v env env' -> Exists (Idx env) -> Exists (Idx env')+    go (LeftHandSideWildcard _) ix'          = ix'+    go (LeftHandSideSingle _)   (Exists ix') = Exists (SuccIdx ix')+    go (LeftHandSidePair l1 l2) ix'          = go l2 $ go l1 ix'++matchEVarsRange :: VarsRange env -> OpenExp env aenv t -> Bool+matchEVarsRange (VarsRange (Exists first) _ (Just rt)) expr = isJust $ go (idxToInt first) rt expr+  where+    go :: Int -> RangeTuple -> OpenExp env aenv t -> Maybe Int+    go i RTNil Nil = Just i+    go i RTSingle (Evar (Var _ ix))+      | checkIdx i ix = Just (i + 1)+    go i (RTPair t1 t2) (Pair e1 e2)+      | Just i' <- go i t2 e2 = go i' t1 e1+    go _ _ _ = Nothing++    checkIdx :: Int -> Idx env t ->  Bool+    checkIdx 0 ZeroIdx = True+    checkIdx i (SuccIdx ix) = checkIdx (i - 1) ix+    checkIdx _ _ = False+matchEVarsRange _ _ = False++varInRange :: VarsRange env -> Var s env t -> Maybe Usages+varInRange (VarsRange (Exists rangeIx) n _) (Var _ varIx) = case go rangeIx varIx of+    Nothing -> Nothing+    Just j  -> Just $ replicate j False ++ [True] ++ replicate (n - j - 1) False+  where+    -- `go ix ix'` checks whether ix <= ix' with recursion, and then checks+    -- whether ix' < ix + n in go'. Returns a Just if both checks+    -- are successful, containing an integer j such that ix + j = ix'.+    go :: Idx env u -> Idx env t -> Maybe Int+    go (SuccIdx ix) (SuccIdx ix') = go ix ix'+    go ZeroIdx      ix'           = go' ix' 0+    go _            ZeroIdx       = Nothing++    go' :: Idx env t -> Int -> Maybe Int+    go' _ j | j >= n    = Nothing+    go' ZeroIdx       j = Just j+    go' (SuccIdx ix') j = go' ix' (j + 1)++-- Describes how often the variables defined in a LHS are used together.+data Count+  = Impossible !Usages+      -- Cannot inline this definition. This happens when the definition+      -- declares multiple variables (the right hand side returns a tuple)+      -- and the variables are used seperately.+  | Infinity+      -- The variable is used in a loop. Inlining should only proceed if+      -- the computation is cheap.+  | Finite {-# UNPACK #-} !Int++type Usages = [Bool] -- Per variable a Boolean denoting whether that variable is used.++instance Semigroup Count where+  Impossible u1 <> Impossible u2 = Impossible $ zipWith (||) u1 u2+  Impossible u  <> Finite 0      = Impossible u+  Finite 0      <> Impossible u  = Impossible u+  Impossible u  <> _             = Impossible $ map (const True) u+  _             <> Impossible u  = Impossible $ map (const True) u+  Infinity      <> _             = Infinity+  _             <> Infinity      = Infinity+  Finite a      <> Finite b      = Finite $ a + b++instance Monoid Count where+  mempty = Finite 0++loopCount :: Count -> Count+loopCount (Finite n) | n > 0 = Infinity+loopCount c                  = c++shrinkLhs+    :: HasCallStack+    => Count+    -> LeftHandSide s t env1 env2+    -> Maybe (Exists (LeftHandSide s t env1))+shrinkLhs _ (LeftHandSideWildcard _) = Nothing -- We cannot shrink this+shrinkLhs (Finite 0)          lhs = Just $ Exists $ LeftHandSideWildcard $ lhsToTupR lhs -- LHS isn't used at all, replace with a wildcard+shrinkLhs (Impossible usages) lhs = case go usages lhs of+    (True , [], lhs') -> Just lhs'+    (False, [], _   ) -> Nothing -- No variables were dropped. Thus lhs == lhs'.+    _                 -> internalError "Mismatch in length of usages array and LHS"+  where+    go :: HasCallStack => Usages -> LeftHandSide s t env1 env2 -> (Bool, Usages, Exists (LeftHandSide s t env1))+    go us           (LeftHandSideWildcard tp) = (False, us, Exists $ LeftHandSideWildcard tp)+    go (True  : us) (LeftHandSideSingle tp)   = (False, us, Exists $ LeftHandSideSingle tp)+    go (False : us) (LeftHandSideSingle tp)   = (True , us, Exists $ LeftHandSideWildcard $ TupRsingle tp)+    go us           (LeftHandSidePair l1 l2)+      | (c2, us' , Exists l2') <- go us  l2+      , (c1, us'', Exists l1') <- go us' l1+      , Exists l2'' <- rebuildLHS l2'+      = let+          lhs'+            | LeftHandSideWildcard t1 <- l1'+            , LeftHandSideWildcard t2 <- l2'' = LeftHandSideWildcard $ TupRpair t1 t2+            | otherwise = LeftHandSidePair l1' l2''+        in+          (c1 || c2, us'', Exists lhs')+    go _ _ = internalError "Empty array, mismatch in length of usages array and LHS"+shrinkLhs _ _ = Nothing++-- The first LHS should be 'larger' than the second, eg the second may have+-- a wildcard if the first LHS does bind variables there, but not the other+-- way around.+--+strengthenShrunkLHS+    :: HasCallStack+    => LeftHandSide s t env1 env2+    -> LeftHandSide s t env1' env2'+    -> env1 :?> env1'+    -> env2 :?> env2'+strengthenShrunkLHS (LeftHandSideWildcard _) (LeftHandSideWildcard _) k = k+strengthenShrunkLHS (LeftHandSideSingle _)   (LeftHandSideSingle _)   k = \ix -> case ix of+  ZeroIdx     -> Just ZeroIdx+  SuccIdx ix' -> SuccIdx <$> k ix'+strengthenShrunkLHS (LeftHandSidePair lA hA) (LeftHandSidePair lB hB) k = strengthenShrunkLHS hA hB $ strengthenShrunkLHS lA lB k+strengthenShrunkLHS (LeftHandSideSingle _)   (LeftHandSideWildcard _) k = \ix -> case ix of+  ZeroIdx     -> Nothing+  SuccIdx ix' -> k ix'+strengthenShrunkLHS (LeftHandSidePair l h)   (LeftHandSideWildcard t) k = strengthenShrunkLHS h (LeftHandSideWildcard t2) $ strengthenShrunkLHS l (LeftHandSideWildcard t1) k+  where+    TupRpair t1 t2 = t+strengthenShrunkLHS (LeftHandSideWildcard _) _                        _ = internalError "Second LHS defines more variables"+strengthenShrunkLHS _                        _                        _ = internalError "Mismatch LHS single with LHS pair"++ -- Shrinking -- ========= @@ -70,8 +229,8 @@ -- instance of beta-reduction to cases where the bound variable is used zero -- (dead-code elimination) or one (linear inlining) times. ---shrinkExp :: Kit acc => PreOpenExp acc env aenv t -> (Bool, PreOpenExp acc env aenv t)-shrinkExp = Stats.substitution "shrink exp" . first getAny . shrinkE+shrinkExp :: HasCallStack => OpenExp env aenv t -> (Bool, OpenExp env aenv t)+shrinkExp = Stats.substitution "shrinkE" . 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@@ -80,35 +239,65 @@     lIMIT :: Int     lIMIT = 1 -    shrinkE :: Kit acc => PreOpenExp acc env aenv t -> (Any, PreOpenExp acc env aenv t)+    cheap :: OpenExp env aenv t -> Bool+    cheap (Evar _)       = True+    cheap (Pair e1 e2)   = cheap e1 && cheap e2+    cheap Nil            = True+    cheap Const{}        = True+    cheap PrimConst{}    = True+    cheap Undef{}        = True+    cheap (Coerce _ _ e) = cheap e+    cheap _              = False++    shrinkE :: HasCallStack => OpenExp env aenv t -> (Any, OpenExp env aenv t)     shrinkE exp = case exp of-      Let bnd body-        | Var _ <- bnd  -> Stats.inline "Var"   . yes $ shrinkE (inline body bnd)-        | uses <= lIMIT -> Stats.betaReduce msg . yes $ shrinkE (inline (snd body') (snd bnd'))-        | otherwise     -> Let <$> bnd' <*> body'+      Let (LeftHandSideSingle _) bnd@Evar{} body -> Stats.inline "Var"   . yes $ shrinkE (inline body bnd)+      Let lhs bnd body+        | shouldInline -> case inlineVars lhs (snd body') (snd bnd') of+            Just inlined -> Stats.betaReduce msg . yes $ shrinkE inlined+            _            -> internalError "Unexpected failure while trying to inline some expression."+        | Just (Exists lhs') <- shrinkLhs count lhs -> case strengthenE (strengthenShrunkLHS lhs lhs' Just) (snd body') of+           Just body'' -> (Any True, Let lhs' (snd bnd') body'')+           Nothing     -> internalError "Unexpected failure in strenthenE. Variable was analysed to be unused in usesOfExp, but appeared to be used in strenthenE."+        | otherwise    -> Let lhs <$> bnd' <*> body'         where+          shouldInline = case count of+            Finite 0     -> False -- Handled by shrinkLhs+            Finite n     -> n <= lIMIT || cheap (snd bnd')+            Infinity     ->               cheap (snd bnd')+            Impossible _ -> False+           bnd'  = shrinkE bnd           body' = shrinkE body-          uses  = usesOfExp ZeroIdx (snd body') -          msg   = case uses of-            0 -> "dead exp"-            _ -> "inline exp"   -- forced inlining when lIMIT > 1+          -- If the lhs includes non-trivial wildcards (the last field of range is Nothing),+          -- then we cannot inline the binding. We can only check which variables are not used,+          -- to detect unused variables.+          --+          -- If the lhs does not include non-trivial wildcards (the last field of range is a Just),+          -- we can both analyse whether we can inline the binding, and check which variables are+          -- not used, to detect unused variables.+          --+          count = case lhsVarsRange lhs of+            Left _      -> Finite 0+            Right range -> usesOfExp range (snd body')++          msg = case count of+            Finite 0 -> "dead exp"+            _        -> "inline exp"   -- forced inlining when lIMIT > 1       ---      Var idx                   -> pure (Var idx)-      Const c                   -> pure (Const c)-      Undef                     -> pure Undef-      Tuple t                   -> Tuple <$> shrinkT t-      Prj tup e                 -> Prj tup <$> shrinkE e-      IndexNil                  -> pure IndexNil-      IndexCons sl sz           -> IndexCons <$> shrinkE sl <*> shrinkE sz-      IndexHead sh              -> IndexHead <$> shrinkE sh-      IndexTail sh              -> IndexTail <$> shrinkE sh+      Evar v                    -> pure (Evar v)+      Const t c                 -> pure (Const t c)+      Undef t                   -> pure (Undef t)+      Nil                       -> pure Nil+      Pair x y                  -> Pair <$> shrinkE x <*> shrinkE y+      VecPack   vec e           -> VecPack   vec <$> shrinkE e+      VecUnpack vec e           -> VecUnpack vec <$> shrinkE e       IndexSlice x ix sh        -> IndexSlice x <$> shrinkE ix <*> shrinkE sh       IndexFull x ix sl         -> IndexFull x <$> shrinkE ix <*> shrinkE sl-      IndexAny                  -> pure IndexAny-      ToIndex sh ix             -> ToIndex <$> shrinkE sh <*> shrinkE ix-      FromIndex sh i            -> FromIndex <$> shrinkE sh <*> shrinkE i+      ToIndex shr sh ix         -> ToIndex shr <$> shrinkE sh <*> shrinkE ix+      FromIndex shr sh i        -> FromIndex shr <$> shrinkE sh <*> shrinkE i+      Case e rhs def            -> Case <$> shrinkE e <*> sequenceA [ (t,) <$> shrinkE c | (t,c) <- rhs ] <*> shrinkMaybeE def       Cond p t e                -> Cond <$> shrinkE p <*> shrinkE t <*> shrinkE e       While p f x               -> While <$> shrinkF p <*> shrinkF f <*> shrinkE x       PrimConst c               -> pure (PrimConst c)@@ -116,60 +305,75 @@       Index a sh                -> Index a <$> shrinkE sh       LinearIndex a i           -> LinearIndex a <$> shrinkE i       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-      Coerce e                  -> Coerce <$> shrinkE e--    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+      ShapeSize shr sh          -> ShapeSize shr <$> shrinkE sh+      Foreign repr ff f e       -> Foreign repr ff <$> shrinkF f <*> shrinkE e+      Coerce t1 t2 e            -> Coerce t1 t2 <$> shrinkE e -    shrinkF :: Kit acc => PreOpenFun acc env aenv t -> (Any, PreOpenFun acc env aenv t)+    shrinkF :: HasCallStack => OpenFun env aenv t -> (Any, OpenFun env aenv t)     shrinkF = first Any . shrinkFun +    shrinkMaybeE :: HasCallStack => Maybe (OpenExp env aenv t) -> (Any, Maybe (OpenExp env aenv t))+    shrinkMaybeE Nothing  = pure Nothing+    shrinkMaybeE (Just e) = Just <$> shrinkE e+     first :: (a -> a') -> (a,b) -> (a',b)     first f (x,y) = (f x, y)      yes :: (Any, x) -> (Any, x)     yes (_, x) = (Any True, x) -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+shrinkFun :: HasCallStack => OpenFun env aenv f -> (Bool, OpenFun env aenv f)+shrinkFun (Lam lhs f) = case lhsVarsRange lhs of+  Left Refl ->+    let b' = case lhs of+                LeftHandSideWildcard TupRunit -> b+                _                             -> True+    in (b', Lam (LeftHandSideWildcard $ lhsToTupR lhs) f')+  Right range ->+    let+      count = usesOfFun range f+    in case shrinkLhs count lhs of+        Just (Exists lhs') -> case strengthenE (strengthenShrunkLHS lhs lhs' Just) f' of+          Just f'' -> (True, Lam lhs' f'')+          Nothing  -> internalError "Unexpected failure in strenthenE. Variable was analysed to be unused in usesOfExp, but appeared to be used in strenthenE."+        Nothing -> (b, Lam lhs f')+  where+    (b, f') = shrinkFun f +shrinkFun (Body b) = Body <$> shrinkExp b  -- The shrinking substitution for array computations. This is further limited to -- dead-code elimination only, primarily because linear inlining may inline -- array computations into scalar expressions, which is generally not desirable. ---type ShrinkAcc acc = forall aenv a.   acc aenv a -> acc aenv a+type ShrinkAcc acc = forall aenv a. acc aenv a -> acc aenv a++{-- type ReduceAcc acc = forall aenv s t. acc aenv s -> acc (aenv,s) t -> Maybe (PreOpenAcc acc aenv t)  shrinkPreAcc     :: forall acc aenv arrs. ShrinkAcc acc -> ReduceAcc acc     -> PreOpenAcc acc aenv arrs     -> PreOpenAcc acc aenv arrs-shrinkPreAcc shrinkAcc reduceAcc = Stats.substitution "shrink acc" shrinkA+shrinkPreAcc shrinkAcc reduceAcc = Stats.substitution "shrinkA" shrinkA   where     shrinkA :: PreOpenAcc acc aenv' a -> PreOpenAcc acc aenv' a     shrinkA pacc = case pacc of-      Alet bnd body+      Alet lhs bnd body         | Just reduct <- reduceAcc bnd' body'   -> shrinkA reduct-        | otherwise                             -> Alet bnd' body'+        | otherwise                             -> Alet lhs bnd' body'         where           bnd'  = shrinkAcc bnd           body' = shrinkAcc body       --       Avar ix                   -> Avar ix-      Atuple tup                -> Atuple (shrinkAT tup)-      Aprj tup a                -> Aprj tup (shrinkAcc a)-      Apply f a                 -> Apply (shrinkAF f) (shrinkAcc a)+      Apair a1 a2               -> Apair (shrinkAcc a1) (shrinkAcc a2)+      Anil                      -> Anil+      Apply repr f a            -> Apply repr (shrinkAF f) (shrinkAcc a)       Aforeign ff af a          -> Aforeign ff af (shrinkAcc a)       Acond p t e               -> Acond (shrinkE p) (shrinkAcc t) (shrinkAcc e)       Awhile p f a              -> Awhile (shrinkAF p) (shrinkAF f) (shrinkAcc a)-      Use a                     -> Use a+      Use repr a                -> Use repr a       Unit e                    -> Unit (shrinkE e)       Reshape e a               -> Reshape (shrinkE e) (shrinkAcc a)       Generate e f              -> Generate (shrinkE e) (shrinkF f)@@ -224,7 +428,7 @@     shrinkCT (SnocAtup t c) = SnocAtup (shrinkCT t) (shrinkC c) --} -    shrinkE :: PreOpenExp acc env aenv' t -> PreOpenExp acc env aenv' t+    shrinkE :: OpenExp env aenv' t -> OpenExp env aenv' t     shrinkE exp = case exp of       Let bnd body              -> Let (shrinkE bnd) (shrinkE body)       Var idx                   -> Var idx@@ -254,48 +458,18 @@       Foreign ff f e            -> Foreign ff (shrinkF f) (shrinkE e)       Coerce e                  -> Coerce (shrinkE e) -    shrinkF :: PreOpenFun acc env aenv' f -> PreOpenFun acc env aenv' f+    shrinkF :: OpenFun env aenv' f -> OpenFun env aenv' f     shrinkF (Lam f)  = Lam (shrinkF f)     shrinkF (Body b) = Body (shrinkE b) -    shrinkT :: Tuple (PreOpenExp acc env aenv') t -> Tuple (PreOpenExp acc env aenv') t+    shrinkT :: Tuple (OpenExp env aenv') t -> Tuple (OpenExp env aenv') t     shrinkT NilTup        = NilTup     shrinkT (SnocTup t e) = shrinkT t `SnocTup` shrinkE e -    shrinkAT :: Atuple (acc aenv') t -> Atuple (acc aenv') t-    shrinkAT NilAtup        = NilAtup-    shrinkAT (SnocAtup t a) = shrinkAT t `SnocAtup` shrinkAcc a-     shrinkAF :: PreOpenAfun acc aenv' f -> PreOpenAfun acc aenv' f-    shrinkAF (Alam  f) = Alam (shrinkAF f)+    shrinkAF (Alam lhs f) = Alam lhs (shrinkAF f)     shrinkAF (Abody a) = Abody (shrinkAcc a)----- A somewhat hacky example implementation of the reduction step. It requires a--- function to open the recursive closure of an array term.----basicReduceAcc-    :: Kit acc-    => (forall aenv a. acc aenv a -> PreOpenAcc acc aenv a)-    -> UsesOfAcc acc-    -> ReduceAcc acc-basicReduceAcc unwrapAcc countAcc (unwrapAcc -> bnd) body@(unwrapAcc -> 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-    -- into the body. Since this implies an array computation could be inlined-    -- into a scalar expression, we limit the shrinking reduction for array-    -- computations to dead-code elimination only.-    ---    lIMIT = 0--    uses  = countAcc True ZeroIdx body-    msg   = case uses of-      0 -> "dead acc"-      _ -> "inline acc"         -- forced inlining when lIMIT > 1-+--}  -- Occurrence Counting -- ===================@@ -303,50 +477,42 @@ -- Count the number of occurrences an in-scope scalar expression bound at the -- given variable index recursively in a term. ---usesOfExp :: forall acc env aenv s t. Idx env s -> PreOpenExp acc env aenv t -> Int-usesOfExp idx = countE+usesOfExp :: forall env aenv t. VarsRange env -> OpenExp env aenv t -> Count+usesOfExp range = countE   where-    countE :: PreOpenExp acc env aenv e -> Int+    countE :: OpenExp env aenv e -> Count+    countE exp | matchEVarsRange range exp = Finite 1     countE exp = case exp of-      Var this-        | Just Refl <- match this idx   -> 1-        | otherwise                     -> 0+      Evar v -> case varInRange range v of+        Just cs                 -> Impossible cs+        Nothing                 -> Finite 0       ---      Let bnd body              -> countE bnd + usesOfExp (SuccIdx idx) body-      Const _                   -> 0-      Undef                     -> 0-      Tuple t                   -> countT t-      Prj _ e                   -> countE e-      IndexNil                  -> 0-      IndexCons sl sz           -> countE sl + countE sz-      IndexHead sh              -> countE sh-      IndexTail sh              -> countE sh-      IndexSlice _ ix sh        -> countE ix + countE sh-      IndexFull _ ix sl         -> countE ix + countE sl-      IndexAny                  -> 0-      ToIndex sh ix             -> countE sh + countE ix-      FromIndex sh i            -> countE sh + countE i-      Cond p t e                -> countE p  + countE t + countE e-      While p f x               -> countE x  + countF idx p + countF idx f-      PrimConst _               -> 0+      Let lhs bnd body          -> countE bnd <> usesOfExp (weakenVarsRange lhs range) body+      Const _ _                 -> Finite 0+      Undef _                   -> Finite 0+      Nil                       -> Finite 0+      Pair e1 e2                -> countE e1 <> countE e2+      VecPack   _ e             -> countE e+      VecUnpack _ e             -> countE e+      IndexSlice _ ix sh        -> countE ix <> countE sh+      IndexFull _ ix sl         -> countE ix <> countE sl+      FromIndex _ sh i          -> countE sh <> countE i+      ToIndex _ sh e            -> countE sh <> countE e+      Case e rhs def            -> countE e  <> mconcat [ countE c | (_,c) <- rhs ] <> maybe (Finite 0) countE def+      Cond p t e                -> countE p  <> countE t <> countE e+      While p f x               -> countE x  <> loopCount (usesOfFun range p) <> loopCount (usesOfFun range f)+      PrimConst _               -> Finite 0       PrimApp _ x               -> countE x       Index _ sh                -> countE sh       LinearIndex _ i           -> countE i-      Shape _                   -> 0-      ShapeSize sh              -> countE sh-      Intersect sh sz           -> countE sh + countE sz-      Union sh sz               -> countE sh + countE sz-      Foreign _ _ e             -> countE e-      Coerce e                  -> countE e--    countF :: Idx env' s -> PreOpenFun acc env' aenv f -> Int-    countF idx' (Lam  f) = countF (SuccIdx idx') f-    countF idx' (Body b) = usesOfExp idx' b--    countT :: Tuple (PreOpenExp acc env aenv) e -> Int-    countT NilTup        = 0-    countT (SnocTup t e) = countT t + countE e+      Shape _                   -> Finite 0+      ShapeSize _ sh            -> countE sh+      Foreign _ _ _ e           -> countE e+      Coerce _ _ e              -> countE e +usesOfFun :: VarsRange env -> OpenFun env aenv f -> Count+usesOfFun range (Lam lhs f) = usesOfFun (weakenVarsRange lhs range) f+usesOfFun range (Body b)    = usesOfExp range b  -- Count the number of occurrences of the array term bound at the given -- environment index. If the first argument is 'True' then it includes in the@@ -354,6 +520,8 @@ -- type UsesOfAcc acc = forall aenv s t. Bool -> Idx aenv s -> acc aenv t -> Int +-- XXX: Should this be converted to use the above 'Count' semigroup?+-- usesOfPreAcc     :: forall acc aenv s t.        Bool@@ -365,97 +533,89 @@   where     countIdx :: Idx aenv a -> Int     countIdx this-        | Just Refl <- match this idx   = 1-        | otherwise                     = 0+        | Just Refl <- matchIdx this idx = 1+        | otherwise                      = 0      count :: PreOpenAcc acc aenv a -> Int     count pacc = case pacc of-      Avar this                 -> countIdx this+      Avar var                   -> countAvar var       ---      Alet bnd body             -> countA bnd + countAcc withShape (SuccIdx idx) body-      Atuple tup                -> countAT tup-      Aprj _ a                  -> countA a     -- special case discount?-      Apply _ a                 -> countA a-      Aforeign _ _ a            -> countA a-      Acond p t e               -> countE p  + countA t + countA e-      Awhile _ _ a              -> countA a-      Use _                     -> 0-      Unit e                    -> countE e-      Reshape e a               -> countE e  + countA a-      Generate e f              -> countE e  + countF f-      Transform sh ix f a       -> countE sh + countF ix + countF f  + countA a-      Replicate _ sh a          -> countE sh + countA a-      Slice _ a sl              -> countE sl + countA a-      Map f a                   -> countF f  + countA a-      ZipWith f a1 a2           -> countF f  + countA a1 + countA a2-      Fold f z a                -> countF f  + countE z  + countA a-      Fold1 f a                 -> countF f  + countA a-      FoldSeg f z a s           -> countF f  + countE z  + countA a  + countA s-      Fold1Seg f a s            -> countF f  + countA a  + countA s-      Scanl f z a               -> countF f  + countE z  + countA a-      Scanl' f z a              -> countF f  + countE z  + countA a-      Scanl1 f a                -> countF f  + countA a-      Scanr f z a               -> countF f  + countE z  + countA a-      Scanr' f z a              -> countF f  + countE z  + countA a-      Scanr1 f a                -> countF f  + countA a-      Permute f1 a1 f2 a2       -> countF f1 + countA a1 + countF f2 + countA a2-      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+      Alet lhs bnd body          -> countA bnd + countAcc withShape (weakenWithLHS lhs >:> idx) body+      Apair a1 a2                -> countA a1 + countA a2+      Anil                       -> 0+      Apply _ f a                -> countAF f idx + countA a+      Aforeign _ _ _ a           -> countA a+      Acond p t e                -> countE p + countA t + countA e+      -- Body and condition of the while loop may be evaluated multiple times.+      -- We multiply the usage count, as a practical solution to this. As+      -- we will check whether the count is at most 1, we will thus never+      -- inline variables used in while loops.+      Awhile c f a               -> 2 * countAF c idx + 2 * countAF f idx + countA a+      Use _ _                    -> 0+      Unit _ e                   -> countE e+      Reshape _ e a              -> countE e  + countA a+      Generate _ e f             -> countE e  + countF f+      Transform _ sh ix f a      -> countE sh + countF ix + countF f  + countA a+      Replicate _ sh a           -> countE sh + countA a+      Slice _ a sl               -> countE sl + countA a+      Map _ f a                  -> countF f  + countA a+      ZipWith _ f a1 a2          -> countF f  + countA a1 + countA a2+      Fold f z a                 -> countF f  + countME z + countA a+      FoldSeg _ f z a s          -> countF f  + countME z + countA a  + countA s+      Scan  _ f z a              -> countF f  + countME z + countA a+      Scan' _ f z a              -> countF f  + countE z  + countA a+      Permute f1 a1 f2 a2        -> countF f1 + countA a1 + countF f2 + countA a2+      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       -- Collect s                 -> countS s -    countE :: PreOpenExp acc env aenv e -> Int+    countE :: OpenExp env aenv e -> Int     countE exp = case exp of-      Let bnd body              -> countE bnd + countE body-      Var _                     -> 0-      Const _                   -> 0-      Undef                     -> 0-      Tuple t                   -> countT t-      Prj _ e                   -> countE e-      IndexNil                  -> 0-      IndexCons sl sz           -> countE sl + countE sz-      IndexHead sh              -> countE sh-      IndexTail sh              -> countE sh-      IndexSlice _ ix sh        -> countE ix + countE sh-      IndexFull _ ix sl         -> countE ix + countE sl-      IndexAny                  -> 0-      ToIndex sh ix             -> countE sh + countE ix-      FromIndex sh i            -> countE sh + countE i-      Cond p t e                -> countE p  + countE t + countE e-      While p f x               -> countF p  + countF f + countE x-      PrimConst _               -> 0-      PrimApp _ x               -> countE x-      Index a sh                -> countA a + countE sh-      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+      Let _ bnd body             -> countE bnd + countE body+      Evar _                     -> 0+      Const _ _                  -> 0+      Undef _                    -> 0+      Nil                        -> 0+      Pair x y                   -> countE x + countE y+      VecPack   _ e              -> countE e+      VecUnpack _ e              -> countE e+      IndexSlice _ ix sh         -> countE ix + countE sh+      IndexFull _ ix sl          -> countE ix + countE sl+      ToIndex _ sh ix            -> countE sh + countE ix+      FromIndex _ sh i           -> countE sh + countE i+      Case e rhs def             -> countE e  + sum [ countE c | (_,c) <- rhs ] + maybe 0 countE def+      Cond p t e                 -> countE p  + countE t + countE e+      While p f x                -> countF p  + countF f + countE x+      PrimConst _                -> 0+      PrimApp _ x                -> countE x+      Index a sh                 -> countAvar a + countE sh+      LinearIndex a i            -> countAvar a + countE i+      ShapeSize _ sh             -> countE sh       Shape a-        | withShape             -> countA a-        | otherwise             -> 0-      Foreign _ _ e             -> countE e-      Coerce e                  -> countE e+        | withShape              -> countAvar a+        | otherwise              -> 0+      Foreign _ _ _ e            -> countE e+      Coerce _ _ e               -> countE e +    countME :: Maybe (OpenExp env aenv e) -> Int+    countME = maybe 0 countE+     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+    countAvar :: ArrayVar aenv a -> Int+    countAvar (Var _ this) = countIdx this -    countT :: Tuple (PreOpenExp acc env aenv) e -> Int-    countT NilTup        = 0-    countT (SnocTup t e) = countT t + countE e+    countAF :: PreOpenAfun acc aenv' f+            -> Idx aenv' s+            -> Int+    countAF (Alam lhs f) v = countAF f (weakenWithLHS lhs >:> v)+    countAF (Abody a)    v = countAcc withShape v a -    countAT :: Atuple (acc aenv) a -> Int-    countAT NilAtup        = 0-    countAT (SnocAtup t a) = countAT t + countA a+    countF :: OpenFun env aenv f -> Int+    countF (Lam _ f) = countF f+    countF (Body  b) = countE b  {--     countS :: PreOpenSeq acc aenv senv arrs -> Int
src/Data/Array/Accelerate/Trafo/Simplify.hs view
@@ -2,63 +2,62 @@ {-# LANGUAGE FlexibleContexts     #-} {-# LANGUAGE FlexibleInstances    #-} {-# LANGUAGE GADTs                #-}+{-# LANGUAGE OverloadedStrings    #-} {-# LANGUAGE PatternGuards        #-} {-# LANGUAGE RankNTypes           #-} {-# LANGUAGE RecordWildCards      #-} {-# LANGUAGE ScopedTypeVariables  #-}-{-# LANGUAGE TemplateHaskell      #-}+{-# LANGUAGE TupleSections        #-}+{-# LANGUAGE TypeApplications     #-} {-# LANGUAGE TypeOperators        #-} {-# LANGUAGE TypeSynonymInstances #-} {-# LANGUAGE ViewPatterns         #-} -- | -- Module      : Data.Array.Accelerate.Trafo.Simplify--- Copyright   : [2012..2017] Manuel M T Chakravarty, Gabriele Keller, Trevor L. McDonell+-- Copyright   : [2012..2020] The Accelerate Team -- License     : BSD3 ----- Maintainer  : Trevor L. McDonell <tmcdonell@cse.unsw.edu.au>+-- Maintainer  : Trevor L. McDonell <trevor.mcdonell@gmail.com> -- Stability   : experimental -- Portability : non-portable (GHC extensions) --  module Data.Array.Accelerate.Trafo.Simplify ( -  Simplify(..),+  simplifyFun,+  simplifyExp  ) where --- standard library-import Control.Applicative                              hiding ( Const )-import Control.Lens                                     hiding ( Const, ix )-import Data.List                                        ( nubBy )-import Data.Maybe-import Data.Monoid-import Data.Typeable-import Text.Printf-import Prelude                                          hiding ( exp, iterate )---- friends-import Data.Array.Accelerate.AST                        hiding ( prj )+import Data.Array.Accelerate.AST+import Data.Array.Accelerate.AST.Environment+import Data.Array.Accelerate.AST.Idx+import Data.Array.Accelerate.AST.LeftHandSide+import Data.Array.Accelerate.AST.Var+import Data.Array.Accelerate.Analysis.Hash import Data.Array.Accelerate.Analysis.Match-import Data.Array.Accelerate.Analysis.Shape import Data.Array.Accelerate.Error-import Data.Array.Accelerate.Product+import Data.Array.Accelerate.Representation.Array                   ( Array, ArrayR(..) )+import Data.Array.Accelerate.Representation.Shape                   ( ShapeR(..), shapeToList )+import Data.Array.Accelerate.Representation.Tag import Data.Array.Accelerate.Trafo.Algebra-import Data.Array.Accelerate.Trafo.Base+import Data.Array.Accelerate.Trafo.Environment import Data.Array.Accelerate.Trafo.Shrink+import Data.Array.Accelerate.Trafo.Substitution import Data.Array.Accelerate.Type-import Data.Array.Accelerate.Array.Sugar                ( Array, Elt(eltType), Shape, Slice, toElt, fromElt, Z(..), (:.)(..)-                                                        , Tuple(..), IsTuple, fromTuple, TupleRepr, shapeToList )-import qualified Data.Array.Accelerate.Debug            as Stats --class Simplify f where-  simplify :: f -> f--instance Kit acc => Simplify (PreFun acc aenv f) where-  simplify = simplifyFun+import qualified Data.Array.Accelerate.Debug.Stats                  as Stats+import qualified Data.Array.Accelerate.Debug.Flags                  as Debug+import qualified Data.Array.Accelerate.Debug.Trace                  as Debug -instance (Kit acc, Elt e) => Simplify (PreExp acc aenv e) where-  simplify = simplifyExp+import Control.Applicative                                          hiding ( Const )+import Control.Lens                                                 hiding ( Const, ix )+import Data.List                                                    ( partition )+import Data.Maybe+import Data.Monoid+import Text.Printf+import Prelude                                                      hiding ( exp, iterate )+import qualified Data.Map.Strict                                    as Map   -- Scalar optimisations@@ -87,10 +86,10 @@ -- tricky and target-dependent issue by, for now, simply ignoring it. -- localCSE :: (Kit acc, Elt a)-         => Gamma      acc env env aenv-         -> PreOpenExp acc env     aenv a-         -> PreOpenExp acc (env,a) aenv b-         -> Maybe (PreOpenExp acc env aenv b)+         => Gamma acc env env aenv+         -> OpenExp env aenv a+         -> OpenExp (env,a) aenv b+         -> Maybe (OpenExp env aenv b) localCSE env bnd body   | Just ix <- lookupExp env bnd = Stats.ruleFired "CSE" . Just $ inline body (Var ix)   | otherwise                    = Nothing@@ -103,9 +102,9 @@ -- > 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)+          => Gamma acc env env aenv+          -> OpenExp env aenv t+          -> Maybe (OpenExp env aenv t) globalCSE env exp   | Just ix <- lookupExp env exp = Stats.ruleFired "CSE" . Just $ Var ix   | otherwise                    = Nothing@@ -141,10 +140,10 @@ -- recoverLoops     :: (Kit acc, Elt b)-    => Gamma      acc env env aenv-    -> PreOpenExp acc env     aenv a-    -> PreOpenExp acc (env,a) aenv b-    -> Maybe (PreOpenExp acc env aenv b)+    => Gamma acc env env aenv+    -> OpenExp env aenv a+    -> OpenExp (env,a) aenv b+    -> Maybe (OpenExp env aenv b) recoverLoops _ bnd e3   -- To introduce scaler loops, we look for expressions of the form:   --@@ -179,15 +178,15 @@   = Nothing    where-    plus :: PreOpenExp acc env aenv Int -> PreOpenExp acc env aenv Int -> PreOpenExp acc env aenv Int+    plus :: OpenExp env aenv Int -> OpenExp env aenv Int -> OpenExp env aenv Int     plus x y = PrimApp (PrimAdd numType) $ Tuple $ NilTup `SnocTup` x `SnocTup` y -    constant :: Int -> PreOpenExp acc env aenv Int+    constant :: Int -> OpenExp env aenv Int     constant i = Const ((),i)      matchEnvTop :: (Elt s, Elt t)-                => PreOpenExp acc (env,s) aenv f-                -> PreOpenExp acc (env,t) aenv g+                => OpenExp (env,s) aenv f+                -> OpenExp (env,t) aenv g                 -> Maybe (s :=: t)     matchEnvTop _ _ = gcast Refl --}@@ -200,38 +199,36 @@ --       introduced by the fusion transformation. This would benefit from a --       rewrite rule schema. --+-- TODO: We currently pass around an environment Gamma, but we do not use it.+--       It might be helpful to do some inlining if this enables other optimizations.+--       Eg, for `let x = -y in -x`, the inlining would allow us to shorten it to `y`.+--       If we do not want to do inlining, we should remove the environment here.+-- simplifyOpenExp-    :: 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)+    :: forall env aenv e.+       Gamma env env aenv+    -> OpenExp env aenv e+    -> (Bool, OpenExp env aenv e) simplifyOpenExp env = first getAny . cvtE   where-    cvtE :: Elt t => PreOpenExp acc env aenv t -> (Any, PreOpenExp acc env aenv t)+    cvtE :: OpenExp env aenv t -> (Any, OpenExp env aenv t)     cvtE exp = case exp of-      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'+      Let lhs bnd body -> (u <> v, exp')         where-          bnd'  = cvtE bnd-          env'  = env `pushExp` snd bnd'-          body' = cvtE' (incExp env') body--      Var ix                    -> pure $ Var ix-      Const c                   -> pure $ Const c-      Undef                     -> pure Undef-      Tuple tup                 -> Tuple <$> cvtT tup-      Prj ix t                  -> prj env ix (cvtE t)-      IndexNil                  -> pure IndexNil-      IndexAny                  -> pure IndexAny-      IndexCons sh sz           -> indexCons (cvtE sh) (cvtE sz)-      IndexHead sh              -> indexHead (cvtE sh)-      IndexTail sh              -> indexTail (cvtE sh)+          (u, bnd') = cvtE bnd+          (v, exp') = cvtLet env lhs bnd' (\env' -> cvtE' env' body)+      Evar var                  -> pure $ Evar var+      Const tp c                -> pure $ Const tp c+      Undef tp                  -> pure $ Undef tp+      Nil                       -> pure Nil+      Pair e1 e2                -> Pair <$> cvtE e1 <*> cvtE e2+      VecPack   vec e           -> VecPack   vec <$> cvtE e+      VecUnpack vec e           -> VecUnpack vec <$> cvtE e       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 shr sh ix         -> toIndex shr (cvtE sh) (cvtE ix)+      FromIndex shr sh ix       -> fromIndex shr (cvtE sh) (cvtE ix)+      Case e rhs def            -> caseof (cvtE e) (sequenceA [ (t,) <$> cvtE c | (t,c) <- rhs ]) (cvtMaybeE def)       Cond p t e                -> cond (cvtE p) (cvtE t) (cvtE e)       PrimConst c               -> pure $ PrimConst c       PrimApp f x               -> (u<>v, fx)@@ -241,180 +238,111 @@       Index a sh                -> Index a <$> cvtE sh       LinearIndex a i           -> LinearIndex a <$> cvtE i       Shape a                   -> shape a-      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+      ShapeSize shr sh          -> shapeSize shr (cvtE sh)+      Foreign tp ff f e         -> Foreign tp ff <$> first Any (simplifyOpenFun EmptyExp f) <*> cvtE e       While p f x               -> While <$> cvtF env p <*> cvtF env f <*> cvtE x-      Coerce e                  -> Coerce <$> cvtE e--    cvtT :: Tuple (PreOpenExp acc env aenv) t -> (Any, Tuple (PreOpenExp acc env aenv) t)-    cvtT NilTup        = pure NilTup-    cvtT (SnocTup t e) = SnocTup <$> cvtT t <*> cvtE e+      Coerce t1 t2 e            -> Coerce t1 t2 <$> cvtE e -    cvtE' :: Elt e' => Gamma acc env' env' aenv -> PreOpenExp acc env' aenv e' -> (Any, PreOpenExp acc env' aenv e')+    cvtE' :: Gamma env' env' aenv -> OpenExp env' aenv e' -> (Any, OpenExp 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)+    cvtF :: Gamma env' env' aenv -> OpenFun env' aenv f -> (Any, OpenFun env' aenv f)     cvtF env' = first Any . simplifyOpenFun env' -    -- Return the minimal set of unique shapes to intersect. This is a bit-    -- inefficient, but the number of shapes is expected to be small so should-    -- be fine in practice.-    ---    intersect :: Shape t-              => (Any, PreOpenExp acc env aenv t)-              -> (Any, PreOpenExp acc env aenv t)-              -> (Any, PreOpenExp acc env aenv t)-    intersect (c1, sh1) (c2, sh2)-      | Nothing <- match sh sh' = Stats.ruleFired "intersect" (yes sh')-      | otherwise               = (c1 <> c2, sh')-      where-        sh      = Intersect sh1 sh2-        sh'     = foldl1 Intersect-                $ 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 (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]+    cvtMaybeE :: Maybe (OpenExp env aenv e') -> (Any, Maybe (OpenExp env aenv e'))+    cvtMaybeE Nothing  = pure Nothing+    cvtMaybeE (Just e) = Just <$> cvtE e +    cvtLet :: Gamma env' env' aenv+           -> ELeftHandSide bnd env' env''+           -> OpenExp env' aenv bnd+           -> (Gamma env'' env'' aenv -> (Any, OpenExp env'' aenv t))+           -> (Any, OpenExp env' aenv t)+    cvtLet env' lhs@(LeftHandSideSingle _) bnd          body = Let lhs bnd <$> body (incExp $ env' `pushExp` bnd) -- Single variable on the LHS, add binding to the environment+    cvtLet env' (LeftHandSideWildcard _)   _            body = body env'                                 -- Binding not used, remove let binding+    cvtLet env' (LeftHandSidePair l1 l2)   (Pair e1 e2) body                                             -- Split binding to multiple bindings+      = first (const $ Any True)+      $ cvtLet env' l1 e1+      $ \env'' -> cvtLet env'' l2 (weakenE (weakenWithLHS l1) e2) body+    cvtLet env' lhs                        bnd          body = Let lhs bnd <$> body (lhsExpr lhs env')   -- Cannot split this binding.      -- Simplify conditional expressions, in particular by eliminating branches     -- when the predicate is a known constant.     ---    cond :: forall t. Elt t-         => (Any, PreOpenExp acc env aenv Bool)-         -> (Any, PreOpenExp acc env aenv t)-         -> (Any, PreOpenExp acc env aenv t)-         -> (Any, PreOpenExp acc env aenv t)+    cond :: (Any, OpenExp env aenv PrimBool)+         -> (Any, OpenExp env aenv t)+         -> (Any, OpenExp env aenv t)+         -> (Any, OpenExp 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')-      | otherwise                = Cond <$> p <*> t <*> e+      | Const _ 1 <- p'                 = Stats.knownBranch "True"      (yes t')+      | Const _ 0 <- p'                 = Stats.knownBranch "False"     (yes e')+      | Just Refl <- matchOpenExp 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.-    ---    -- 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+    caseof :: (Any, OpenExp env aenv TAG)+           -> (Any, [(TAG, OpenExp env aenv b)])+           -> (Any, Maybe (OpenExp env aenv b))+           -> (Any, OpenExp env aenv b)+    caseof x@(_,x') xs@(_,xs') md@(_,md')+      | Const _ t   <- x'+      = Stats.caseElim "known" (yes (fromJust $ lookup t xs'))+      | Just d      <- md'+      , []          <- xs'+      = Stats.caseElim "redundant" (yes d)+      | Just d      <- md'+      , [(_,(_,u))] <- us+      , Just Refl   <- matchOpenExp d u+      = Stats.caseDefault "merge" $ yes (Case x' (map snd vs) (Just u))+      | Nothing     <- md'+      , []          <- vs+      , [(_,(_,u))] <- us+      = Stats.caseElim "overlap" (yes u)+      | Nothing     <- md'+      , [(_,(_,u))] <- us+      = Stats.caseDefault "introduction" $ yes (Case x' (map snd vs) (Just u))+      | otherwise+      = Case <$> x <*> xs <*> md       where-        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 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+        (us,vs) = partition (\(n,_) -> n > 1)+                $ Map.elems+                . Map.fromListWith merge+                $ [ (hashOpenExp e, (1,(t, e))) | (t,e) <- xs' ] +        merge :: (Int, (TAG, OpenExp env aenv b)) -> (Int, (TAG, OpenExp env aenv b)) -> (Int, (TAG, OpenExp env aenv b))+        merge (n,(_,a)) (m,(_,b))+          = internalCheck "hashOpenExp/collision" (maybe False (const True) (matchOpenExp a b))+          $ (n+m, (0xff, a))      -- 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 (_,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)-      | _ :. 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)-      | 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--    shape :: forall sh t. (Shape sh, Elt t) => acc aenv (Array sh t) -> (Any, PreOpenExp acc env aenv sh)-    shape _-      | Just Refl <- matchTupleType (eltType (undefined::sh)) (eltType (undefined::Z))-      = Stats.ruleFired "shape/Z" $ yes (Const (fromElt Z))+    shape :: ArrayVar aenv (Array sh t) -> (Any, OpenExp env aenv sh)+    shape (Var (ArrayR ShapeRz _) _)+      = Stats.ruleFired "shape/Z" $ yes Nil     shape a       = pure $ Shape a -    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+    shapeSize :: ShapeR sh -> (Any, OpenExp env aenv sh) -> (Any, OpenExp env aenv Int)+    shapeSize shr (_, sh)+      | Just c <- extractConstTuple sh+      = Stats.ruleFired "shapeSize/const" $ yes (Const scalarTypeInt (product (shapeToList shr c)))+    shapeSize shr sh+      = ShapeSize shr <$> 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+    toIndex :: ShapeR sh+            -> (Any, OpenExp env aenv sh)+            -> (Any, OpenExp env aenv sh)+            -> (Any, OpenExp env aenv Int)+    toIndex _ (_,sh) (_,FromIndex _ sh' ix)+      | Just Refl <- matchOpenExp sh sh' = Stats.ruleFired "toIndex/fromIndex" $ yes ix+    toIndex shr sh ix                    = ToIndex shr <$> 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+    fromIndex :: ShapeR sh+              -> (Any, OpenExp env aenv sh)+              -> (Any, OpenExp env aenv Int)+              -> (Any, OpenExp env aenv sh)+    fromIndex _ (_,sh) (_,ToIndex _ sh' ix)+      | Just Refl <- matchOpenExp sh sh' = Stats.ruleFired "fromIndex/toIndex" $ yes ix+    fromIndex shr sh ix                  = FromIndex shr <$> sh <*> ix      first :: (a -> a') -> (a,b) -> (a',b)     first f (x,y) = (f x, y)@@ -422,28 +350,36 @@     yes :: x -> (Any, x)     yes x = (Any True, x) +extractConstTuple :: OpenExp env aenv t -> Maybe t+extractConstTuple Nil          = Just ()+extractConstTuple (Pair e1 e2) = (,) <$> extractConstTuple e1 <*> extractConstTuple e2+extractConstTuple (Const _ c)  = Just c+extractConstTuple _            = Nothing  -- Simplification for open functions -- simplifyOpenFun-    :: Kit acc-    => Gamma acc env env aenv-    -> PreOpenFun acc env aenv f-    -> (Bool, PreOpenFun acc env aenv f)-simplifyOpenFun env (Body e) = Body <$> simplifyOpenExp env  e-simplifyOpenFun env (Lam f)  = Lam  <$> simplifyOpenFun env' f+    :: Gamma env env aenv+    -> OpenFun env aenv f+    -> (Bool, OpenFun env aenv f)+simplifyOpenFun env (Body e)    = Body    <$> simplifyOpenExp env  e+simplifyOpenFun env (Lam lhs f) = Lam lhs <$> simplifyOpenFun env' f   where-    env' = incExp env `pushExp` Var ZeroIdx+    env' = lhsExpr lhs env +lhsExpr :: ELeftHandSide t env env' -> Gamma env env aenv -> Gamma env' env' aenv+lhsExpr (LeftHandSideWildcard _) env = env+lhsExpr (LeftHandSideSingle  tp) env = incExp env `pushExp` Evar (Var tp ZeroIdx)+lhsExpr (LeftHandSidePair l1 l2) env = lhsExpr l2 $ lhsExpr l1 env  -- Simplify closed expressions and functions. The process is applied -- repeatedly until no more changes are made. ---simplifyExp :: (Elt t, Kit acc) => PreExp acc aenv t -> PreExp acc aenv t-simplifyExp = iterate summariseOpenExp (simplifyOpenExp EmptyExp)+simplifyExp :: HasCallStack => Exp aenv t -> Exp aenv t+simplifyExp = iterate summariseOpenExp matchOpenExp shrinkExp (simplifyOpenExp EmptyExp) -simplifyFun :: Kit acc => PreFun acc aenv f -> PreFun acc aenv f-simplifyFun = iterate summariseOpenFun (simplifyOpenFun EmptyExp)+simplifyFun :: HasCallStack => Fun aenv f -> Fun aenv f+simplifyFun = iterate summariseOpenFun matchOpenFun shrinkFun (simplifyOpenFun EmptyExp)   -- NOTE: [Simplifier iterations]@@ -463,16 +399,16 @@ -- 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 -> 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))+    :: forall f a. HasCallStack     => (f a -> Stats)-    -> (f a -> (Bool, f a))+    -> (forall s t. f s -> f t -> Maybe (s :~: t))  -- match+    -> (f a -> (Bool, f a))                         -- shrink+    -> (f a -> (Bool, f a))                         -- simplify     -> f a     -> f a-iterate summarise f = fix 1 . setup+iterate summarise match shrink simplify = fix 1 . setup   where     -- The maximum number of simplifier iterations. To be conservative and avoid     -- excessive run times, we (should) set this value very low.@@ -481,18 +417,18 @@     --     lIMIT       = 25 -    simplify'   = Stats.simplifierDone . f-    setup x     = Stats.trace Stats.dump_simpl_iterations (msg 0 "init" x)+    simplify'   = Stats.simplifierDone . simplify+    setup x     = Debug.trace Debug.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 "simplify" "iteration limit reached" (not (x0 ==^ f x0)) x0+      | i > lIMIT       = internalWarning "iteration limit reached" (not (x0 ==^ simplify x0)) x0       | not shrunk      = x1       | not simplified  = x2       | otherwise       = fix (i+1) x2       where-        (shrunk,     x1) = trace i "shrink"   $ shrink' x0+        (shrunk,     x1) = trace i "shrink"   $ shrink x0         (simplified, x2) = trace i "simplify" $ simplify' x1      -- debugging support@@ -500,7 +436,7 @@     u ==^ (_,v)         = isJust (match u v)      trace i s v@(changed,x)-      | changed         = Stats.trace Stats.dump_simpl_iterations (msg i s x) v+      | changed         = Debug.trace Debug.dump_simpl_iterations (msg i s x) v       | otherwise       = v      msg :: Int -> String -> f a -> String@@ -525,6 +461,12 @@   show (Stats a b c d e) =     printf "terms = %d, types = %d, lets = %d, vars = %d, primops = %d" a b c d e +instance Semigroup Stats where+  (<>) = (+++)++instance Monoid Stats where+  mempty = Stats 0 0 0 0 0+ 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)@@ -542,40 +484,29 @@ {-# INLINE vars    #-} {-# INLINE ops     #-} -summariseOpenFun :: PreOpenFun acc env aenv f -> Stats-summariseOpenFun (Body e) = summariseOpenExp e & terms +~ 1-summariseOpenFun (Lam f)  = summariseOpenFun f & terms +~ 1 & binders +~ 1+summariseOpenFun :: OpenFun 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 :: OpenExp env aenv t -> Stats summariseOpenExp = (terms +~ 1) . goE   where     zero = Stats 0 0 0 0 0 -    travE :: PreOpenExp acc env aenv t -> Stats+    travE :: OpenExp env aenv t -> Stats     travE = summariseOpenExp -    travF :: PreOpenFun acc env aenv t -> Stats+    travF :: OpenFun 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 @@ -588,15 +519,13 @@      travBoundedType :: BoundedType t -> Stats     travBoundedType (IntegralBoundedType t) = travIntegralType t & types +~ 1-    travBoundedType (NonNumBoundedType t)   = travNonNumType t & types +~ 1      -- travScalarType :: ScalarType t -> Stats     -- travScalarType (SingleScalarType t) = travSingleType t & types +~ 1     -- travScalarType (VectorScalarType t) = travVectorType t & types +~ 1      travSingleType :: SingleType t -> Stats-    travSingleType (NumSingleType t)    = travNumType t & types +~ 1-    travSingleType (NonNumSingleType t) = travNonNumType t & types +~ 1+    travSingleType (NumSingleType t) = travNumType t & types +~ 1      -- travVectorType :: VectorType t -> Stats     -- travVectorType (Vector2Type t)  = travSingleType t & types +~ 1@@ -606,36 +535,32 @@     -- travVectorType (Vector16Type t) = travSingleType t & types +~ 1      -- The scrutinee has already been counted-    goE :: PreOpenExp acc env aenv t -> Stats+    goE :: OpenExp 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.+        Let _ bnd body        -> travE bnd +++ travE body & binders +~ 1+        Evar{}                -> zero & vars +~ 1+        Foreign _ _ _ x       -> travE x & terms +~ 1   -- +1 for asm, ignore fallback impls.         Const{}               -> zero-        Undef                 -> 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+        Undef _               -> zero+        Nil                   -> zero & terms +~ 1+        Pair e1 e2            -> travE e1 +++ travE e2 & terms +~ 1+        VecPack   _ e         -> travE e+        VecUnpack _ e         -> travE e         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+        ToIndex _ sh ix       -> travE sh +++ travE ix+        FromIndex _ sh ix     -> travE sh +++ travE ix+        Case e rhs def        -> travE e +++ mconcat [ travE c | (_,c) <- rhs ] +++ maybe zero travE def         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+        ShapeSize _ sh        -> travE sh         PrimApp f x           -> travPrimFun f +++ travE x-        Coerce e              -> travE e+        Coerce _ _ e          -> travE e      travPrimFun :: PrimFun f -> Stats     travPrimFun = (ops +~ 1) . goF@@ -703,9 +628,6 @@             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 
src/Data/Array/Accelerate/Trafo/Substitution.hs view
@@ -2,18 +2,23 @@ {-# LANGUAGE FlexibleInstances   #-} {-# LANGUAGE GADTs               #-} {-# LANGUAGE KindSignatures      #-}+{-# LANGUAGE OverloadedStrings   #-} {-# LANGUAGE PatternGuards       #-} {-# LANGUAGE RankNTypes          #-} {-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TemplateHaskell     #-}+{-# LANGUAGE TupleSections       #-}+{-# LANGUAGE TypeApplications    #-} {-# LANGUAGE TypeFamilies        #-} {-# LANGUAGE TypeOperators       #-}+{-# LANGUAGE ViewPatterns        #-} {-# OPTIONS_HADDOCK hide #-} -- | -- Module      : Data.Array.Accelerate.Trafo.Substitution--- Copyright   : [2012..2017] Manuel M T Chakravarty, Gabriele Keller, Trevor L. McDonell+-- Copyright   : [2012..2020] The Accelerate Team -- License     : BSD3 ----- Maintainer  : Trevor L. McDonell <tmcdonell@cse.unsw.edu.au>+-- Maintainer  : Trevor L. McDonell <trevor.mcdonell@gmail.com> -- Stability   : experimental -- Portability : non-portable (GHC extensions) --@@ -21,29 +26,43 @@ module Data.Array.Accelerate.Trafo.Substitution (    -- ** Renaming & Substitution-  inline, substitute, compose,+  inline, inlineVars, compose,   subTop, subAtop,    -- ** Weakening-  (:>), Sink(..), SinkExp(..),+  (:>), Sink(..), SinkExp(..), weakenVars,    -- ** Strengthening   (:?>), strengthen, strengthenE,    -- ** Rebuilding terms   RebuildAcc, Rebuildable(..), RebuildableAcc,-  RebuildableExp(..), RebuildTup(..)+  RebuildableExp(..), rebuildWeakenVar, rebuildLHS,+  OpenAccFun(..), OpenAccExp(..), -) where+  -- ** Checks+  isIdentity, isIdentityIndexing, extractExpVars,+  bindingIsTrivial, -import Control.Applicative                              hiding ( Const )-import Prelude                                          hiding ( exp, seq )+) where  import Data.Array.Accelerate.AST-import Data.Array.Accelerate.Array.Sugar                ( Elt, Arrays, Tuple(..), Atuple(..) )+import Data.Array.Accelerate.AST.LeftHandSide+import Data.Array.Accelerate.AST.Var+import Data.Array.Accelerate.AST.Idx+import Data.Array.Accelerate.AST.Environment+import Data.Array.Accelerate.Analysis.Match+import Data.Array.Accelerate.Error+import Data.Array.Accelerate.Representation.Type+import Data.Array.Accelerate.Representation.Array import qualified Data.Array.Accelerate.Debug.Stats      as Stats +import Data.Kind+import Control.Applicative                              hiding ( Const )+import Control.Monad+import Prelude                                          hiding ( exp, seq ) + -- NOTE: [Renaming and Substitution] -- -- To do things like renaming and substitution, we need some operation on@@ -69,52 +88,165 @@ -- a class of operations on variables that is closed under shifting. -- infixr `compose`-infixr `substitute`+-- infixr `substitute` +lhsFullVars :: forall s a env1 env2. LeftHandSide s a env1 env2 -> Maybe (Vars s env2 a)+lhsFullVars = fmap snd . go weakenId+  where+    go :: forall env env' b. (env' :> env2) -> LeftHandSide s b env env' -> Maybe (env :> env2, Vars s env2 b)+    go k (LeftHandSideWildcard TupRunit) = Just (k, TupRunit)+    go k (LeftHandSideSingle s) = Just $ (weakenSucc $ k, TupRsingle $ Var s $ k >:> ZeroIdx)+    go k (LeftHandSidePair l1 l2)+      | Just (k',  v2) <- go k  l2+      , Just (k'', v1) <- go k' l1 = Just (k'', TupRpair v1 v2)+    go _ _ = Nothing++bindingIsTrivial :: LeftHandSide s a env1 env2 -> Vars s env2 b -> Maybe (a :~: b)+bindingIsTrivial lhs vars+  | Just lhsVars <- lhsFullVars lhs+  , Just Refl    <- matchVars vars lhsVars+  = Just Refl+bindingIsTrivial _ _ = Nothing++isIdentity :: OpenFun env aenv (a -> b) -> Maybe (a :~: b)+isIdentity (Lam lhs (Body (extractExpVars -> Just vars))) = bindingIsTrivial lhs vars+isIdentity _ = Nothing++-- Detects whether the function is of the form \ix -> a ! ix+isIdentityIndexing :: OpenFun env aenv (a -> b) -> Maybe (ArrayVar aenv (Array a b))+isIdentityIndexing (Lam lhs (Body body))+  | Index avar ix <- body+  , Just vars     <- extractExpVars ix+  , Just Refl     <- bindingIsTrivial lhs vars+  = Just avar+isIdentityIndexing _ = Nothing+ -- | Replace the first variable with the given expression. The environment -- shrinks. ---inline :: RebuildableAcc acc-       => PreOpenExp acc (env, s) aenv t-       -> PreOpenExp acc env      aenv s-       -> PreOpenExp acc env      aenv t+inline :: OpenExp (env, s) aenv t+       -> OpenExp env      aenv s+       -> OpenExp env      aenv t inline f g = Stats.substitution "inline" $ rebuildE (subTop g) f +inlineVars :: forall env env' aenv t1 t2.+              ELeftHandSide t1 env env'+           ->        OpenExp env' aenv t2+           ->        OpenExp env  aenv t1+           -> Maybe (OpenExp env  aenv t2)+inlineVars lhsBound expr bound+  | Just vars <- lhsFullVars lhsBound = substitute (strengthenWithLHS lhsBound) weakenId vars expr+  where+    substitute+        :: forall env1 env2 t.+           env1 :?> env2+        -> env :> env2+        -> ExpVars env1 t1+        -> OpenExp env1 aenv t+        -> Maybe (OpenExp env2 aenv t)+    substitute _ k2 vars (extractExpVars -> Just vars')+      | Just Refl <- matchVars vars vars' = Just $ weakenE k2 bound+    substitute k1 k2 vars topExp = case topExp of+      Let lhs e1 e2+        | Exists lhs' <- rebuildLHS lhs+                          -> Let lhs' <$> travE e1 <*> substitute (strengthenAfter lhs lhs' k1) (weakenWithLHS lhs' .> k2) (weakenWithLHS lhs `weakenVars` vars) e2+      Evar (Var t ix)     -> Evar . Var t <$> k1 ix+      Foreign tp asm f e1 -> Foreign tp asm f <$> travE e1+      Pair e1 e2          -> Pair <$> travE e1 <*> travE e2+      Nil                 -> Just Nil+      VecPack   vec e1    -> VecPack   vec <$> travE e1+      VecUnpack vec e1    -> VecUnpack vec <$> travE e1+      IndexSlice si e1 e2 -> IndexSlice si <$> travE e1 <*> travE e2+      IndexFull  si e1 e2 -> IndexFull  si <$> travE e1 <*> travE e2+      ToIndex   shr e1 e2 -> ToIndex   shr <$> travE e1 <*> travE e2+      FromIndex shr e1 e2 -> FromIndex shr <$> travE e1 <*> travE e2+      Case e1 rhs def     -> Case <$> travE e1 <*> mapM (\(t,c) -> (t,) <$> travE c) rhs <*> travMaybeE def+      Cond e1 e2 e3       -> Cond <$> travE e1 <*> travE e2 <*> travE e3+      While f1 f2 e1      -> While <$> travF f1 <*> travF f2 <*> travE e1+      Const t c           -> Just $ Const t c+      PrimConst c         -> Just $ PrimConst c+      PrimApp p e1        -> PrimApp p <$> travE e1+      Index a e1          -> Index a <$> travE e1+      LinearIndex a e1    -> LinearIndex a <$> travE e1+      Shape a             -> Just $ Shape a+      ShapeSize shr e1    -> ShapeSize shr <$> travE e1+      Undef t             -> Just $ Undef t+      Coerce t1 t2 e1     -> Coerce t1 t2 <$> travE e1++      where+        travE :: OpenExp env1 aenv s -> Maybe (OpenExp env2 aenv s)+        travE = substitute k1 k2 vars++        travF :: OpenFun env1 aenv s -> Maybe (OpenFun env2 aenv s)+        travF = substituteF k1 k2 vars++        travMaybeE :: Maybe (OpenExp env1 aenv s) -> Maybe (Maybe (OpenExp env2 aenv s))+        travMaybeE Nothing  = pure Nothing+        travMaybeE (Just x) = Just <$> travE x++    substituteF :: forall env1 env2 t.+               env1 :?> env2+            -> env :> env2+            -> ExpVars env1 t1+            -> OpenFun env1 aenv t+            -> Maybe (OpenFun env2 aenv t)+    substituteF k1 k2 vars (Body e) = Body <$> substitute k1 k2 vars e+    substituteF k1 k2 vars (Lam lhs f)+      | Exists lhs' <- rebuildLHS lhs = Lam lhs' <$> substituteF (strengthenAfter lhs lhs' k1) (weakenWithLHS lhs' .> k2) (weakenWithLHS lhs `weakenVars` vars) f++inlineVars _ _ _ = Nothing++ -- | Replace an expression that uses the top environment variable with another. -- The result of the first is let bound into the second. ---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-substitute f g+{- substitute' :: OpenExp (env, b) aenv c+            -> OpenExp (env, a) aenv b+            -> OpenExp (env, a) aenv c+substitute' f g   | Stats.substitution "substitute" False = undefined--  | Var ZeroIdx <- g    = f     -- don't rebind an identity function-  | otherwise           = Let g $ rebuildE split f+  | isIdentity f = g -- don't rebind an identity function+  | isIdentity g = f+  | otherwise = Let g $ rebuildE split f   where-    split :: Elt c => Idx (env,b) c -> PreOpenExp acc ((env,a),b) aenv c+    split :: Idx (env,b) c -> OpenExp ((env,a),b) aenv c     split ZeroIdx       = Var ZeroIdx     split (SuccIdx ix)  = Var (SuccIdx (SuccIdx ix)) +substitute :: LeftHandSide b env envb+           -> OpenExp envb c+           -> LeftHandSide a env enva+           -> OpenExp enva b+-}  -- | Composition of unary functions. ---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"+compose :: HasCallStack+        => OpenFun env aenv (b -> c)+        -> OpenFun env aenv (a -> b)+        -> OpenFun env aenv (a -> c)+compose f@(Lam lhsB (Body c)) g@(Lam lhsA (Body b))+  | Stats.substitution "compose" False = undefined+  | Just Refl <- isIdentity f = g -- don't rebind an identity function+  | Just Refl <- isIdentity g = f -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+  | Exists lhsB' <- rebuildLHS lhsB+  = Lam lhsA+  $ Body+  $ Let lhsB' b+  $ weakenE (sinkWithLHS lhsB lhsB' $ weakenWithLHS lhsA) c+  -- = Stats.substitution "compose" . Lam lhs2 . Body $ substitute' f g+compose _+  _ = error "compose: impossible evaluation" -subAtop :: Arrays t => PreOpenAcc acc aenv s -> Idx (aenv, s) t -> PreOpenAcc acc aenv t-subAtop t ZeroIdx       = t-subAtop _ (SuccIdx idx) = Avar idx+subTop :: OpenExp env aenv s -> ExpVar (env, s) t -> OpenExp env aenv t+subTop s (Var _  ZeroIdx     ) = s+subTop _ (Var tp (SuccIdx ix)) = Evar $ Var tp ix +subAtop :: PreOpenAcc acc aenv t -> ArrayVar (aenv, t) (Array sh2 e2) -> PreOpenAcc acc aenv (Array sh2 e2)+subAtop t (Var _    ZeroIdx      ) = t+subAtop _ (Var repr (SuccIdx idx)) = Avar $ Var repr idx+ data Identity a = Identity { runIdentity :: a }  instance Functor Identity where@@ -131,16 +263,16 @@ -- class Rebuildable f where   {-# MINIMAL rebuildPartial #-}-  type AccClo f :: (* -> * -> *)+  type AccClo f :: Type -> Type -> Type    rebuildPartial :: (Applicative f', SyntacticAcc fa)-                 => (forall a'. Arrays a' => Idx aenv a' -> f' (fa (AccClo f) aenv' a'))+                 => (forall sh e. ArrayVar aenv (Array sh e) -> f' (fa (AccClo f) aenv' (Array sh e)))                  -> f aenv  a                  -> f' (f aenv' a)    {-# INLINEABLE rebuildA #-}   rebuildA :: (SyntacticAcc fa)-           => (forall a'. Arrays a' => Idx aenv a' -> fa (AccClo f) aenv' a')+           => (forall sh e. ArrayVar aenv (Array sh e) -> fa (AccClo f) aenv' (Array sh e))            -> f aenv  a            -> f aenv' a   rebuildA av = runIdentity . rebuildPartial (Identity . av)@@ -150,13 +282,13 @@ 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+                  => (forall e'. ExpVar env e' -> f' (fe env' aenv e'))+                  -> f env aenv e                   -> f' (f env' aenv e) -  {-# INLINABLE rebuildE #-}+  {-# INLINEABLE rebuildE #-}   rebuildE :: SyntacticExp fe-           => (forall e'. Elt e' => Idx env e' -> fe (AccClo (f env)) env' aenv e')+           => (forall e'. ExpVar env e' -> fe env' aenv e')            -> f env  aenv e            -> f env' aenv e   rebuildE v = runIdentity . rebuildPartialE (Identity . v)@@ -165,48 +297,48 @@ -- type RebuildableAcc acc = (Rebuildable acc, AccClo acc ~ acc) +-- Wrappers which add the 'acc' type argument+--+data OpenAccExp (acc :: Type -> Type -> Type) env aenv a where+  OpenAccExp :: { unOpenAccExp :: OpenExp env aenv a } -> OpenAccExp acc env aenv a++data OpenAccFun (acc :: Type -> Type -> Type) env aenv a where+  OpenAccFun :: { unOpenAccFun :: OpenFun env aenv a } -> OpenAccFun acc env aenv a+ -- 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+instance Rebuildable (OpenAccExp acc env) where+  type AccClo (OpenAccExp acc env) = acc   {-# INLINEABLE rebuildPartial #-}-  rebuildPartial = rebuildPreOpenExp rebuildPartial (pure . IE)+  rebuildPartial v (OpenAccExp e) = OpenAccExp <$> Stats.substitution "rebuild" (rebuildOpenExp (pure . IE) (reindexAvar v) e) -instance RebuildableAcc acc => Rebuildable (PreOpenFun acc env) where-  type AccClo (PreOpenFun acc env) = acc+instance Rebuildable (OpenAccFun acc env) where+  type AccClo (OpenAccFun acc env) = acc   {-# INLINEABLE rebuildPartial #-}-  rebuildPartial = rebuildFun rebuildPartial (pure . IE)+  rebuildPartial v (OpenAccFun f) = OpenAccFun <$> Stats.substitution "rebuild" (rebuildFun (pure . IE) (reindexAvar v) f)  instance RebuildableAcc acc => Rebuildable (PreOpenAcc acc) where   type AccClo (PreOpenAcc acc) = acc   {-# INLINEABLE rebuildPartial #-}-  rebuildPartial = rebuildPreOpenAcc rebuildPartial+  rebuildPartial x = Stats.substitution "rebuild" $ rebuildPreOpenAcc rebuildPartial x  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)+  rebuildPartial x = Stats.substitution "rebuild" $ rebuildAfun rebuildPartial x  instance Rebuildable OpenAcc where   type AccClo OpenAcc = OpenAcc   {-# INLINEABLE rebuildPartial #-}-  rebuildPartial = rebuildOpenAcc+  rebuildPartial x = Stats.substitution "rebuild" $ rebuildOpenAcc x -instance RebuildableAcc acc => RebuildableExp (PreOpenExp acc) where+instance RebuildableExp OpenExp where   {-# INLINEABLE rebuildPartialE #-}-  rebuildPartialE v = rebuildPreOpenExp rebuildPartial v (pure . IA)+  rebuildPartialE v x = Stats.substitution "rebuild" $ rebuildOpenExp v (ReindexAvar pure) x -instance RebuildableAcc acc => RebuildableExp (PreOpenFun acc) where+instance RebuildableExp OpenFun where   {-# INLINEABLE rebuildPartialE #-}-  rebuildPartialE v = rebuildFun rebuildPartial v (pure . IA)+  rebuildPartialE v x = Stats.substitution "rebuild" $ rebuildFun v (ReindexAvar pure) x  -- NOTE: [Weakening] --@@ -222,10 +354,6 @@ -- variable references to make room for the new bindings. -- --- The type of shifting terms from one context into another----type env :> env' = forall t'. Idx env t' -> Idx env' t'- class Sink f where   weaken :: env :> env' -> f env t -> f env' t @@ -234,36 +362,47 @@   --   -- {-# INLINEABLE weaken #-}   -- default weaken :: Rebuildable f => env :> env' -> f env t -> f env' t-  -- weaken k = Stats.substitution "weaken" . rebuildA (Avar . k)+  -- weaken k = Stats.substitution "weaken" . rebuildA rebuildWeakenVar  --instance Rebuildable f => Sink f where -- undecidable, incoherent---  weaken k = Stats.substitution "weaken" . rebuildA (Avar . k)+--  weaken k = Stats.substitution "weaken" . rebuildA rebuildWeakenVar  instance Sink Idx where   {-# INLINEABLE weaken #-}-  weaken k = k+  weaken = (>:>) -instance RebuildableAcc acc => Sink (PreOpenAcc acc) where+instance Sink (Var s) where   {-# INLINEABLE weaken #-}-  weaken k = Stats.substitution "weaken" . rebuildA (Avar . k)+  weaken k (Var s ix) = Var s (k >:> ix) -instance RebuildableAcc acc => Sink (PreOpenAfun acc) where+weakenVars :: env :> env' -> Vars s env t -> Vars s env' t+weakenVars _  TupRunit      = TupRunit+weakenVars k (TupRsingle v) = TupRsingle $ weaken k v+weakenVars k (TupRpair v w) = TupRpair (weakenVars k v) (weakenVars k w)++rebuildWeakenVar :: env :> env' -> ArrayVar env (Array sh e) -> PreOpenAcc acc env' (Array sh e)+rebuildWeakenVar k (Var s idx) = Avar $ Var s $ k >:> idx++rebuildWeakenEvar :: env :> env' -> ExpVar env t -> OpenExp env' aenv t+rebuildWeakenEvar k (Var s idx) = Evar $ Var s $ k >:> idx++instance RebuildableAcc acc => Sink (PreOpenAcc acc) where   {-# INLINEABLE weaken #-}-  weaken k = Stats.substitution "weaken" . rebuildA (Avar . k)+  weaken k = Stats.substitution "weaken" . rebuildA (rebuildWeakenVar k) -instance RebuildableAcc acc => Sink (PreOpenExp acc env) where+instance RebuildableAcc acc => Sink (PreOpenAfun acc) where   {-# INLINEABLE weaken #-}-  weaken k = Stats.substitution "weaken" . rebuildA (Avar . k)+  weaken k = Stats.substitution "weaken" . rebuildA (rebuildWeakenVar k) -instance RebuildableAcc acc => Sink (PreOpenFun acc env) where+instance Sink (OpenExp env) where   {-# INLINEABLE weaken #-}-  weaken k = Stats.substitution "weaken" . rebuildA (Avar . k)+  weaken k = Stats.substitution "weaken" . runIdentity . rebuildOpenExp (Identity . Evar) (ReindexAvar (Identity . weaken k)) -instance RebuildableAcc acc => Sink (RebuildTup acc env) where+instance Sink (OpenFun env) where   {-# INLINEABLE weaken #-}-  weaken k = Stats.substitution "weaken" . rebuildA (Avar . k)+  weaken k = Stats.substitution "weaken" . runIdentity . rebuildFun (Identity . Evar) (ReindexAvar (Identity . weaken k)) -instance RebuildableAcc acc => Sink (PreBoundary acc) where+instance Sink Boundary where   {-# INLINEABLE weaken #-}   weaken k bndy =     case bndy of@@ -275,7 +414,7 @@  instance Sink OpenAcc where   {-# INLINEABLE weaken #-}-  weaken k = Stats.substitution "weaken" . rebuildA (Avar . k)+  weaken k = Stats.substitution "weaken" . rebuildA (rebuildWeakenVar 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.@@ -293,13 +432,13 @@   -- 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+instance SinkExp OpenExp where   {-# INLINEABLE weakenE #-}-  weakenE v = Stats.substitution "weakenE" . rebuildE (IE . v)+  weakenE v = Stats.substitution "weakenE" . rebuildE (rebuildWeakenEvar v) -instance RebuildableAcc acc => SinkExp (PreOpenFun acc) where+instance SinkExp OpenFun where   {-# INLINEABLE weakenE #-}-  weakenE v = Stats.substitution "weakenE" . rebuildE (IE . v)+  weakenE v = Stats.substitution "weakenE" . rebuildE (rebuildWeakenEvar v)  -- See above for why this is disabled. -- {-# RULES@@ -319,13 +458,29 @@ 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)+strengthen :: forall f env env' t. Rebuildable f => env :?> env' -> f env t -> Maybe (f env' t)+strengthen k x = Stats.substitution "strengthen" $ rebuildPartial @f @Maybe @IdxA (\(Var s ix) -> fmap (IA . Var s) $ k ix) x  {-# INLINEABLE strengthenE #-}-strengthenE :: RebuildableExp f => env :?> env' -> f env aenv t -> Maybe (f env' aenv t)-strengthenE k = rebuildPartialE (fmap IE . k)+strengthenE :: forall f env env' aenv t. RebuildableExp f => env :?> env' -> f env aenv t -> Maybe (f env' aenv t)+strengthenE k x = Stats.substitution "strengthenE" $ rebuildPartialE @f @Maybe @IdxE (\(Var tp ix) -> fmap (IE . Var tp) $ k ix) x +strengthenWithLHS :: LeftHandSide s t env1 env2 -> env2 :?> env1+strengthenWithLHS (LeftHandSideWildcard _) = Just+strengthenWithLHS (LeftHandSideSingle _)   = \ix -> case ix of+  ZeroIdx   -> Nothing+  SuccIdx i -> Just i+strengthenWithLHS (LeftHandSidePair l1 l2) = strengthenWithLHS l2 >=> strengthenWithLHS l1++strengthenAfter :: LeftHandSide s t env1 env2 -> LeftHandSide s t env1' env2' -> env1 :?> env1' -> env2 :?> env2'+strengthenAfter (LeftHandSideWildcard _) (LeftHandSideWildcard _) k = k+strengthenAfter (LeftHandSideSingle _)   (LeftHandSideSingle _)   k = \ix -> case ix of+  ZeroIdx   -> Just ZeroIdx+  SuccIdx i -> SuccIdx <$> k i+strengthenAfter (LeftHandSidePair l1 l2) (LeftHandSidePair l1' l2') k =+  strengthenAfter l2 l2' $ strengthenAfter l1 l1' k+strengthenAfter _ _ _ = error "Substitution.strengthenAfter: left hand sides do not match"+ -- Simultaneous Substitution =================================================== -- @@ -336,230 +491,273 @@ -- SEE: [Weakening] -- 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 => 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+  varIn         :: ExpVar env t -> f env aenv t+  expOut        :: f env aenv t -> OpenExp env aenv t+  weakenExp     :: f env aenv t -> f (env, s) aenv t -newtype IdxE (acc :: * -> * -> *) env aenv t = IE { unIE :: Idx env t }+newtype IdxE env aenv t = IE { unIE :: ExpVar env t }  instance SyntacticExp IdxE where   varIn          = IE-  expOut         = Var . unIE-  weakenExp _    = IE . SuccIdx . unIE-  -- weakenExpAcc _ = IE . unIE+  expOut         = Evar . unIE+  weakenExp (IE (Var tp ix)) = IE $ Var tp $ SuccIdx ix -instance SyntacticExp PreOpenExp where-  varIn          = Var+instance SyntacticExp OpenExp where+  varIn          = Evar   expOut         = id-  weakenExp k    = runIdentity . rebuildPreOpenExp k (Identity . weakenExp k . IE) (Identity . IA)-  -- weakenExpAcc k = runIdentity . rebuildPreOpenExp k (Identity . IE) (Identity . weakenAcc k . IA)+  weakenExp      = runIdentity . rebuildOpenExp (Identity . weakenExp . IE) (ReindexAvar Identity)  {-# INLINEABLE shiftE #-} shiftE-    :: (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)+    :: (Applicative f, SyntacticExp fe)+    => RebuildEvar f fe env      env'      aenv+    -> RebuildEvar f fe (env, s) (env', s) aenv+shiftE _ (Var tp ZeroIdx)      = pure $ varIn (Var tp ZeroIdx)+shiftE v (Var tp (SuccIdx ix)) = weakenExp <$> v (Var tp ix) -{-# 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-    -> f (PreOpenExp acc env' aenv' t)-rebuildPreOpenExp k v av exp =-  case exp of-    Const c             -> pure (Const c)-    PrimConst c         -> pure (PrimConst c)-    Undef               -> pure Undef-    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-    Coerce e            -> Coerce       <$> rebuildPreOpenExp k v av e+{-# INLINEABLE shiftE' #-}+shiftE'+    :: (Applicative f, SyntacticExp fa)+    => ELeftHandSide t env1 env1'+    -> ELeftHandSide t env2 env2'+    -> RebuildEvar f fa env1  env2  aenv+    -> RebuildEvar f fa env1' env2' aenv+shiftE' (LeftHandSideWildcard _) (LeftHandSideWildcard _) v = v+shiftE' (LeftHandSideSingle _)   (LeftHandSideSingle _)   v = shiftE v+shiftE' (LeftHandSidePair a1 b1) (LeftHandSidePair a2 b2) v = shiftE' b1 b2 $ shiftE' a1 a2 v+shiftE' _ _ _ = error "Substitution: left hand sides do not match" -{-# 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      -> pure NilTup-    SnocTup t e -> SnocTup <$> rebuildTup k v av t <*> rebuildPreOpenExp k v av e+{-# INLINEABLE rebuildMaybeExp #-}+rebuildMaybeExp+    :: (HasCallStack, Applicative f, SyntacticExp fe)+    => RebuildEvar f fe env env' aenv'+    -> ReindexAvar f aenv aenv'+    -> Maybe (OpenExp env  aenv t)+    -> f (Maybe (OpenExp env' aenv' t))+rebuildMaybeExp _ _  Nothing  = pure Nothing+rebuildMaybeExp v av (Just x) = Just <$> rebuildOpenExp v av x +{-# INLINEABLE rebuildOpenExp #-}+rebuildOpenExp+    :: (HasCallStack, Applicative f, SyntacticExp fe)+    => RebuildEvar f fe env env' aenv'+    -> ReindexAvar f aenv aenv'+    -> OpenExp env  aenv t+    -> f (OpenExp env' aenv' t)+rebuildOpenExp v av@(ReindexAvar reindex) exp =+  case exp of+    Const t c           -> pure $ Const t c+    PrimConst c         -> pure $ PrimConst c+    Undef t             -> pure $ Undef t+    Evar var            -> expOut          <$> v var+    Let lhs a b+      | Exists lhs' <- rebuildLHS lhs+                        -> Let lhs'        <$> rebuildOpenExp v av a  <*> rebuildOpenExp (shiftE' lhs lhs' v) av b+    Pair e1 e2          -> Pair            <$> rebuildOpenExp v av e1 <*> rebuildOpenExp v av e2+    Nil                 -> pure Nil+    VecPack   vec e     -> VecPack   vec   <$> rebuildOpenExp v av e+    VecUnpack vec e     -> VecUnpack vec   <$> rebuildOpenExp v av e+    IndexSlice x ix sh  -> IndexSlice x    <$> rebuildOpenExp v av ix <*> rebuildOpenExp v av sh+    IndexFull x ix sl   -> IndexFull x     <$> rebuildOpenExp v av ix <*> rebuildOpenExp v av sl+    ToIndex shr sh ix   -> ToIndex shr     <$> rebuildOpenExp v av sh <*> rebuildOpenExp v av ix+    FromIndex shr sh ix -> FromIndex shr   <$> rebuildOpenExp v av sh <*> rebuildOpenExp v av ix+    Case e rhs def      -> Case            <$> rebuildOpenExp v av e  <*> sequenceA [ (t,) <$> rebuildOpenExp v av c | (t,c) <- rhs ] <*> rebuildMaybeExp v av def+    Cond p t e          -> Cond            <$> rebuildOpenExp v av p  <*> rebuildOpenExp v av t  <*> rebuildOpenExp v av e+    While p f x         -> While           <$> rebuildFun v av p      <*> rebuildFun v av f      <*> rebuildOpenExp v av x+    PrimApp f x         -> PrimApp f       <$> rebuildOpenExp v av x+    Index a sh          -> Index           <$> reindex a              <*> rebuildOpenExp v av sh+    LinearIndex a i     -> LinearIndex     <$> reindex a              <*> rebuildOpenExp v av i+    Shape a             -> Shape           <$> reindex a+    ShapeSize shr sh    -> ShapeSize shr   <$> rebuildOpenExp v av sh+    Foreign tp ff f e   -> Foreign tp ff f <$> rebuildOpenExp v av e+    Coerce t1 t2 e      -> Coerce t1 t2    <$> rebuildOpenExp v av e+ {-# 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 =+    :: (HasCallStack, Applicative f, SyntacticExp fe)+    => RebuildEvar f fe env env' aenv'+    -> ReindexAvar f aenv aenv'+    -> OpenFun env  aenv  t+    -> f (OpenFun env' aenv' t)+rebuildFun v av fun =   case fun of-    Body e      -> Body <$> rebuildPreOpenExp k v av e-    Lam f       -> Lam  <$> rebuildFun k (shiftE k v) av f+    Body e -> Body <$> rebuildOpenExp v av e+    Lam lhs f+      | Exists lhs' <- rebuildLHS lhs+        -> Lam lhs' <$> rebuildFun (shiftE' lhs lhs' v) av f  -- The array environment -- -----------------  type RebuildAcc acc =-  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+  forall aenv aenv' f fa a. (HasCallStack, Applicative f, SyntacticAcc fa)+    => RebuildAvar f fa acc aenv aenv'+    -> acc aenv a     -> f (acc aenv' a) -class SyntacticAcc f where-  avarIn        :: Arrays t => Idx aenv t     -> f acc aenv t-  accOut        :: Arrays t => f acc aenv t   -> PreOpenAcc acc aenv t-  weakenAcc     :: Arrays t => RebuildAcc acc -> f acc aenv t -> f acc (aenv, s) t+newtype IdxA (acc :: Type -> Type -> Type) aenv t = IA { unIA :: ArrayVar aenv t } -newtype IdxA (acc :: * -> * -> *) aenv t = IA { unIA :: Idx aenv t }+class SyntacticAcc f where+  avarIn        :: ArrayVar aenv (Array sh e) -> f acc aenv (Array sh e)+  accOut        :: f acc aenv (Array sh e) -> PreOpenAcc acc aenv (Array sh e)+  weakenAcc     :: RebuildAcc acc -> f acc aenv (Array sh e) -> f acc (aenv, s) (Array sh e)  instance SyntacticAcc IdxA where-  avarIn         = IA-  accOut         = Avar . unIA-  weakenAcc _    = IA . SuccIdx . unIA+  avarIn                       = IA+  accOut                       = Avar . unIA+  weakenAcc _ (IA (Var s idx)) = IA $ Var s $ SuccIdx idx  instance SyntacticAcc PreOpenAcc where   avarIn        = Avar   accOut        = id   weakenAcc k   = runIdentity . rebuildPreOpenAcc k (Identity . weakenAcc k . IA) +type RebuildAvar f (fa :: (Type -> Type -> Type) -> Type -> Type -> Type) acc aenv aenv'+    = forall sh e. ArrayVar aenv (Array sh e) -> f (fa acc aenv' (Array sh e))++type RebuildEvar f fe env env' aenv' =+  forall t'. ExpVar env t' -> f (fe env' aenv' t')++newtype ReindexAvar f aenv aenv' =+  ReindexAvar (forall sh e. ArrayVar aenv (Array sh e) -> f (ArrayVar aenv' (Array sh e)))++reindexAvar+    :: forall f fa acc aenv aenv'.+       (HasCallStack, Applicative f, SyntacticAcc fa)+    => RebuildAvar f fa acc aenv aenv'+    -> ReindexAvar f        aenv aenv'+reindexAvar v = ReindexAvar f where+  f :: forall sh e. ArrayVar aenv (Array sh e) -> f (ArrayVar aenv' (Array sh e))+  f var = g <$> v var++  g :: fa acc aenv' (Array sh e) -> ArrayVar aenv' (Array sh e)+  g fa = case accOut fa of+    Avar var' -> var'+    _ -> internalError "An Avar which was used in an Exp was mapped to an array term other than Avar. This mapping is invalid as an Exp can only contain array variables."++ {-# INLINEABLE shiftA #-} shiftA-    :: (Applicative f, SyntacticAcc fa, Arrays t)+    :: (HasCallStack, Applicative f, SyntacticAcc fa)     => 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+    -> RebuildAvar f fa acc aenv aenv'+    -> ArrayVar  (aenv,  s) (Array sh e)+    -> f (fa acc (aenv', s) (Array sh e))+shiftA _ _ (Var s ZeroIdx)      = pure $ avarIn $ Var s ZeroIdx+shiftA k v (Var s (SuccIdx ix)) = weakenAcc k <$> v (Var s ix) +shiftA'+    :: (HasCallStack, Applicative f, SyntacticAcc fa)+    => ALeftHandSide t aenv1 aenv1'+    -> ALeftHandSide t aenv2 aenv2'+    -> RebuildAcc acc+    -> RebuildAvar f fa acc aenv1  aenv2+    -> RebuildAvar f fa acc aenv1' aenv2'+shiftA' (LeftHandSideWildcard _) (LeftHandSideWildcard _) _ v = v+shiftA' (LeftHandSideSingle _)   (LeftHandSideSingle _)   k v = shiftA k v+shiftA' (LeftHandSidePair a1 b1) (LeftHandSidePair a2 b2) k v = shiftA' b1 b2 k $ shiftA' a1 a2 k v+shiftA' _ _ _ _ = internalError "left hand sides do not match"+ {-# INLINEABLE rebuildOpenAcc #-} rebuildOpenAcc-    :: (Applicative f, SyntacticAcc fa)-    => (forall t'. Arrays t' => Idx aenv t' -> f (fa OpenAcc aenv' t'))+    :: (HasCallStack, Applicative f, SyntacticAcc fa)+    => (forall sh e. ArrayVar aenv (Array sh e) -> f (fa OpenAcc aenv' (Array sh e)))     -> OpenAcc aenv  t     -> f (OpenAcc aenv' t) rebuildOpenAcc av (OpenAcc acc) = OpenAcc <$> rebuildPreOpenAcc rebuildOpenAcc av acc  {-# INLINEABLE rebuildPreOpenAcc #-} rebuildPreOpenAcc-    :: (Applicative f, SyntacticAcc fa)+    :: (HasCallStack, Applicative f, SyntacticAcc fa)     => RebuildAcc acc-    -> (forall t'. Arrays t' => Idx aenv t' -> f (fa acc aenv' t'))+    -> RebuildAvar f fa acc aenv aenv'     -> PreOpenAcc acc aenv  t     -> f (PreOpenAcc acc aenv' t) rebuildPreOpenAcc k av acc =   case acc of-    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 <*> rebuildBoundary k av b  <*> k av a-    Stencil2 f b1 a1 b2 a2  -> Stencil2     <$> rebuildFun k (pure . IE) av f <*> rebuildBoundary k av b1 <*> k av a1 <*> rebuildBoundary k av b2 <*> k av a2+    Use repr a                -> pure $ Use repr a+    Alet lhs a b              -> rebuildAlet k av lhs a b+    Avar ix                   -> accOut          <$> av ix+    Apair as bs               -> Apair           <$> k av as <*> k av bs+    Anil                      -> pure Anil+    Apply repr f a            -> Apply repr      <$> rebuildAfun k av f <*> k av a+    Acond p t e               -> Acond           <$> rebuildOpenExp (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 tp e                 -> Unit tp         <$> rebuildOpenExp (pure . IE) av' e+    Reshape shr e a           -> Reshape shr     <$> rebuildOpenExp (pure . IE) av' e <*> k av a+    Generate repr e f         -> Generate repr   <$> rebuildOpenExp (pure . IE) av' e <*> rebuildFun (pure . IE) av' f+    Transform repr sh ix f a  -> Transform repr  <$> rebuildOpenExp (pure . IE) av' sh <*> rebuildFun (pure . IE) av' ix <*> rebuildFun (pure . IE) av' f <*> k av a+    Replicate sl slix a       -> Replicate sl    <$> rebuildOpenExp (pure . IE) av' slix <*> k av a+    Slice sl a slix           -> Slice sl        <$> k av a <*> rebuildOpenExp (pure . IE) av' slix+    Map tp f a                -> Map tp          <$> rebuildFun (pure . IE) av' f <*> k av a+    ZipWith tp f a1 a2        -> ZipWith tp      <$> rebuildFun (pure . IE) av' f <*> k av a1 <*> k av a2+    Fold f z a                -> Fold            <$> rebuildFun (pure . IE) av' f <*> rebuildMaybeExp (pure . IE) av' z <*> k av a+    FoldSeg itp f z a s       -> FoldSeg itp     <$> rebuildFun (pure . IE) av' f <*> rebuildMaybeExp (pure . IE) av' z <*> k av a <*> k av s+    Scan  d f z a             -> Scan  d         <$> rebuildFun (pure . IE) av' f <*> rebuildMaybeExp (pure . IE) av' z <*> k av a+    Scan' d f z a             -> Scan' d         <$> rebuildFun (pure . IE) av' f <*> rebuildOpenExp (pure . IE) av' z <*> k av a+    Permute f1 a1 f2 a2       -> Permute         <$> rebuildFun (pure . IE) av' f1 <*> k av a1 <*> rebuildFun (pure . IE) av' f2 <*> k av a2+    Backpermute shr sh f a    -> Backpermute shr <$> rebuildOpenExp (pure . IE) av' sh <*> rebuildFun (pure . IE) av' f <*> k av a+    Stencil sr tp f b a       -> Stencil sr tp   <$> rebuildFun (pure . IE) av' f <*> rebuildBoundary av' b  <*> k av a+    Stencil2 s1 s2 tp f b1 a1 b2 a2+                              -> Stencil2 s1 s2 tp <$> rebuildFun (pure . IE) av' f <*> rebuildBoundary av' b1 <*> k av a1 <*> rebuildBoundary av' b2 <*> k av a2+    Aforeign repr ff afun as  -> Aforeign repr ff afun <$> k av as     -- Collect seq             -> Collect      <$> rebuildSeq k av seq-    Aforeign ff afun as     -> Aforeign ff afun <$> k av as+  where+    av' = reindexAvar av  {-# INLINEABLE rebuildAfun #-} rebuildAfun-    :: (Applicative f, SyntacticAcc fa)+    :: (HasCallStack, Applicative f, SyntacticAcc fa)     => RebuildAcc acc-    -> (forall t'. Arrays t' => Idx aenv t' -> f (fa acc aenv' t'))+    -> RebuildAvar f fa acc aenv aenv'     -> PreOpenAfun acc aenv  t     -> f (PreOpenAfun acc aenv' t)-rebuildAfun k av afun =-  case afun of-    Abody b     -> Abody <$> k av b-    Alam f      -> Alam  <$> rebuildAfun k (shiftA k av) f+rebuildAfun k av (Abody b) = Abody <$> k av b+rebuildAfun k av (Alam lhs1 f)+  | Exists lhs2 <- rebuildLHS lhs1+  = Alam lhs2 <$> rebuildAfun k (shiftA' lhs1 lhs2 k av) f -{-# INLINEABLE rebuildAtup #-}-rebuildAtup-    :: (Applicative f, SyntacticAcc fa)+rebuildAlet+    :: forall f fa acc aenv1 aenv1' aenv2 bndArrs arrs. (HasCallStack, Applicative f, SyntacticAcc fa)     => RebuildAcc acc-    -> (forall t'. Arrays t' => Idx aenv t' -> f (fa acc aenv' t'))-    -> Atuple (acc aenv)  t-    -> f (Atuple (acc aenv') t)-rebuildAtup k av atup =-  case atup of-    NilAtup      -> pure NilAtup-    SnocAtup t a -> SnocAtup <$> rebuildAtup k av t <*> k av a+    -> RebuildAvar f fa acc aenv1 aenv2+    -> ALeftHandSide bndArrs aenv1 aenv1'+    -> acc aenv1  bndArrs+    -> acc aenv1' arrs+    -> f (PreOpenAcc acc aenv2 arrs)+rebuildAlet k av lhs1 bind1 body1+  | Exists lhs2 <- rebuildLHS lhs1+  = Alet lhs2 <$> k av bind1 <*> k (shiftA' lhs1 lhs2 k av) body1 +{-# INLINEABLE rebuildLHS #-}+rebuildLHS :: LeftHandSide s t aenv1 aenv1' -> Exists (LeftHandSide s t aenv2)+rebuildLHS (LeftHandSideWildcard r) = Exists $ LeftHandSideWildcard r+rebuildLHS (LeftHandSideSingle s)   = Exists $ LeftHandSideSingle s+rebuildLHS (LeftHandSidePair as bs)+  | Exists as' <- rebuildLHS as+  , Exists bs' <- rebuildLHS bs+  = Exists $ LeftHandSidePair as' bs'+ {-# INLINEABLE rebuildBoundary #-} rebuildBoundary-    :: (Applicative f, SyntacticAcc fa)-    => RebuildAcc acc-    -> (forall t'. Arrays t' => Idx aenv t' -> f (fa acc aenv' t'))-    -> PreBoundary acc aenv t-    -> f (PreBoundary acc aenv' t)-rebuildBoundary k av bndy =+    :: Applicative f+    => ReindexAvar f aenv aenv'+    -> Boundary aenv t+    -> f (Boundary aenv' t)+rebuildBoundary av bndy =   case bndy of     Clamp       -> pure Clamp     Mirror      -> pure Mirror     Wrap        -> pure Wrap     Constant v  -> pure (Constant v)-    Function f  -> Function <$> rebuildFun k (pure . IE) av f+    Function f  -> Function <$> rebuildFun (pure . IE) av f  {-- {-# INLINEABLE rebuildSeq #-} rebuildSeq     :: (SyntacticAcc fa, Applicative f)     => RebuildAcc acc-    -> (forall t'. Arrays t' => Idx aenv t' -> f (fa acc aenv' t'))+    -> RebuildAvar f fa acc aenv aenv'     -> PreOpenSeq acc aenv senv t     -> f (PreOpenSeq acc aenv' senv t) rebuildSeq k v seq =@@ -571,7 +769,7 @@ {-# INLINEABLE rebuildP #-} rebuildP :: (SyntacticAcc fa, Applicative f)          => RebuildAcc acc-         -> (forall t'. Arrays t' => Idx aenv t' -> f (fa acc aenv' t'))+         -> RebuildAvar f fa acc aenv aenv'          -> Producer acc aenv senv a          -> f (Producer acc aenv' senv a) rebuildP k v p =@@ -581,17 +779,17 @@     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+    ScanSeq f e x        -> ScanSeq <$> rebuildFun (pure . IE) v f <*> rebuildOpenExp (pure . IE) v e <*> pure x  {-# 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'))+         -> RebuildAvar f fa acc aenv aenv'          -> 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+    FoldSeq f e x          -> FoldSeq <$> rebuildFun (pure . IE) v f <*> rebuildOpenExp (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@@ -599,4 +797,10 @@     rebuildT NilAtup        = pure NilAtup     rebuildT (SnocAtup t s) = SnocAtup <$> (rebuildT t) <*> (rebuildC k v s) --}++extractExpVars :: OpenExp env aenv a -> Maybe (ExpVars env a)+extractExpVars Nil          = Just TupRunit+extractExpVars (Pair e1 e2) = TupRpair <$> extractExpVars e1 <*> extractExpVars e2+extractExpVars (Evar v)     = Just $ TupRsingle v+extractExpVars _            = Nothing 
+ src/Data/Array/Accelerate/Trafo/Var.hs view
@@ -0,0 +1,78 @@+{-# LANGUAGE GADTs               #-}+{-# LANGUAGE LambdaCase          #-}+{-# LANGUAGE RankNTypes          #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TypeOperators       #-}+-- |+-- Module      : Data.Array.Accelerate.Trafo.Var+-- Copyright   : [2012..2020] The Accelerate Team+-- License     : BSD3+--+-- Maintainer  : Trevor L. McDonell <trevor.mcdonell@gmail.com>+-- Stability   : experimental+-- Portability : non-portable (GHC extensions)+--++module Data.Array.Accelerate.Trafo.Var+  where++import Data.Array.Accelerate.AST+import Data.Array.Accelerate.AST.Environment+import Data.Array.Accelerate.AST.Idx+import Data.Array.Accelerate.AST.LeftHandSide+import Data.Array.Accelerate.AST.Var+import Data.Array.Accelerate.Representation.Array+import Data.Array.Accelerate.Representation.Type+++data DeclareVars s t aenv where+  DeclareVars :: LeftHandSide s t env env'+              -> (env :> env')+              -> (forall env''. env' :> env'' -> Vars s env'' t)+              -> DeclareVars s t env++declareVars :: TupR s t -> DeclareVars s t env+declareVars TupRunit+  = DeclareVars LeftHandSideUnit weakenId $ const $ TupRunit+declareVars (TupRsingle s)+  = DeclareVars (LeftHandSideSingle s) (weakenSucc weakenId) $ \k -> TupRsingle $ Var s $ k >:> ZeroIdx+declareVars (TupRpair r1 r2)+  | DeclareVars lhs1 subst1 a1 <- declareVars r1+  , DeclareVars lhs2 subst2 a2 <- declareVars r2+  = DeclareVars (LeftHandSidePair lhs1 lhs2) (subst2 .> subst1) $ \k -> a1 (k .> subst2) `TupRpair` a2 k+++type InjectAcc  acc = forall env t. PreOpenAcc acc env t -> acc env t+type ExtractAcc acc = forall env t. acc env t -> Maybe (PreOpenAcc acc env t)++avarIn :: InjectAcc acc+       -> ArrayVar aenv a+       -> acc aenv a+avarIn inject v@(Var ArrayR{} _) = inject (Avar v)++avarsIn :: forall acc aenv arrs.+           InjectAcc acc+        -> ArrayVars aenv arrs+        -> acc aenv arrs+avarsIn inject = go+  where+    go :: ArrayVars aenv t -> acc aenv t+    go TupRunit       = inject Anil+    go (TupRsingle v) = avarIn inject v+    go (TupRpair a b) = inject (go a `Apair` go b)++avarsOut+    :: ExtractAcc acc+    -> PreOpenAcc acc aenv a+    -> Maybe (ArrayVars aenv a)+avarsOut extract = \case+  Anil   -> Just $ TupRunit+  Avar v -> Just $ TupRsingle v+  Apair al ar+    | Just pl <- extract al+    , Just pr <- extract ar+    , Just as <- avarsOut extract pl+    , Just bs <- avarsOut extract pr+    -> Just (TupRpair as bs)+  _ -> Nothing+
src/Data/Array/Accelerate/Type.hs view
@@ -1,24 +1,30 @@-{-# LANGUAGE ConstraintKinds      #-}-{-# LANGUAGE DataKinds            #-}-{-# LANGUAGE DeriveDataTypeable   #-}-{-# LANGUAGE FlexibleInstances    #-}-{-# LANGUAGE GADTs                #-}-{-# LANGUAGE TemplateHaskell      #-}-{-# LANGUAGE TypeFamilies         #-}-{-# LANGUAGE TypeOperators        #-}-{-# OPTIONS_GHC -fno-warn-orphans #-}+{-# LANGUAGE BangPatterns        #-}+{-# LANGUAGE CPP                 #-}+{-# LANGUAGE ConstraintKinds     #-}+{-# LANGUAGE DataKinds           #-}+{-# LANGUAGE FlexibleInstances   #-}+{-# LANGUAGE GADTs               #-}+{-# LANGUAGE MagicHash           #-}+{-# LANGUAGE OverloadedStrings   #-}+{-# LANGUAGE PatternSynonyms     #-}+{-# LANGUAGE RoleAnnotations     #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TemplateHaskell     #-}+{-# LANGUAGE TypeApplications    #-}+{-# LANGUAGE TypeFamilies        #-}+{-# LANGUAGE TypeOperators       #-}+{-# LANGUAGE ViewPatterns        #-} {-# OPTIONS_HADDOCK hide #-} -- | -- Module      : Data.Array.Accelerate.Type--- Copyright   : [2008..2018] Manuel M T Chakravarty, Gabriele Keller---               [2009..2018] Trevor L. McDonell+-- Copyright   : [2008..2020] The Accelerate Team -- License     : BSD3 ----- Maintainer  : Trevor L. McDonell <tmcdonell@cse.unsw.edu.au>+-- Maintainer  : Trevor L. McDonell <trevor.mcdonell@gmail.com> -- Stability   : experimental -- Portability : non-portable (GHC extensions) -----  /Scalar types supported in array computations/+--  Primitive scalar types supported by Accelerate -- --  Integral types: --    * Int@@ -31,35 +37,18 @@ --    * Word16 --    * Word32 --    * Word64---    * CShort---    * CUShort---    * CInt---    * CUInt---    * CLong---    * CULong---    * CLLong---    * CULLong -- --  Floating types: --    * Half --    * Float --    * Double---    * CFloat---    * CDouble -----  Non-numeric types:---    * Bool---    * Char---    * CChar---    * CSChar---    * CUChar------  SIMD vector types:---    * V2---    * V3---    * V4---    * V8---    * V16+--  SIMD vector types of the above:+--    * Vec2+--    * Vec3+--    * Vec4+--    * Vec8+--    * Vec16 -- -- Note that 'Int' has the same bit width as in plain Haskell computations. -- 'Float' and 'Double' represent IEEE single and double precision floating@@ -67,95 +56,76 @@ --  module Data.Array.Accelerate.Type (-  Half(..), Float, Double, Char, Bool(..),++  Half(..), Float, Double,   module Data.Int,   module Data.Word,   module Foreign.C.Types,-  module Data.Array.Accelerate.Type-) where+  module Data.Array.Accelerate.Type, +) where -import Data.Orphans ()    -- orphan instances for 8-tuples and beyond+import Data.Array.Accelerate.Orphans () -- Prim Half+import Data.Primitive.Vec --- standard libraries import Data.Bits import Data.Int+import Data.Primitive.Types import Data.Type.Equality-import Data.Typeable import Data.Word-import GHC.TypeLits+import Foreign.C.Types+import Foreign.Storable                                             ( Storable ) import Language.Haskell.TH import Numeric.Half import Text.Printf-import Foreign.Storable-import Foreign.C.Types-    (CChar, CSChar, CUChar, CShort, CUShort, CInt, CUInt, CLong, CULong, CLLong, CULLong, CFloat, CDouble) +import GHC.Prim+import GHC.TypeLits + -- Scalar types -- ------------  -- Reified dictionaries --+data SingleDict a where+  SingleDict :: ( Eq a, Ord a, Show a, Storable a, Prim a )+             => SingleDict a  data IntegralDict a where-  IntegralDict :: ( Bounded a, Eq a, Ord a, Show a-                  , Bits a, FiniteBits a, Integral a, Num a, Real a, Storable a )+  IntegralDict :: ( Eq a, Ord a, Show a+                  , Bounded a, Bits a, FiniteBits a, Integral a, Num a, Real a, Storable a )                => IntegralDict a  data FloatingDict a where   FloatingDict :: ( Eq a, Ord a, Show a-                  , Floating a, Fractional a, Num a, Real a, RealFrac a-                  , RealFloat a, Storable a )+                  , Floating a, Fractional a, Num a, Real a, RealFrac a, RealFloat a, Storable a )                => FloatingDict a -data NonNumDict a where-  NonNumDict :: ( Bounded a, Eq a, Ord a, Show a, Storable a )-             => NonNumDict a - -- Scalar type representation --  -- | Integral types supported in array computations. -- data IntegralType a where-  TypeInt     :: IntegralDict Int     -> IntegralType Int-  TypeInt8    :: IntegralDict Int8    -> IntegralType Int8-  TypeInt16   :: IntegralDict Int16   -> IntegralType Int16-  TypeInt32   :: IntegralDict Int32   -> IntegralType Int32-  TypeInt64   :: IntegralDict Int64   -> IntegralType Int64-  TypeWord    :: IntegralDict Word    -> IntegralType Word-  TypeWord8   :: IntegralDict Word8   -> IntegralType Word8-  TypeWord16  :: IntegralDict Word16  -> IntegralType Word16-  TypeWord32  :: IntegralDict Word32  -> IntegralType Word32-  TypeWord64  :: IntegralDict Word64  -> IntegralType Word64-  TypeCShort  :: IntegralDict CShort  -> IntegralType CShort-  TypeCUShort :: IntegralDict CUShort -> IntegralType CUShort-  TypeCInt    :: IntegralDict CInt    -> IntegralType CInt-  TypeCUInt   :: IntegralDict CUInt   -> IntegralType CUInt-  TypeCLong   :: IntegralDict CLong   -> IntegralType CLong-  TypeCULong  :: IntegralDict CULong  -> IntegralType CULong-  TypeCLLong  :: IntegralDict CLLong  -> IntegralType CLLong-  TypeCULLong :: IntegralDict CULLong -> IntegralType CULLong+  TypeInt     :: IntegralType Int+  TypeInt8    :: IntegralType Int8+  TypeInt16   :: IntegralType Int16+  TypeInt32   :: IntegralType Int32+  TypeInt64   :: IntegralType Int64+  TypeWord    :: IntegralType Word+  TypeWord8   :: IntegralType Word8+  TypeWord16  :: IntegralType Word16+  TypeWord32  :: IntegralType Word32+  TypeWord64  :: IntegralType Word64  -- | Floating-point types supported in array computations. -- data FloatingType a where-  TypeHalf    :: FloatingDict Half    -> FloatingType Half-  TypeFloat   :: FloatingDict Float   -> FloatingType Float-  TypeDouble  :: FloatingDict Double  -> FloatingType Double-  TypeCFloat  :: FloatingDict CFloat  -> FloatingType CFloat-  TypeCDouble :: FloatingDict CDouble -> FloatingType CDouble---- | Non-numeric types supported in array computations.----data NonNumType a where-  TypeBool    :: NonNumDict Bool      -> NonNumType Bool   --  marshalled to Word8-  TypeChar    :: NonNumDict Char      -> NonNumType Char-  TypeCChar   :: NonNumDict CChar     -> NonNumType CChar-  TypeCSChar  :: NonNumDict CSChar    -> NonNumType CSChar-  TypeCUChar  :: NonNumDict CUChar    -> NonNumType CUChar+  TypeHalf    :: FloatingType Half+  TypeFloat   :: FloatingType Float+  TypeDouble  :: FloatingType Double  -- | Numeric element types implement Num & Real --@@ -167,61 +137,35 @@ -- data BoundedType a where   IntegralBoundedType :: IntegralType a -> BoundedType a-  NonNumBoundedType   :: NonNumType a   -> BoundedType a  -- | All scalar element types implement Eq & Ord -- data ScalarType a where-  SingleScalarType :: SingleType a     -> ScalarType a-  VectorScalarType :: VectorType (v a) -> ScalarType (v a)+  SingleScalarType :: SingleType a         -> ScalarType a+  VectorScalarType :: VectorType (Vec n a) -> ScalarType (Vec n a)  data SingleType a where-  NumSingleType    :: NumType a    -> SingleType a-  NonNumSingleType :: NonNumType a -> SingleType a--data VectorType v where-  Vector2Type   :: SingleType a -> VectorType (V2 a)-  Vector3Type   :: SingleType a -> VectorType (V3 a)-  Vector4Type   :: SingleType a -> VectorType (V4 a)-  Vector8Type   :: SingleType a -> VectorType (V8 a)-  Vector16Type  :: SingleType a -> VectorType (V16 a)+  NumSingleType :: NumType a -> SingleType a --- Showing type names---+data VectorType a where+  VectorType :: KnownNat n => {-# UNPACK #-} !Int -> SingleType a -> VectorType (Vec n a)  instance Show (IntegralType a) where-  show (TypeInt _)     = "Int"-  show (TypeInt8 _)    = "Int8"-  show (TypeInt16 _)   = "Int16"-  show (TypeInt32 _)   = "Int32"-  show (TypeInt64 _)   = "Int64"-  show (TypeWord _)    = "Word"-  show (TypeWord8 _)   = "Word8"-  show (TypeWord16 _)  = "Word16"-  show (TypeWord32 _)  = "Word32"-  show (TypeWord64 _)  = "Word64"-  show (TypeCShort _)  = "CShort"-  show (TypeCUShort _) = "CUShort"-  show (TypeCInt _)    = "CInt"-  show (TypeCUInt _)   = "CUInt"-  show (TypeCLong _)   = "CLong"-  show (TypeCULong _)  = "CULong"-  show (TypeCLLong _)  = "CLLong"-  show (TypeCULLong _) = "CULLong"+  show TypeInt    = "Int"+  show TypeInt8   = "Int8"+  show TypeInt16  = "Int16"+  show TypeInt32  = "Int32"+  show TypeInt64  = "Int64"+  show TypeWord   = "Word"+  show TypeWord8  = "Word8"+  show TypeWord16 = "Word16"+  show TypeWord32 = "Word32"+  show TypeWord64 = "Word64"  instance Show (FloatingType a) where-  show (TypeHalf _)    = "Half"-  show (TypeFloat _)   = "Float"-  show (TypeDouble _)  = "Double"-  show (TypeCFloat _)  = "CFloat"-  show (TypeCDouble _) = "CDouble"--instance Show (NonNumType a) where-  show (TypeBool _)   = "Bool"-  show (TypeChar _)   = "Char"-  show (TypeCChar _)  = "CChar"-  show (TypeCSChar _) = "CSChar"-  show (TypeCUChar _) = "CUChar"+  show TypeHalf   = "Half"+  show TypeFloat  = "Float"+  show TypeDouble = "Double"  instance Show (NumType a) where   show (IntegralNumType ty) = show ty@@ -229,175 +173,219 @@  instance Show (BoundedType a) where   show (IntegralBoundedType ty) = show ty-  show (NonNumBoundedType ty)   = show ty  instance Show (SingleType a) where-  show (NumSingleType ty)    = show ty-  show (NonNumSingleType ty) = show ty+  show (NumSingleType ty) = show ty  instance Show (VectorType a) where-  show (Vector2Type t)  = printf "<2 x %s>" (show t)-  show (Vector3Type t)  = printf "<3 x %s>" (show t)-  show (Vector4Type t)  = printf "<4 x %s>" (show t)-  show (Vector8Type t)  = printf "<8 x %s>" (show t)-  show (Vector16Type t) = printf "<16 x %s>" (show t)+  show (VectorType n ty) = printf "<%d x %s>" n (show ty)  instance Show (ScalarType a) where   show (SingleScalarType ty) = show ty   show (VectorScalarType ty) = show ty ---- Querying scalar type representations------- | Integral types+-- | Querying Integral types -- class (IsSingle a, IsNum a, IsBounded a) => IsIntegral a where   integralType :: IntegralType a --- | Floating types+-- | Querying Floating types -- class (Floating a, IsSingle a, IsNum a) => IsFloating a where   floatingType :: FloatingType a --- | Non-numeric types----class IsNonNum a where-  nonNumType :: NonNumType a---- | Numeric types+-- | Querying Numeric types -- class (Num a, IsSingle a) => IsNum a where   numType :: NumType a --- | Bounded types+-- | Querying Bounded types -- class IsBounded a where   boundedType :: BoundedType a --- | All single value types+-- | Querying single value types -- class IsScalar a => IsSingle a where   singleType :: SingleType a --- | All scalar types+-- | Querying all scalar types ---class Typeable a => IsScalar a where+class IsScalar a where   scalarType :: ScalarType a  --- Extract reified dictionaries---- integralDict :: IntegralType a -> IntegralDict a-integralDict (TypeInt     dict) = dict-integralDict (TypeInt8    dict) = dict-integralDict (TypeInt16   dict) = dict-integralDict (TypeInt32   dict) = dict-integralDict (TypeInt64   dict) = dict-integralDict (TypeWord    dict) = dict-integralDict (TypeWord8   dict) = dict-integralDict (TypeWord16  dict) = dict-integralDict (TypeWord32  dict) = dict-integralDict (TypeWord64  dict) = dict-integralDict (TypeCShort  dict) = dict-integralDict (TypeCUShort dict) = dict-integralDict (TypeCInt    dict) = dict-integralDict (TypeCUInt   dict) = dict-integralDict (TypeCLong   dict) = dict-integralDict (TypeCULong  dict) = dict-integralDict (TypeCLLong  dict) = dict-integralDict (TypeCULLong dict) = dict+integralDict TypeInt    = IntegralDict+integralDict TypeInt8   = IntegralDict+integralDict TypeInt16  = IntegralDict+integralDict TypeInt32  = IntegralDict+integralDict TypeInt64  = IntegralDict+integralDict TypeWord   = IntegralDict+integralDict TypeWord8  = IntegralDict+integralDict TypeWord16 = IntegralDict+integralDict TypeWord32 = IntegralDict+integralDict TypeWord64 = IntegralDict  floatingDict :: FloatingType a -> FloatingDict a-floatingDict (TypeHalf    dict) = dict-floatingDict (TypeFloat   dict) = dict-floatingDict (TypeDouble  dict) = dict-floatingDict (TypeCFloat  dict) = dict-floatingDict (TypeCDouble dict) = dict+floatingDict TypeHalf   = FloatingDict+floatingDict TypeFloat  = FloatingDict+floatingDict TypeDouble = FloatingDict -nonNumDict :: NonNumType a -> NonNumDict a-nonNumDict (TypeBool   dict) = dict-nonNumDict (TypeChar   dict) = dict-nonNumDict (TypeCChar  dict) = dict-nonNumDict (TypeCSChar dict) = dict-nonNumDict (TypeCUChar dict) = dict+singleDict :: SingleType a -> SingleDict a+singleDict = single+  where+    single :: SingleType a -> SingleDict a+    single (NumSingleType    t) = num t +    num :: NumType a -> SingleDict a+    num (IntegralNumType t) = integral t+    num (FloatingNumType t) = floating t --- Type representation--- ------------------------- Representation of product types, consisting of:------   * unit (void)------   * scalar types: values which go in registers. These may be single value---     types such as int and float, or SIMD vectors of single value types such---     as <4 * float>. We do not allow vectors-of-vectors.------   * pairs: representing compound values (i.e. tuples) where each component---     will be stored in a separate array.----data TupleType a where-  TypeRunit   ::                               TupleType ()-  TypeRscalar :: ScalarType a               -> TupleType a-  TypeRpair   :: TupleType a -> TupleType b -> TupleType (a, b)+    integral :: IntegralType a -> SingleDict a+    integral TypeInt    = SingleDict+    integral TypeInt8   = SingleDict+    integral TypeInt16  = SingleDict+    integral TypeInt32  = SingleDict+    integral TypeInt64  = SingleDict+    integral TypeWord   = SingleDict+    integral TypeWord8  = SingleDict+    integral TypeWord16 = SingleDict+    integral TypeWord32 = SingleDict+    integral TypeWord64 = SingleDict -instance Show (TupleType a) where-  show TypeRunit        = "()"-  show (TypeRscalar t)  = show t-  show (TypeRpair a b)  = printf "(%s,%s)" (show a) (show b)+    floating :: FloatingType a -> SingleDict a+    floating TypeHalf   = SingleDict+    floating TypeFloat  = SingleDict+    floating TypeDouble = SingleDict  --- Type-level bit sizes--- --------------------+scalarTypeInt :: ScalarType Int+scalarTypeInt = SingleScalarType $ NumSingleType $ IntegralNumType TypeInt --- |Constraint that values of these two types have the same bit width----type BitSizeEq a b = (BitSize a == BitSize b) ~ 'True+scalarTypeWord :: ScalarType Word+scalarTypeWord = SingleScalarType $ NumSingleType $ IntegralNumType TypeWord -type family BitSize a :: Nat+scalarTypeInt32 :: ScalarType Int32+scalarTypeInt32 = SingleScalarType $ NumSingleType $ IntegralNumType TypeInt32 +scalarTypeWord8 :: ScalarType Word8+scalarTypeWord8 = SingleScalarType $ NumSingleType $ IntegralNumType TypeWord8 --- SIMD vector types--- -----------------+scalarTypeWord32 :: ScalarType Word32+scalarTypeWord32 = SingleScalarType $ NumSingleType $ IntegralNumType TypeWord32 -data V2 a  = V2 !a !a-  deriving (Typeable, Eq, Ord)+rnfScalarType :: ScalarType t -> ()+rnfScalarType (SingleScalarType t) = rnfSingleType t+rnfScalarType (VectorScalarType t) = rnfVectorType t -data V3 a  = V3 !a !a !a-  deriving (Typeable, Eq, Ord)+rnfSingleType :: SingleType t -> ()+rnfSingleType (NumSingleType t) = rnfNumType t -data V4 a  = V4 !a !a !a !a-  deriving (Typeable, Eq, Ord)+rnfVectorType :: VectorType t -> ()+rnfVectorType (VectorType !_ t) = rnfSingleType t -data V8 a  = V8 !a !a !a !a !a !a !a !a-  deriving (Typeable, Eq, Ord)+rnfBoundedType :: BoundedType t -> ()+rnfBoundedType (IntegralBoundedType t) = rnfIntegralType t -data V16 a = V16 !a !a !a !a !a !a !a !a !a !a !a !a !a !a !a !a-  deriving (Typeable, Eq, Ord)+rnfNumType :: NumType t -> ()+rnfNumType (IntegralNumType t) = rnfIntegralType t+rnfNumType (FloatingNumType t) = rnfFloatingType t -instance Show a => Show (V2 a) where-  show (V2 a b) = printf "<%s,%s>" (show a) (show b)+rnfIntegralType :: IntegralType t -> ()+rnfIntegralType TypeInt    = ()+rnfIntegralType TypeInt8   = ()+rnfIntegralType TypeInt16  = ()+rnfIntegralType TypeInt32  = ()+rnfIntegralType TypeInt64  = ()+rnfIntegralType TypeWord   = ()+rnfIntegralType TypeWord8  = ()+rnfIntegralType TypeWord16 = ()+rnfIntegralType TypeWord32 = ()+rnfIntegralType TypeWord64 = () -instance Show a => Show (V3 a) where-  show (V3 a b c) = printf "<%s,%s,%s>" (show a) (show b) (show c)+rnfFloatingType :: FloatingType t -> ()+rnfFloatingType TypeHalf   = ()+rnfFloatingType TypeFloat  = ()+rnfFloatingType TypeDouble = () -instance Show a => Show (V4 a) where-  show (V4 a b c d) = printf "<%s,%s,%s,%s>" (show a) (show b) (show c) (show d) -instance Show a => Show (V8 a) where-  show (V8 a b c d e f g h) =-    printf "<%s,%s,%s,%s,%s,%s,%s,%s>"-      (show a) (show b) (show c) (show d) (show e) (show f) (show g) (show h)+liftScalar :: ScalarType t -> t -> Q (TExp t)+liftScalar (SingleScalarType t) = liftSingle t+liftScalar (VectorScalarType t) = liftVector t -instance Show a => Show (V16 a) where-  show (V16 a b c d e f g h i j k l m n o p) =-    printf "<%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s>"-      (show a) (show b) (show c) (show d) (show e) (show f) (show g) (show h)-      (show i) (show j) (show k) (show l) (show m) (show n) (show o) (show p)+liftSingle :: SingleType t -> t -> Q (TExp t)+liftSingle (NumSingleType t) = liftNum t +liftVector :: VectorType t -> t -> Q (TExp t)+liftVector VectorType{} = liftVec +liftNum :: NumType t -> t -> Q (TExp t)+liftNum (IntegralNumType t) = liftIntegral t+liftNum (FloatingNumType t) = liftFloating t++liftIntegral :: IntegralType t -> t -> Q (TExp t)+liftIntegral TypeInt    x = [|| x ||]+liftIntegral TypeInt8   x = [|| x ||]+liftIntegral TypeInt16  x = [|| x ||]+liftIntegral TypeInt32  x = [|| x ||]+liftIntegral TypeInt64  x = [|| x ||]+liftIntegral TypeWord   x = [|| x ||]+liftIntegral TypeWord8  x = [|| x ||]+liftIntegral TypeWord16 x = [|| x ||]+liftIntegral TypeWord32 x = [|| x ||]+liftIntegral TypeWord64 x = [|| x ||]++liftFloating :: FloatingType t -> t -> Q (TExp t)+liftFloating TypeHalf   x = [|| x ||]+liftFloating TypeFloat  x = [|| x ||]+liftFloating TypeDouble x = [|| x ||]+++liftScalarType :: ScalarType t -> Q (TExp (ScalarType t))+liftScalarType (SingleScalarType t) = [|| SingleScalarType $$(liftSingleType t) ||]+liftScalarType (VectorScalarType t) = [|| VectorScalarType $$(liftVectorType t) ||]++liftSingleType :: SingleType t -> Q (TExp (SingleType t))+liftSingleType (NumSingleType t) = [|| NumSingleType $$(liftNumType t) ||]++liftVectorType :: VectorType t -> Q (TExp (VectorType t))+liftVectorType (VectorType n t) = [|| VectorType n $$(liftSingleType t) ||]++liftNumType :: NumType t -> Q (TExp (NumType t))+liftNumType (IntegralNumType t) = [|| IntegralNumType $$(liftIntegralType t) ||]+liftNumType (FloatingNumType t) = [|| FloatingNumType $$(liftFloatingType t) ||]++liftBoundedType :: BoundedType t -> Q (TExp (BoundedType t))+liftBoundedType (IntegralBoundedType t) = [|| IntegralBoundedType $$(liftIntegralType t) ||]++liftIntegralType :: IntegralType t -> Q (TExp (IntegralType t))+liftIntegralType TypeInt    = [|| TypeInt ||]+liftIntegralType TypeInt8   = [|| TypeInt8 ||]+liftIntegralType TypeInt16  = [|| TypeInt16 ||]+liftIntegralType TypeInt32  = [|| TypeInt32 ||]+liftIntegralType TypeInt64  = [|| TypeInt64 ||]+liftIntegralType TypeWord   = [|| TypeWord ||]+liftIntegralType TypeWord8  = [|| TypeWord8 ||]+liftIntegralType TypeWord16 = [|| TypeWord16 ||]+liftIntegralType TypeWord32 = [|| TypeWord32 ||]+liftIntegralType TypeWord64 = [|| TypeWord64 ||]++liftFloatingType :: FloatingType t -> Q (TExp (FloatingType t))+liftFloatingType TypeHalf   = [|| TypeHalf ||]+liftFloatingType TypeFloat  = [|| TypeFloat ||]+liftFloatingType TypeDouble = [|| TypeDouble ||]+++-- 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++ -- Instances -- --------- --@@ -407,55 +395,39 @@ -- to split this into a separate module. -- -$( runQ $ do+$(runQ $ do   let       bits :: FiniteBits b => b -> Integer       bits = toInteger . finiteBitSize        integralTypes :: [(Name, Integer)]       integralTypes =-        [ (''Int,     bits (undefined::Int))-        , (''Int8,    8)-        , (''Int16,   16)-        , (''Int32,   32)-        , (''Int64,   64)-        , (''Word,    bits (undefined::Word))-        , (''Word8,   8)-        , (''Word16,  16)-        , (''Word32,  32)-        , (''Word64,  64)-        , (''CShort,  16)-        , (''CUShort, 16)-        , (''CInt,    32)-        , (''CUInt,   32)-        , (''CLong,   bits (undefined::CLong))-        , (''CULong,  bits (undefined::CULong))-        , (''CLLong,  64)-        , (''CULLong, 64)+        [ (''Int,    bits (undefined::Int))+        , (''Int8,   8)+        , (''Int16,  16)+        , (''Int32,  32)+        , (''Int64,  64)+        , (''Word,   bits (undefined::Word))+        , (''Word8,  8)+        , (''Word16, 16)+        , (''Word32, 32)+        , (''Word64, 64)         ]        floatingTypes :: [(Name, Integer)]       floatingTypes =-        [ (''Half,    16)-        , (''Float,   32)-        , (''Double,  64)-        , (''CFloat,  32)-        , (''CDouble, 64)+        [ (''Half,   16)+        , (''Float,  32)+        , (''Double, 64)         ] -      nonNumTypes :: [(Name, Integer)]-      nonNumTypes =-        [ (''Bool,   8)    -- stored as Word8-        , (''Char,   32)-        , (''CChar,  8)-        , (''CSChar, 8)-        , (''CUChar, 8)-        ]+      vectorTypes :: [(Name, Integer)]+      vectorTypes = integralTypes ++ floatingTypes        mkIntegral :: Name -> Integer -> Q [Dec]       mkIntegral t n =         [d| instance IsIntegral $(conT t) where-              integralType = $(conE (mkName ("Type" ++ nameBase t))) IntegralDict+              integralType = $(conE (mkName ("Type" ++ nameBase t)))              instance IsNum $(conT t) where               numType = IntegralNumType integralType@@ -475,7 +447,7 @@       mkFloating :: Name -> Integer -> Q [Dec]       mkFloating t n =         [d| instance IsFloating $(conT t) where-              floatingType = $(conE (mkName ("Type" ++ nameBase t))) FloatingDict+              floatingType = $(conE (mkName ("Type" ++ nameBase t)))              instance IsNum $(conT t) where               numType = FloatingNumType floatingType@@ -489,52 +461,18 @@             type instance BitSize $(conT t) = $(litT (numTyLit n))           |] -      mkNonNum :: Name -> Integer -> Q [Dec]-      mkNonNum t n =-        [d| instance IsNonNum $(conT t) where-              nonNumType = $(conE (mkName ("Type" ++ nameBase t))) NonNumDict--            instance IsBounded $(conT t) where-              boundedType = NonNumBoundedType nonNumType--            instance IsSingle $(conT t) where-              singleType = NonNumSingleType nonNumType--            instance IsScalar $(conT t) where-              scalarType = SingleScalarType singleType--            type instance BitSize $(conT t) = $(litT (numTyLit n))-          |]-       mkVector :: Name -> Integer -> Q [Dec]       mkVector t n =-        [d| instance IsScalar (V2 $(conT t)) where-              scalarType = VectorScalarType (Vector2Type singleType)--            instance IsScalar (V3 $(conT t)) where-              scalarType = VectorScalarType (Vector3Type singleType)--            instance IsScalar (V4 $(conT t)) where-              scalarType = VectorScalarType (Vector4Type singleType)--            instance IsScalar (V8 $(conT t)) where-              scalarType = VectorScalarType (Vector8Type singleType)--            instance IsScalar (V16 $(conT t)) where-              scalarType = VectorScalarType (Vector16Type singleType)+        [d| instance KnownNat n => IsScalar (Vec n $(conT t)) where+              scalarType = VectorScalarType (VectorType (fromIntegral (natVal' (proxy# :: Proxy# n))) singleType) -            type instance BitSize (V2 $(conT t))  = $(litT (numTyLit (2*n)))-            type instance BitSize (V3 $(conT t))  = $(litT (numTyLit (3*n)))-            type instance BitSize (V4 $(conT t))  = $(litT (numTyLit (4*n)))-            type instance BitSize (V8 $(conT t))  = $(litT (numTyLit (8*n)))-            type instance BitSize (V16 $(conT t)) = $(litT (numTyLit (16*n)))+            type instance BitSize (Vec w $(conT t)) = w GHC.TypeLits.* $(litT (numTyLit n))           |]       --   is <- mapM (uncurry mkIntegral) integralTypes   fs <- mapM (uncurry mkFloating) floatingTypes-  ns <- mapM (uncurry mkNonNum)   nonNumTypes-  vs <- mapM (uncurry mkVector)  (integralTypes ++ floatingTypes ++ nonNumTypes)+  vs <- mapM (uncurry mkVector)   vectorTypes   ---  return (concat is ++ concat fs ++ concat ns ++ concat vs)+  return (concat is ++ concat fs ++ concat vs)  ) 
src/Data/Array/Accelerate/Unsafe.hs view
@@ -1,9 +1,11 @@+{-# LANGUAGE MonoLocalBinds        #-}+{-# LANGUAGE FlexibleContexts      #-} -- | -- Module      : Data.Array.Accelerate.Unsafe--- Copyright   : [2009..2018] Manuel M T Chakravarty, Gabriele Keller, Trevor L. McDonell+-- Copyright   : [2009..2020] The Accelerate Team -- License     : BSD3 ----- Maintainer  : Trevor L. McDonell <tmcdonell@cse.unsw.edu.au>+-- Maintainer  : Trevor L. McDonell <trevor.mcdonell@gmail.com> -- Stability   : experimental -- Portability : non-portable (GHC extensions) --@@ -15,12 +17,13 @@ module Data.Array.Accelerate.Unsafe (    -- ** Unsafe operations-  undef, coerce,+  Coerce, coerce,+  undef,  ) where -import Data.Array.Accelerate.Array.Sugar import Data.Array.Accelerate.Smart+import Data.Array.Accelerate.Sugar.Elt   -- | The function 'coerce' allows you to convert a value between any two types@@ -33,17 +36,17 @@ -- -- Furthermore, as we typically declare newtype wrappers similarly to: ----- > type instance EltRepr (Sum a) = ((), EltRepr a)+-- > type instance EltR (Sum a) = ((), EltR a) -- -- This can be used instead of the newtype constructor, to go from the newtype's -- abstract type to the concrete type by dropping the extra @()@ from the -- representation, and vice-versa. ----- You will get a runtime error if it fails to find a coercion between the two--- representations.+-- The type class 'Coerce' assures that there is a coercion between the two+-- types. -- -- @since 1.2.0.0 ---coerce :: (Elt a, Elt b) => Exp a -> Exp b-coerce = mkUnsafeCoerce+coerce :: Coerce (EltR a) (EltR b) => Exp a -> Exp b+coerce = mkCoerce 
src/Data/Atomic.hs view
@@ -1,13 +1,15 @@ {-# LANGUAGE ForeignFunctionInterface #-} {-# LANGUAGE MagicHash                #-} {-# LANGUAGE NoImplicitPrelude        #-}+{-# LANGUAGE TemplateHaskell          #-} {-# LANGUAGE UnboxedTuples            #-}+{-# OPTIONS_GHC -fobject-code #-} -- | -- Module      : Data.Atomic--- Copyright   : [2016..2017] Manuel M T Chakravarty, Gabriele Keller, Trevor L. McDonell+-- Copyright   : [2016..2020] The Accelerate Team -- License     : BSD3 ----- Maintainer  : Trevor L. McDonell <tmcdonell@cse.unsw.edu.au>+-- Maintainer  : Trevor L. McDonell <trevor.mcdonell@gmail.com> -- Stability   : experimental -- Portability : non-portable (GHC extensions) --@@ -22,6 +24,7 @@ ) where  import Data.Int+import Language.Haskell.TH.Syntax  import GHC.Ptr import GHC.Base@@ -65,4 +68,10 @@ -- | Decrement the atomic value by the given amount. Return the old value. -- foreign import ccall unsafe "atomic_fetch_and_sub_64" subtract :: Atomic -> Int64 -> IO Int64++-- SEE: [linking to .c files]+--+runQ $ do+  addForeignFilePath LangC "cbits/atomic.c"+  return [] 
+ src/Data/BitSet.hs view
@@ -0,0 +1,162 @@+{-# LANGUAGE BangPatterns #-}+{-# LANGUAGE TypeFamilies #-}+{-# OPTIONS_HADDOCK hide #-}+-- |+-- Module      : Data.BitSet+-- Copyright   : [2019..2020] The Accelerate Team+-- License     : BSD3+--+-- Maintainer  : Trevor L. McDonell <trevor.mcdonell@gmail.com>+-- Stability   : experimental+-- Portability : non-portable (GHC extensions)+--++module Data.BitSet where++import Data.Bits+import Prelude                                            hiding ( foldl, foldr )+import qualified Data.List                                as List++import GHC.Exts                                           ( IsList, build )+import qualified GHC.Exts                                 as Exts+++-- | A space-efficient implementation of a set data structure for+-- enumerated data types.+--+newtype BitSet c a = BitSet { getBits :: c }+  deriving Eq++instance (Enum a, Show a, Bits c, Num c) => Show (BitSet c a) where+  showsPrec p bs+    = showParen (p > 10)+    $ showString "fromList " . shows (toList bs)++instance (Enum a, Bits c) => Semigroup (BitSet c a) where+  (<>) = union++instance (Enum a, Bits c, Num c) => Monoid (BitSet c a) where+  mempty = empty++instance (Enum a, Bits c, Num c) => IsList (BitSet c a) where+  type Item (BitSet c a) = a+  fromList = fromList+  toList   = toList+  {-# INLINE fromList #-}+  {-# INLINE toList   #-}++-- | Is the bit set empty?+--+{-# INLINE null #-}+null :: (Eq c, Num c) => BitSet c a -> Bool+null (BitSet bits) = bits == 0++-- | The number of elements in the bit set.+--+{-# INLINE size #-}+size :: Bits c => BitSet c a -> Int+size (BitSet bits) = popCount bits++-- | Ask whether the item is in the bit set.+--+{-# INLINE member #-}+member :: (Enum a , Bits c) => a -> BitSet c a -> Bool+member x (BitSet bits) = bits `testBit` fromEnum x++-- | The empty bit set.+--+{-# INLINE empty #-}+empty :: (Enum a, Bits c, Num c) => BitSet c a+empty = BitSet 0++-- | Create a singleton set.+--+{-# INLINE singleton #-}+singleton :: (Enum a, Bits c, Num c) => a -> BitSet c a+singleton x = BitSet $! bit (fromEnum x)++-- | Insert an item into the bit set.+--+{-# INLINE insert #-}+insert :: (Enum a, Bits c) => a -> BitSet c a -> BitSet c a+insert x (BitSet bits) = BitSet $! bits `setBit` fromEnum x++-- | Delete an item from the bit set.+{-# INLINE delete #-}+delete :: (Enum a, Bits c) => a -> BitSet c a -> BitSet c a+delete x (BitSet bits ) = BitSet $! bits `clearBit` fromEnum x++-- | The union of two bit sets.+--+{-# INLINE union #-}+union :: Bits c => BitSet c a -> BitSet c a -> BitSet c a+union (BitSet bits1) (BitSet bits2) = BitSet $! bits1 .|. bits2++-- | Difference of two bit sets.+--+{-# INLINE difference #-}+difference :: Bits c => BitSet c a -> BitSet c a -> BitSet c a+difference (BitSet bits1) (BitSet bits2) = BitSet $! bits1 .&. complement bits2++-- | See 'difference'.+--+infix 5 \\ -- comment to fool cpp: https://downloads.haskell.org/~ghc/latest/docs/html/users_guide/phases.html#cpp-and-string-gaps+{-# INLINE (\\) #-}+(\\) :: Bits c => BitSet c a -> BitSet c a -> BitSet c a+(\\) = difference++-- | The intersection of two bit sets.+--+{-# INLINE intersection #-}+intersection :: Bits c => BitSet c a -> BitSet c a -> BitSet c a+intersection (BitSet bits1) (BitSet bits2) = BitSet $! bits1 .&. bits2++-- | Transform this bit set by applying a function to every value.+-- Resulting bit set may be smaller then the original.+--+{-# INLINE map #-}+map :: (Enum a, Enum b, Bits c, Num c) => (a -> b) -> BitSet c a -> BitSet c b+map f = foldl' (\bs a -> f a `insert` bs) empty++-- | Reduce this bit set by applying a binary function to all elements,+-- using the given starting value. Each application of the operator is+-- evaluated before before using the result in the next application. This+-- function is strict in the starting value.+--+{-# INLINE foldl' #-}+foldl' :: (Enum a, Bits c) => (b -> a -> b) -> b -> BitSet c a -> b+foldl' f z (BitSet bits) = go z (popCount bits) 0+  where+    go !acc 0  !_ = acc+    go !acc !n !b = if bits `testBit` b+                      then go (f acc $ toEnum b) (pred n) (succ b)+                      else go acc n (succ b)++-- | Reduce this bit set by applying a binary function to all elements,+-- using the given starting value.+--+{-# INLINE foldr #-}+foldr :: (Enum a, Bits c) => (a -> b -> b) -> b -> BitSet c a -> b+foldr f z (BitSet bits) = go (popCount bits) 0+  where+    go 0  !_ = z+    go !n !b = if bits `testBit` b+                 then toEnum b `f` go (pred n) (succ b)+                 else go n (succ b)++-- | Convert this bit set set to a list of elements.+--+{-# INLINE [0] toList #-}+toList :: (Enum a, Bits c, Num c) => BitSet c a -> [a]+toList bs = build (\k z -> foldr k z bs)++-- | Make a bit set from a list of elements.+--+{-# INLINE [0] fromList #-}+fromList :: (Enum a, Bits c, Num c) => [a] -> BitSet c a+fromList xs = BitSet $! List.foldl' (\i x -> i `setBit` fromEnum x) 0 xs++{-# RULES+"fromList/toList" forall bs. fromList (toList bs) = bs+  #-}+
+ src/Data/Primitive/Vec.hs view
@@ -0,0 +1,290 @@+{-# LANGUAGE BangPatterns        #-}+{-# LANGUAGE DataKinds           #-}+{-# LANGUAGE GADTs               #-}+{-# LANGUAGE KindSignatures      #-}+{-# LANGUAGE MagicHash           #-}+{-# LANGUAGE OverloadedStrings   #-}+{-# LANGUAGE PatternSynonyms     #-}+{-# LANGUAGE RoleAnnotations     #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TemplateHaskell     #-}+{-# LANGUAGE UnboxedTuples       #-}+{-# LANGUAGE ViewPatterns        #-}+{-# OPTIONS_HADDOCK hide #-}+-- |+-- Module      : Data.Primitive.Vec+-- Copyright   : [2008..2020] The Accelerate Team+-- License     : BSD3+--+-- Maintainer  : Trevor L. McDonell <trevor.mcdonell@gmail.com>+-- Stability   : experimental+-- Portability : non-portable (GHC extensions)+--++module Data.Primitive.Vec (++  -- * SIMD vector types+  Vec(..),+  Vec2, pattern Vec2,+  Vec3, pattern Vec3,+  Vec4, pattern Vec4,+  Vec8, pattern Vec8,+  Vec16, pattern Vec16,++  listOfVec,+  liftVec,++) where++import Control.Monad.ST+import Data.Primitive.ByteArray+import Data.Primitive.Types+import Data.Text.Prettyprint.Doc+import Language.Haskell.TH+import Language.Haskell.TH.Syntax++import GHC.Base                                                     ( isTrue# )+import GHC.Int+import GHC.Prim+import GHC.TypeLits+import GHC.Word+++-- Note: [Representing SIMD vector types]+--+-- A simple polymorphic representation of SIMD types such as the following:+--+-- > data Vec2 a = Vec2 !a !a+--+-- is not able to unpack the values into the constructor, meaning that+-- 'Vec2' is storing pointers to (strict) values on the heap, which is+-- a very inefficient representation.+--+-- We might try defining a data family instead so that we can get efficient+-- unboxed representations, and even make use of the unlifted SIMD types GHC+-- knows about:+--+-- > data family Vec2 a :: *+-- > data instance Vec2 Float    = Vec2_Float Float# Float#   -- reasonable+-- > data instance Vec2 Double   = Vec2_Double DoubleX2#      -- built in!+--+-- However, this runs into the problem that GHC stores all values as word sized+-- entities:+--+-- > data instance Vec2 Int      = Vec2_Int Int# Int#+-- > data instance Vec2 Int8     = Vec2_Int8 Int8# Int8#      -- Int8# does not exist; requires a full Int#+--+-- which, again, is very memory inefficient.+--+-- So, as a last resort, we'll just use a ByteArray# to ensure an efficient+-- packed representation.+--+-- One inefficiency of this approach is that the byte array does track its size,+-- which redundant for our use case (derivable from type level information).+--+data Vec (n :: Nat) a = Vec ByteArray#++type role Vec nominal representational++instance (Show a, Prim a, KnownNat n) => Show (Vec n a) where+  show = vec . listOfVec+    where+      vec :: [a] -> String+      vec = show+          . group . encloseSep (flatAlt "< " "<") (flatAlt " >" ">") ", "+          . map viaShow++listOfVec :: forall a n. (Prim a, KnownNat n) => Vec n a -> [a]+listOfVec (Vec ba#) = go 0#+  where+    go :: Int# -> [a]+    go i# | isTrue# (i# <# n#)  = indexByteArray# ba# i# : go (i# +# 1#)+          | otherwise           = []++    !(I# n#)  = fromIntegral (natVal' (proxy# :: Proxy# n))++instance Eq (Vec n a) where+  Vec ba1# == Vec ba2# = ByteArray ba1# == ByteArray ba2#++-- Type synonyms for common SIMD vector types+--+-- Note that non-power-of-two sized SIMD vectors are a bit dubious, and+-- special care must be taken in the code generator. For example, LLVM will+-- treat a Vec3 with alignment of _4_, meaning that reads and writes will+-- be (without further action) incorrect.+--+type Vec2 a  = Vec 2 a+type Vec3 a  = Vec 3 a+type Vec4 a  = Vec 4 a+type Vec8 a  = Vec 8 a+type Vec16 a = Vec 16 a++pattern Vec2 :: Prim a => a -> a -> Vec2 a+pattern Vec2 a b <- (unpackVec2 -> (a,b))+  where Vec2 = packVec2+{-# COMPLETE Vec2 #-}++pattern Vec3 :: Prim a => a -> a -> a -> Vec3 a+pattern Vec3 a b c <- (unpackVec3 -> (a,b,c))+  where Vec3 = packVec3+{-# COMPLETE Vec3 #-}++pattern Vec4 :: Prim a => a -> a -> a -> a -> Vec4 a+pattern Vec4 a b c d <- (unpackVec4 -> (a,b,c,d))+  where Vec4 = packVec4+{-# COMPLETE Vec4 #-}++pattern Vec8 :: Prim a => a -> a -> a -> a -> a -> a -> a -> a -> Vec8 a+pattern Vec8 a b c d e f g h <- (unpackVec8 -> (a,b,c,d,e,f,g,h))+  where Vec8 = packVec8+{-# COMPLETE Vec8 #-}++pattern Vec16 :: Prim a => a -> a -> a -> a -> a -> a -> a -> a -> a -> a -> a -> a -> a -> a -> a -> a -> Vec16 a+pattern Vec16 a b c d e f g h i j k l m n o p <- (unpackVec16 -> (a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p))+  where Vec16 = packVec16+{-# COMPLETE Vec16 #-}++unpackVec2 :: Prim a => Vec2 a -> (a,a)+unpackVec2 (Vec ba#) =+  ( indexByteArray# ba# 0#+  , indexByteArray# ba# 1#+  )++unpackVec3 :: Prim a => Vec3 a -> (a,a,a)+unpackVec3 (Vec ba#) =+  ( indexByteArray# ba# 0#+  , indexByteArray# ba# 1#+  , indexByteArray# ba# 2#+  )++unpackVec4 :: Prim a => Vec4 a -> (a,a,a,a)+unpackVec4 (Vec ba#) =+  ( indexByteArray# ba# 0#+  , indexByteArray# ba# 1#+  , indexByteArray# ba# 2#+  , indexByteArray# ba# 3#+  )++unpackVec8 :: Prim a => Vec8 a -> (a,a,a,a,a,a,a,a)+unpackVec8 (Vec ba#) =+  ( indexByteArray# ba# 0#+  , indexByteArray# ba# 1#+  , indexByteArray# ba# 2#+  , indexByteArray# ba# 3#+  , indexByteArray# ba# 4#+  , indexByteArray# ba# 5#+  , indexByteArray# ba# 6#+  , indexByteArray# ba# 7#+  )++unpackVec16 :: Prim a => Vec16 a -> (a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a)+unpackVec16 (Vec ba#) =+  ( indexByteArray# ba# 0#+  , indexByteArray# ba# 1#+  , indexByteArray# ba# 2#+  , indexByteArray# ba# 3#+  , indexByteArray# ba# 4#+  , indexByteArray# ba# 5#+  , indexByteArray# ba# 6#+  , indexByteArray# ba# 7#+  , indexByteArray# ba# 8#+  , indexByteArray# ba# 9#+  , indexByteArray# ba# 10#+  , indexByteArray# ba# 11#+  , indexByteArray# ba# 12#+  , indexByteArray# ba# 13#+  , indexByteArray# ba# 14#+  , indexByteArray# ba# 15#+  )++packVec2 :: Prim a => a -> a -> Vec2 a+packVec2 a b = runST $ do+  mba <- newByteArray (2 * sizeOf a)+  writeByteArray mba 0 a+  writeByteArray mba 1 b+  ByteArray ba# <- unsafeFreezeByteArray mba+  return $! Vec ba#++packVec3 :: Prim a => a -> a -> a -> Vec3 a+packVec3 a b c = runST $ do+  mba <- newByteArray (3 * sizeOf a)+  writeByteArray mba 0 a+  writeByteArray mba 1 b+  writeByteArray mba 2 c+  ByteArray ba# <- unsafeFreezeByteArray mba+  return $! Vec ba#++packVec4 :: Prim a => a -> a -> a -> a -> Vec4 a+packVec4 a b c d = runST $ do+  mba <- newByteArray (4 * sizeOf a)+  writeByteArray mba 0 a+  writeByteArray mba 1 b+  writeByteArray mba 2 c+  writeByteArray mba 3 d+  ByteArray ba# <- unsafeFreezeByteArray mba+  return $! Vec ba#++packVec8 :: Prim a => a -> a -> a -> a -> a -> a -> a -> a -> Vec8 a+packVec8 a b c d e f g h = runST $ do+  mba <- newByteArray (8 * sizeOf a)+  writeByteArray mba 0 a+  writeByteArray mba 1 b+  writeByteArray mba 2 c+  writeByteArray mba 3 d+  writeByteArray mba 4 e+  writeByteArray mba 5 f+  writeByteArray mba 6 g+  writeByteArray mba 7 h+  ByteArray ba# <- unsafeFreezeByteArray mba+  return $! Vec ba#++packVec16 :: Prim a => a -> a -> a -> a -> a -> a -> a -> a -> a -> a -> a -> a -> a -> a -> a -> a -> Vec16 a+packVec16 a b c d e f g h i j k l m n o p = runST $ do+  mba <- newByteArray (16 * sizeOf a)+  writeByteArray mba 0 a+  writeByteArray mba 1 b+  writeByteArray mba 2 c+  writeByteArray mba 3 d+  writeByteArray mba 4 e+  writeByteArray mba 5 f+  writeByteArray mba 6 g+  writeByteArray mba 7 h+  writeByteArray mba 8 i+  writeByteArray mba 9 j+  writeByteArray mba 10 k+  writeByteArray mba 11 l+  writeByteArray mba 12 m+  writeByteArray mba 13 n+  writeByteArray mba 14 o+  writeByteArray mba 15 p+  ByteArray ba# <- unsafeFreezeByteArray mba+  return $! Vec ba#++-- O(n) at runtime to copy from the Addr# to the ByteArray#. We should be able+-- to do this without copying, but I don't think the definition of ByteArray# is+-- exported (or it is deeply magical).+--+liftVec :: Vec n a -> Q (TExp (Vec n a))+liftVec (Vec ba#)+  = unsafeTExpCoerce+    [| runST $ \s ->+         case newByteArray# $(liftInt# n#) s                                             of { (# s1, mba# #) ->+         case copyAddrToByteArray# $(litE (StringPrimL bytes)) mba# 0# $(liftInt# n#) s1 of { s2             ->+         case unsafeFreezeByteArray# mba# s2                                             of { (# s3, ba'# #) ->+           (# s3, Vec ba'# #)+        }}}+     |]+  where+      bytes :: [Word8]+      bytes = go 0#+        where+          go i# | isTrue# (i# <# n#) = W8# (indexWord8Array# ba# i#) : go (i# +# 1#)+                | otherwise          = []++      n# = sizeofByteArray# ba#++      -- XXX: Typed TH does not support unlifted types+      --+      liftInt# :: Int# -> ExpQ+      liftInt# i# = litE (IntPrimL (toInteger (I# i#)))+
+ src/Language/Haskell/TH/Extra.hs view
@@ -0,0 +1,36 @@+{-# LANGUAGE TemplateHaskell #-}+-- |+-- Module      : Language.Haskell.TH.Extra+-- Copyright   : [2019..2020] The Accelerate Team+-- License     : BSD3+--+-- Maintainer  : Trevor L. McDonell <trevor.mcdonell@gmail.com>+-- Stability   : experimental+-- Portability : non-portable (GHC extensions)+--++module Language.Haskell.TH.Extra+  where++import Language.Haskell.TH                                          hiding ( tupP, tupE )+import qualified Language.Haskell.TH                                as TH+++tupT :: [TypeQ] -> TypeQ+tupT [t] = t+tupT tup =+  let n = length tup+   in foldl (\ts t -> [t| $ts $t |]) (tupleT n) tup++tupP :: [PatQ] -> PatQ+tupP [p] = p+tupP ps  = TH.tupP ps++tupE :: [ExpQ] -> ExpQ+tupE [t] = t+tupE ts  = TH.tupE ts++tyVarBndrName :: TyVarBndr -> Name+tyVarBndrName (PlainTV  n)   = n+tyVarBndrName (KindedTV n _) = n+
test/doctest/Main.hs view
@@ -1,9 +1,9 @@ -- | -- Module      : Main--- Copyright   : [2017] Trevor L. McDonell+-- Copyright   : [2017..2020] The Accelerate Team -- License     : BSD3 ----- Maintainer  : Trevor L. McDonell <tmcdonell@cse.unsw.edu.au>+-- Maintainer  : Trevor L. McDonell <trevor.mcdonell@gmail.com> -- Stability   : experimental -- Portability : non-portable (GHC extensions) --
test/nofib/Main.hs view
@@ -1,9 +1,9 @@ -- | -- Module      : nofib-interpreter--- Copyright   : [2017] Trevor L. McDonell+-- Copyright   : [2017..2020] The Accelerate Team -- License     : BSD3 ----- Maintainer  : Trevor L. McDonell <tmcdonell@cse.unsw.edu.au>+-- Maintainer  : Trevor L. McDonell <trevor.mcdonell@gmail.com> -- Stability   : experimental -- Portability : non-portable (GHC extensions) --