packages feed

feldspar-language 0.3.3 → 0.4.0.2

raw patch · 61 files changed

+6119/−5460 lines, 61 filesdep +arraydep +taggeddep +type-leveldep ~QuickCheckdep ~basesetup-changedPVP ok

version bump matches the API change (PVP)

Dependencies added: array, tagged, type-level

Dependency ranges changed: QuickCheck, base

API changes (from Hackage documentation)

- Feldspar.Core: (!) :: (RandomAccess a) => a -> Data Int -> Element a
- Feldspar.Core: arrayLen :: (Storable a) => Data Length -> [a] -> Data [a]
- Feldspar.Core: class (Typeable (Internal a)) => Computable a where { type family Internal a; }
- Feldspar.Core: class Program a
- Feldspar.Core: class RandomAccess a where { type family Element a; }
- Feldspar.Core: class Set a
- Feldspar.Core: class (Typeable a) => Storable a
- Feldspar.Core: function3 :: (Storable a, Storable b, Storable c, Storable d) => String -> (Size a -> Size b -> Size c -> Size d) -> (a -> b -> c -> d) -> (Data a -> Data b -> Data c -> Data d)
- Feldspar.Core: function4 :: (Storable a, Storable b, Storable c, Storable d, Storable e) => String -> (Size a -> Size b -> Size c -> Size d -> Size e) -> (a -> b -> c -> d -> e) -> (Data a -> Data b -> Data c -> Data d -> Data e)
- Feldspar.Core: getIx :: (Storable a) => Data [a] -> Data Int -> Data a
- Feldspar.Core: noInline :: (Computable a, Computable b) => String -> (a -> b) -> (a -> b)
- Feldspar.Core: printCore :: (Program a) => a -> IO ()
- Feldspar.Core: printCoreWithSize :: (Program a) => a -> IO ()
- Feldspar.Core: setIx :: (Storable a) => Data [a] -> Data Int -> Data a -> Data [a]
- Feldspar.Core: showCore :: (Program a) => a -> String
- Feldspar.Core: showCoreWithSize :: (Program a) => a -> String
- Feldspar.Core: size :: (Storable a) => Data [a] -> [Range Length]
- Feldspar.Core: trace :: (Storable a) => Int -> Data a -> Data a
- Feldspar.Core: type Signed16 = Int16
- Feldspar.Core: type Signed32 = Int32
- Feldspar.Core: type Signed8 = Int8
- Feldspar.Core: type Unsigned16 = Word16
- Feldspar.Core: type Unsigned32 = Word32
- Feldspar.Core: type Unsigned8 = Word8
- Feldspar.Core: universal :: (Set a) => a
- Feldspar.Core: while :: (Computable state) => (state -> Data Bool) -> (state -> state) -> (state -> state)
- Feldspar.Core.Expr: (!) :: (RandomAccess a) => a -> Data Int -> Element a
- Feldspar.Core.Expr: (|$|) :: Expr (a -> b) -> Data a -> Expr b
- Feldspar.Core.Expr: Application :: Expr (a -> b) -> Data a -> Expr b
- Feldspar.Core.Expr: Data :: Size a -> Ref (Expr a) -> Data a
- Feldspar.Core.Expr: Function :: String -> (a -> b) -> Expr (a -> b)
- Feldspar.Core.Expr: IfThenElse :: Data Bool -> (a :-> b) -> (a :-> b) -> Data a -> Expr b
- Feldspar.Core.Expr: Lambda :: (Data a -> Data b) -> (Data a) -> (Data b) -> :-> a b
- Feldspar.Core.Expr: NoInline :: String -> Ref (a :-> b) -> Data a -> Expr b
- Feldspar.Core.Expr: Parallel :: Data Length -> (Int :-> a) -> Expr [a]
- Feldspar.Core.Expr: Val :: a -> Expr a
- Feldspar.Core.Expr: Value :: a -> Expr a
- Feldspar.Core.Expr: Variable :: Expr a
- Feldspar.Core.Expr: While :: (a :-> Bool) -> (a :-> a) -> Data a -> Expr a
- Feldspar.Core.Expr: _function :: (Typeable b) => String -> (Size a -> Size b) -> (a -> b) -> (Data a -> Data b)
- Feldspar.Core.Expr: _function2 :: (Typeable c) => String -> (Size a -> Size b -> Size c) -> (a -> b -> c) -> (Data a -> Data b -> Data c)
- Feldspar.Core.Expr: _function3 :: (Typeable d) => String -> (Size a -> Size b -> Size c -> Size d) -> (a -> b -> c -> d) -> (Data a -> Data b -> Data c -> Data d)
- Feldspar.Core.Expr: _function4 :: (Typeable e) => String -> (Size a -> Size b -> Size c -> Size d -> Size e) -> (a -> b -> c -> d -> e) -> (Data a -> Data b -> Data c -> Data d -> Data e)
- Feldspar.Core.Expr: apply :: (a :-> b) -> Data a -> Data b
- Feldspar.Core.Expr: array :: (Storable a) => Size a -> a -> Data a
- Feldspar.Core.Expr: arrayLen :: (Storable a) => Data Length -> [a] -> Data [a]
- Feldspar.Core.Expr: cap :: (Storable a, (Size a) ~ (Range b), Ord b) => Range b -> Data a -> Data a
- Feldspar.Core.Expr: class (Typeable (Internal a)) => Computable a where { type family Internal a; }
- Feldspar.Core.Expr: class RandomAccess a where { type family Element a; }
- Feldspar.Core.Expr: data (:->) a b
- Feldspar.Core.Expr: data Data a
- Feldspar.Core.Expr: data Expr a
- Feldspar.Core.Expr: dataId :: Data a -> Unique
- Feldspar.Core.Expr: dataRef :: Data a -> Ref (Expr a)
- Feldspar.Core.Expr: dataSize :: Data a -> Size a
- Feldspar.Core.Expr: dataToExpr :: Data a -> Expr a
- Feldspar.Core.Expr: dataType :: Data a -> Tuple StorableType
- Feldspar.Core.Expr: eval :: (Computable a) => a -> Internal a
- Feldspar.Core.Expr: evalD :: Data a -> a
- Feldspar.Core.Expr: evalE :: Expr a -> a
- Feldspar.Core.Expr: evalF :: (a :-> b) -> (a -> b)
- Feldspar.Core.Expr: exprToData :: (Typeable a) => Size a -> Expr a -> Data a
- Feldspar.Core.Expr: externalize :: (Computable a) => Data (Internal a) -> a
- Feldspar.Core.Expr: false :: Data Bool
- Feldspar.Core.Expr: freshVar :: (Typeable a) => Size a -> Data a
- Feldspar.Core.Expr: function :: (Storable a, Storable b) => String -> (Size a -> Size b) -> (a -> b) -> (Data a -> Data b)
- Feldspar.Core.Expr: function2 :: (Storable a, Storable b, Storable c) => String -> (Size a -> Size b -> Size c) -> (a -> b -> c) -> (Data a -> Data b -> Data c)
- Feldspar.Core.Expr: function3 :: (Storable a, Storable b, Storable c, Storable d) => String -> (Size a -> Size b -> Size c -> Size d) -> (a -> b -> c -> d) -> (Data a -> Data b -> Data c -> Data d)
- Feldspar.Core.Expr: function4 :: (Storable a, Storable b, Storable c, Storable d, Storable e) => String -> (Size a -> Size b -> Size c -> Size d -> Size e) -> (a -> b -> c -> d -> e) -> (Data a -> Data b -> Data c -> Data d -> Data e)
- Feldspar.Core.Expr: get21 :: (Typeable a) => Data (a, b) -> Data a
- Feldspar.Core.Expr: get22 :: (Typeable b) => Data (a, b) -> Data b
- Feldspar.Core.Expr: get31 :: (Typeable a) => Data (a, b, c) -> Data a
- Feldspar.Core.Expr: get32 :: (Typeable b) => Data (a, b, c) -> Data b
- Feldspar.Core.Expr: get33 :: (Typeable c) => Data (a, b, c) -> Data c
- Feldspar.Core.Expr: get41 :: (Typeable a) => Data (a, b, c, d) -> Data a
- Feldspar.Core.Expr: get42 :: (Typeable b) => Data (a, b, c, d) -> Data b
- Feldspar.Core.Expr: get43 :: (Typeable c) => Data (a, b, c, d) -> Data c
- Feldspar.Core.Expr: get44 :: (Typeable d) => Data (a, b, c, d) -> Data d
- Feldspar.Core.Expr: getIx :: (Storable a) => Data [a] -> Data Int -> Data a
- Feldspar.Core.Expr: ifThenElse :: (Computable a, Computable b) => Data Bool -> (a -> b) -> (a -> b) -> (a -> b)
- Feldspar.Core.Expr: instance [overlap ok] (Computable a, Computable b) => Computable (a, b)
- Feldspar.Core.Expr: instance [overlap ok] (Computable a, Computable b, Computable c) => Computable (a, b, c)
- Feldspar.Core.Expr: instance [overlap ok] (Computable a, Computable b, Computable c, Computable d) => Computable (a, b, c, d)
- Feldspar.Core.Expr: instance [overlap ok] (Storable a) => Computable (Data a)
- Feldspar.Core.Expr: instance [overlap ok] (Storable a) => RandomAccess (Data [a])
- Feldspar.Core.Expr: instance [overlap ok] Eq (Data a)
- Feldspar.Core.Expr: instance [overlap ok] Ord (Data a)
- Feldspar.Core.Expr: internalize :: (Computable a) => a -> Data (Internal a)
- Feldspar.Core.Expr: lambda :: (Typeable a) => Size a -> (Data a -> Data b) -> (a :-> b)
- Feldspar.Core.Expr: liftFun :: (Computable a, Computable b) => (Data (Internal a) -> Data (Internal b)) -> (a -> b)
- Feldspar.Core.Expr: lowerFun :: (Computable a, Computable b) => (a -> b) -> (Data (Internal a) -> Data (Internal b))
- Feldspar.Core.Expr: noInline :: (Computable a, Computable b) => String -> (a -> b) -> (a -> b)
- Feldspar.Core.Expr: parallel :: (Storable a) => Data Length -> (Data Int -> Data a) -> Data [a]
- Feldspar.Core.Expr: resultSize :: (a :-> b) -> Size b
- Feldspar.Core.Expr: setIx :: (Storable a) => Data [a] -> Data Int -> Data a -> Data [a]
- Feldspar.Core.Expr: size :: (Storable a) => Data [a] -> [Range Length]
- Feldspar.Core.Expr: true :: Data Bool
- Feldspar.Core.Expr: tup2 :: (Typeable a, Typeable b) => Data a -> Data b -> Data (a, b)
- Feldspar.Core.Expr: tup3 :: (Typeable a, Typeable b, Typeable c) => Data a -> Data b -> Data c -> Data (a, b, c)
- Feldspar.Core.Expr: tup4 :: (Typeable a, Typeable b, Typeable c, Typeable d) => Data a -> Data b -> Data c -> Data d -> Data (a, b, c, d)
- Feldspar.Core.Expr: unit :: Data ()
- Feldspar.Core.Expr: value :: (Storable a) => a -> Data a
- Feldspar.Core.Expr: while :: (Computable state) => (state -> Data Bool) -> (state -> state) -> (state -> state)
- Feldspar.Core.Expr: whileSized :: (Computable state) => Size (Internal state) -> Size (Internal state) -> (state -> Data Bool) -> (state -> state) -> (state -> state)
- Feldspar.Core.Functions: (&&) :: Data Bool -> Data Bool -> Data Bool
- Feldspar.Core.Functions: (&&*) :: (Computable a) => (a -> Data Bool) -> (a -> Data Bool) -> (a -> Data Bool)
- Feldspar.Core.Functions: (?) :: (Computable a) => Data Bool -> (a, a) -> a
- Feldspar.Core.Functions: (||) :: Data Bool -> Data Bool -> Data Bool
- Feldspar.Core.Functions: (||*) :: (Computable a) => (a -> Data Bool) -> (a -> Data Bool) -> (a -> Data Bool)
- Feldspar.Core.Functions: absNum :: (Numeric a) => Data a -> Data a
- Feldspar.Core.Functions: absNum' :: (Numeric a, Num (Size a)) => Data a -> Data a
- Feldspar.Core.Functions: addNum :: (Numeric a) => Data a -> Data a -> Data a
- Feldspar.Core.Functions: allOnes :: (Eq a, Bits a) => a -> Bool
- Feldspar.Core.Functions: countBits :: (Bits b) => b -> Int
- Feldspar.Core.Functions: divFrac :: (Fractional' a) => Data a -> Data a -> Data a
- Feldspar.Core.Functions: for :: (Computable a) => Data Int -> Data Int -> a -> (Data Int -> a -> a) -> a
- Feldspar.Core.Functions: fromIntegerNum :: (Numeric a) => Integer -> Data a
- Feldspar.Core.Functions: fromRationalFrac :: (Fractional' a) => Rational -> Data a
- Feldspar.Core.Functions: instance [overlap ok] (Fractional' a, Numeric a) => Fractional (Data a)
- Feldspar.Core.Functions: instance [overlap ok] (Numeric a) => Num (Data a)
- Feldspar.Core.Functions: instance [overlap ok] Bits Int
- Feldspar.Core.Functions: instance [overlap ok] Bits Signed16
- Feldspar.Core.Functions: instance [overlap ok] Bits Signed32
- Feldspar.Core.Functions: instance [overlap ok] Bits Signed8
- Feldspar.Core.Functions: instance [overlap ok] Bits Unsigned16
- Feldspar.Core.Functions: instance [overlap ok] Bits Unsigned32
- Feldspar.Core.Functions: instance [overlap ok] Bits Unsigned8
- Feldspar.Core.Functions: instance [overlap ok] Eq ()
- Feldspar.Core.Functions: instance [overlap ok] Eq Bool
- Feldspar.Core.Functions: instance [overlap ok] Eq Float
- Feldspar.Core.Functions: instance [overlap ok] Eq Int
- Feldspar.Core.Functions: instance [overlap ok] Eq Signed16
- Feldspar.Core.Functions: instance [overlap ok] Eq Signed32
- Feldspar.Core.Functions: instance [overlap ok] Eq Signed8
- Feldspar.Core.Functions: instance [overlap ok] Eq Unsigned16
- Feldspar.Core.Functions: instance [overlap ok] Eq Unsigned32
- Feldspar.Core.Functions: instance [overlap ok] Eq Unsigned8
- Feldspar.Core.Functions: instance [overlap ok] Fractional' Float
- Feldspar.Core.Functions: instance [overlap ok] Integral Int
- Feldspar.Core.Functions: instance [overlap ok] Integral Signed16
- Feldspar.Core.Functions: instance [overlap ok] Integral Signed32
- Feldspar.Core.Functions: instance [overlap ok] Integral Signed8
- Feldspar.Core.Functions: instance [overlap ok] Integral Unsigned16
- Feldspar.Core.Functions: instance [overlap ok] Integral Unsigned32
- Feldspar.Core.Functions: instance [overlap ok] Integral Unsigned8
- Feldspar.Core.Functions: instance [overlap ok] Numeric Float
- Feldspar.Core.Functions: instance [overlap ok] Numeric Int
- Feldspar.Core.Functions: instance [overlap ok] Numeric Signed16
- Feldspar.Core.Functions: instance [overlap ok] Numeric Signed32
- Feldspar.Core.Functions: instance [overlap ok] Numeric Signed8
- Feldspar.Core.Functions: instance [overlap ok] Numeric Unsigned16
- Feldspar.Core.Functions: instance [overlap ok] Numeric Unsigned32
- Feldspar.Core.Functions: instance [overlap ok] Numeric Unsigned8
- Feldspar.Core.Functions: instance [overlap ok] Ord Float
- Feldspar.Core.Functions: instance [overlap ok] Ord Int
- Feldspar.Core.Functions: instance [overlap ok] Ord Signed16
- Feldspar.Core.Functions: instance [overlap ok] Ord Signed32
- Feldspar.Core.Functions: instance [overlap ok] Ord Signed8
- Feldspar.Core.Functions: instance [overlap ok] Ord Unsigned16
- Feldspar.Core.Functions: instance [overlap ok] Ord Unsigned32
- Feldspar.Core.Functions: instance [overlap ok] Ord Unsigned8
- Feldspar.Core.Functions: mulNum :: (Numeric a) => Data a -> Data a -> Data a
- Feldspar.Core.Functions: noSizeProp :: a -> ()
- Feldspar.Core.Functions: noSizeProp2 :: a -> b -> ()
- Feldspar.Core.Functions: not :: Data Bool -> Data Bool
- Feldspar.Core.Functions: optAbs :: (Numeric a, (Size a) ~ (Range b), Num b, Ord b) => Data a -> Data a
- Feldspar.Core.Functions: optAdd :: (Numeric a, Num (Size a)) => Data a -> Data a -> Data a
- Feldspar.Core.Functions: optAnd :: (Bits a, Storable a) => Data a -> Data a -> Data a
- Feldspar.Core.Functions: optEq :: (Storable a, (Size a) ~ (Range b), Ord b, Num b) => Data a -> Data a -> Data Bool
- Feldspar.Core.Functions: optExp :: (Integral a, Storable a) => Data a -> Data a -> Data a
- Feldspar.Core.Functions: optGT :: (Storable a, Ord a, (Size a) ~ (Range b), Ord b, Num b) => Data a -> Data a -> Data Bool
- Feldspar.Core.Functions: optGTE :: (Storable a, Ord a, (Size a) ~ (Range b), Ord b, Num b) => Data a -> Data a -> Data Bool
- Feldspar.Core.Functions: optLT :: (Storable a, Ord a, (Size a) ~ (Range b), Ord b, Num b) => Data a -> Data a -> Data Bool
- Feldspar.Core.Functions: optLTE :: (Storable a, Ord a, (Size a) ~ (Range b), Ord b, Num b) => Data a -> Data a -> Data Bool
- Feldspar.Core.Functions: optMax :: (Ord a, (Size a) ~ (Range b), Ord b, Num b) => Data a -> Data a -> Data a
- Feldspar.Core.Functions: optMin :: (Ord a, (Size a) ~ (Range b), Ord b, Num b) => Data a -> Data a -> Data a
- Feldspar.Core.Functions: optMod :: (Integral a, (Size a) ~ (Range b), Ord b, Num b, Enum b) => Data a -> Data a -> Data a
- Feldspar.Core.Functions: optMul :: (Numeric a, Num (Size a)) => Data a -> Data a -> Data a
- Feldspar.Core.Functions: optNeq :: (Storable a, (Size a) ~ (Range b), Ord b, Num b) => Data a -> Data a -> Data Bool
- Feldspar.Core.Functions: optOr :: (Bits a, Storable a) => Data a -> Data a -> Data a
- Feldspar.Core.Functions: optRem :: (Integral a, (Size a) ~ (Range b), Ord b, Num b, Enum b) => Data a -> Data a -> Data a
- Feldspar.Core.Functions: optSignedExp :: (Integral a, Bits a, Storable a, (Size a) ~ (Range b), Ord b, Num b) => Data a -> Data a -> Data a
- Feldspar.Core.Functions: optSignum :: (Numeric a, (Size a) ~ (Range b), Num b, Ord b) => Data a -> Data a
- Feldspar.Core.Functions: optSub :: (Numeric a, Num (Size a)) => Data a -> Data a -> Data a
- Feldspar.Core.Functions: optXor :: (Bits a, Bits a, Storable a) => Data a -> Data a -> Data a
- Feldspar.Core.Functions: optZero :: (a -> Data Int -> a) -> a -> Data Int -> a
- Feldspar.Core.Functions: revBits :: (Bits b) => b -> b
- Feldspar.Core.Functions: scanLeft :: (Bits b) => b -> Int
- Feldspar.Core.Functions: signumNum :: (Numeric a) => Data a -> Data a
- Feldspar.Core.Functions: signumNum' :: (Numeric a, Num (Size a)) => Data a -> Data a
- Feldspar.Core.Functions: subNum :: (Numeric a) => Data a -> Data a -> Data a
- Feldspar.Core.Functions: unfoldCore :: (Computable state, Storable a) => Data Length -> state -> (Data Int -> state -> (Data a, state)) -> (Data [a], state)
- Feldspar.Core.Graph: Array :: StorableData -> Function
- Feldspar.Core.Graph: Constant :: PrimitiveData -> Source
- Feldspar.Core.Graph: Function :: String -> Function
- Feldspar.Core.Graph: Graph :: [Node] -> Interface -> Graph
- Feldspar.Core.Graph: HierGraph :: Hierarchy -> Interface -> HierarchicalGraph
- Feldspar.Core.Graph: Hierarchy :: [(Node, [Hierarchy])] -> Hierarchy
- Feldspar.Core.Graph: IfThenElse :: Interface -> Interface -> Function
- Feldspar.Core.Graph: Input :: Function
- Feldspar.Core.Graph: Interface :: NodeId -> Tuple Source -> Tuple StorableType -> Tuple StorableType -> Interface
- Feldspar.Core.Graph: Local :: SubFunction -> NodeId -> Local
- Feldspar.Core.Graph: NoInline :: String -> Interface -> Function
- Feldspar.Core.Graph: Node :: NodeId -> Function -> Tuple Source -> Tuple StorableType -> Tuple StorableType -> Node
- Feldspar.Core.Graph: Parallel :: Interface -> Function
- Feldspar.Core.Graph: SubFunction :: SuperNode -> Int -> NodeId -> [NodeId] -> SubFunction
- Feldspar.Core.Graph: Variable :: Variable -> Source
- Feldspar.Core.Graph: While :: Interface -> Interface -> Function
- Feldspar.Core.Graph: class PrP a
- Feldspar.Core.Graph: data Function
- Feldspar.Core.Graph: data Graph
- Feldspar.Core.Graph: data HierarchicalGraph
- Feldspar.Core.Graph: data Hierarchy
- Feldspar.Core.Graph: data Interface
- Feldspar.Core.Graph: data Local
- Feldspar.Core.Graph: data Node
- Feldspar.Core.Graph: data Source
- Feldspar.Core.Graph: data SubFunction
- Feldspar.Core.Graph: fanout :: Graph -> Map NodeId [NodeId]
- Feldspar.Core.Graph: findLocalities :: Graph -> [Local]
- Feldspar.Core.Graph: function :: Node -> Function
- Feldspar.Core.Graph: graphHierarchy :: HierarchicalGraph -> Hierarchy
- Feldspar.Core.Graph: graphInterface :: Graph -> Interface
- Feldspar.Core.Graph: graphNodes :: Graph -> [Node]
- Feldspar.Core.Graph: hierGraphInterface :: HierarchicalGraph -> Interface
- Feldspar.Core.Graph: input :: Node -> Tuple Source
- Feldspar.Core.Graph: inputType :: Node -> Tuple StorableType
- Feldspar.Core.Graph: instance [overlap ok] Eq Function
- Feldspar.Core.Graph: instance [overlap ok] Eq Graph
- Feldspar.Core.Graph: instance [overlap ok] Eq Interface
- Feldspar.Core.Graph: instance [overlap ok] Eq Local
- Feldspar.Core.Graph: instance [overlap ok] Eq Node
- Feldspar.Core.Graph: instance [overlap ok] Eq Source
- Feldspar.Core.Graph: instance [overlap ok] Eq SubFunction
- Feldspar.Core.Graph: instance [overlap ok] Ord SubFunction
- Feldspar.Core.Graph: instance [overlap ok] PrP (Node, [Hierarchy])
- Feldspar.Core.Graph: instance [overlap ok] PrP Function
- Feldspar.Core.Graph: instance [overlap ok] PrP Graph
- Feldspar.Core.Graph: instance [overlap ok] PrP HierarchicalGraph
- Feldspar.Core.Graph: instance [overlap ok] PrP Hierarchy
- Feldspar.Core.Graph: instance [overlap ok] PrP Node
- Feldspar.Core.Graph: instance [overlap ok] PrP [(Node, [Hierarchy])]
- Feldspar.Core.Graph: instance [overlap ok] PrP [Hierarchy]
- Feldspar.Core.Graph: instance [overlap ok] PrP [Node]
- Feldspar.Core.Graph: instance [overlap ok] Show Function
- Feldspar.Core.Graph: instance [overlap ok] Show Graph
- Feldspar.Core.Graph: instance [overlap ok] Show HierarchicalGraph
- Feldspar.Core.Graph: instance [overlap ok] Show Interface
- Feldspar.Core.Graph: instance [overlap ok] Show Local
- Feldspar.Core.Graph: instance [overlap ok] Show Node
- Feldspar.Core.Graph: instance [overlap ok] Show Source
- Feldspar.Core.Graph: instance [overlap ok] Show SubFunction
- Feldspar.Core.Graph: interfaceInput :: Interface -> NodeId
- Feldspar.Core.Graph: interfaceInputType :: Interface -> Tuple StorableType
- Feldspar.Core.Graph: interfaceOutput :: Interface -> Tuple Source
- Feldspar.Core.Graph: interfaceOutputType :: Interface -> Tuple StorableType
- Feldspar.Core.Graph: listprint :: (a -> String) -> String -> [a] -> String
- Feldspar.Core.Graph: makeHierarchical :: Graph -> HierarchicalGraph
- Feldspar.Core.Graph: minimalSubFun :: Map SuperNode Int -> [SubFunction] -> SubFunction
- Feldspar.Core.Graph: nodeId :: Node -> NodeId
- Feldspar.Core.Graph: nodeMap :: Graph -> (NodeId -> Node)
- Feldspar.Core.Graph: orderSuperNodes :: Graph -> Map NodeId [SubFunction] -> Map SuperNode Int
- Feldspar.Core.Graph: outputType :: Node -> Tuple StorableType
- Feldspar.Core.Graph: prP :: (PrP a) => Int -> a -> String
- Feldspar.Core.Graph: sfBranch :: SubFunction -> Int
- Feldspar.Core.Graph: sfInput :: SubFunction -> NodeId
- Feldspar.Core.Graph: sfOutput :: SubFunction -> [NodeId]
- Feldspar.Core.Graph: sfSuper :: SubFunction -> SuperNode
- Feldspar.Core.Graph: sortNodes :: [Node] -> [Node]
- Feldspar.Core.Graph: sourceNodes :: Tuple Source -> [NodeId]
- Feldspar.Core.Graph: subFunctions :: Graph -> [SubFunction]
- Feldspar.Core.Graph: type NodeId = Int
- Feldspar.Core.Graph: type SuperNode = NodeId
- Feldspar.Core.Graph: type Variable = (NodeId, [Int])
- Feldspar.Core.Ref: data Ref a
- Feldspar.Core.Ref: deref :: Ref a -> a
- Feldspar.Core.Ref: instance [overlap ok] Eq (Ref a)
- Feldspar.Core.Ref: instance [overlap ok] Ord (Ref a)
- Feldspar.Core.Ref: ref :: a -> Ref a
- Feldspar.Core.Ref: refId :: Ref a -> Unique
- Feldspar.Core.Reify: buildSubFun :: (Typeable a, Typeable b) => (a :-> b) -> Reify Interface
- Feldspar.Core.Reify: class Program a
- Feldspar.Core.Reify: instance [overlap ok] (Computable a) => Program a
- Feldspar.Core.Reify: instance [overlap ok] (Computable a, Computable b) => Program (a -> b)
- Feldspar.Core.Reify: instance [overlap ok] (Computable a, Computable b) => Program (a, b)
- Feldspar.Core.Reify: instance [overlap ok] (Computable a, Computable b, Computable c) => Program (a -> b -> c)
- Feldspar.Core.Reify: instance [overlap ok] (Computable a, Computable b, Computable c) => Program (a, b, c)
- Feldspar.Core.Reify: instance [overlap ok] (Computable a, Computable b, Computable c, Computable d) => Program (a -> b -> c -> d)
- Feldspar.Core.Reify: instance [overlap ok] (Computable a, Computable b, Computable c, Computable d) => Program (a, b, c, d)
- Feldspar.Core.Reify: instance [overlap ok] (Computable a, Computable b, Computable c, Computable d, Computable e) => Program (a -> b -> c -> d -> e)
- Feldspar.Core.Reify: instance [overlap ok] (Storable a) => Show (Data a)
- Feldspar.Core.Reify: numArgs :: (Program a) => T a -> Int
- Feldspar.Core.Reify: printCore :: (Program a) => a -> IO ()
- Feldspar.Core.Reify: printCoreWithSize :: (Program a) => a -> IO ()
- Feldspar.Core.Reify: reify :: (Program a) => a -> Graph
- Feldspar.Core.Reify: runGraph :: Reify a -> Info -> (a, ([Node], Info))
- Feldspar.Core.Reify: showCore :: (Program a) => a -> String
- Feldspar.Core.Reify: showCoreWithSize :: (Program a) => a -> String
- Feldspar.Core.Reify: startInfo :: Info
- Feldspar.Core.Show: instance [overlap ok] HaskellValue Source
- Feldspar.Core.Show: instance [overlap ok] HaskellValue Variable
- Feldspar.Core.Show: showGraph :: Bool -> String -> Bool -> Graph -> String
- Feldspar.Core.Show: showNode :: Bool -> Node -> [Hierarchy] -> String
- Feldspar.Core.Show: showSF :: (HaskellValue inp, HaskellValue outp) => Bool -> Hierarchy -> String -> inp -> outp -> String
- Feldspar.Core.Show: showSubFun :: (HaskellValue inp, HaskellValue outp) => Bool -> Hierarchy -> String -> Maybe inp -> outp -> String
- Feldspar.Core.Show: sizeComment :: Tuple StorableType -> String
- Feldspar.Core.Show: tupPatt :: Tuple StorableType -> NodeId -> Tuple Variable
- Feldspar.Core.Show: viewBinOp :: String -> Maybe String
- Feldspar.Core.Trace: trace :: (Storable a) => Int -> Data a -> Data a
- Feldspar.Core.Types: One :: a -> Tuple a
- Feldspar.Core.Types: PrimitiveData :: PrimitiveData -> StorableData
- Feldspar.Core.Types: StorableData :: [StorableData] -> StorableData
- Feldspar.Core.Types: StorableType :: [Range Length] -> PrimitiveType -> StorableType
- Feldspar.Core.Types: T :: T a
- Feldspar.Core.Types: Tup :: [Tuple a] -> Tuple a
- Feldspar.Core.Types: UnitData :: () -> PrimitiveData
- Feldspar.Core.Types: UnitType :: PrimitiveType
- Feldspar.Core.Types: bitSize :: PrimitiveType -> Int
- Feldspar.Core.Types: class (Storable a) => Primitive a
- Feldspar.Core.Types: class Set a
- Feldspar.Core.Types: class (Typeable a) => Storable a
- Feldspar.Core.Types: class (Eq a, Monoid (Size a), Set (Size a)) => Typeable a where { type family Size a; }
- Feldspar.Core.Types: data PrimitiveData
- Feldspar.Core.Types: data PrimitiveType
- Feldspar.Core.Types: data StorableData
- Feldspar.Core.Types: data StorableType
- Feldspar.Core.Types: data T a
- Feldspar.Core.Types: data Tuple a
- Feldspar.Core.Types: instance [overlap ok] (Eq a) => Eq (Tuple a)
- Feldspar.Core.Types: instance [overlap ok] (Eq a, Eq b) => Eq (a :> b)
- Feldspar.Core.Types: instance [overlap ok] (HaskellType a) => HaskellType (Tuple a)
- Feldspar.Core.Types: instance [overlap ok] (HaskellValue a) => HaskellValue (Tuple a)
- Feldspar.Core.Types: instance [overlap ok] (Monoid a, Monoid b) => Monoid (a :> b)
- Feldspar.Core.Types: instance [overlap ok] (Ord a) => Set (Range a)
- Feldspar.Core.Types: instance [overlap ok] (Ord a, Ord b) => Ord (a :> b)
- Feldspar.Core.Types: instance [overlap ok] (Set a, Set b) => Set (a :> b)
- Feldspar.Core.Types: instance [overlap ok] (Set a, Set b) => Set (a, b)
- Feldspar.Core.Types: instance [overlap ok] (Set a, Set b, Set c) => Set (a, b, c)
- Feldspar.Core.Types: instance [overlap ok] (Set a, Set b, Set c, Set d) => Set (a, b, c, d)
- Feldspar.Core.Types: instance [overlap ok] (Show a) => Show (Tuple a)
- Feldspar.Core.Types: instance [overlap ok] (Show a, Show b) => Show (a :> b)
- Feldspar.Core.Types: instance [overlap ok] (Storable a) => Primitive a
- Feldspar.Core.Types: instance [overlap ok] (Storable a) => Storable [a]
- Feldspar.Core.Types: instance [overlap ok] (Storable a) => Typeable [a]
- Feldspar.Core.Types: instance [overlap ok] (Typeable a, Typeable b) => Typeable (a, b)
- Feldspar.Core.Types: instance [overlap ok] (Typeable a, Typeable b, Typeable c) => Typeable (a, b, c)
- Feldspar.Core.Types: instance [overlap ok] (Typeable a, Typeable b, Typeable c, Typeable d) => Typeable (a, b, c, d)
- Feldspar.Core.Types: instance [overlap ok] Eq PrimitiveData
- Feldspar.Core.Types: instance [overlap ok] Eq PrimitiveType
- Feldspar.Core.Types: instance [overlap ok] Eq StorableData
- Feldspar.Core.Types: instance [overlap ok] Eq StorableType
- Feldspar.Core.Types: instance [overlap ok] Foldable Tuple
- Feldspar.Core.Types: instance [overlap ok] Functor Tuple
- Feldspar.Core.Types: instance [overlap ok] HaskellType PrimitiveType
- Feldspar.Core.Types: instance [overlap ok] HaskellType StorableType
- Feldspar.Core.Types: instance [overlap ok] HaskellValue PrimitiveData
- Feldspar.Core.Types: instance [overlap ok] HaskellValue StorableData
- Feldspar.Core.Types: instance [overlap ok] Set ()
- Feldspar.Core.Types: instance [overlap ok] Show PrimitiveData
- Feldspar.Core.Types: instance [overlap ok] Show PrimitiveType
- Feldspar.Core.Types: instance [overlap ok] Show StorableData
- Feldspar.Core.Types: instance [overlap ok] Show StorableType
- Feldspar.Core.Types: instance [overlap ok] Storable ()
- Feldspar.Core.Types: instance [overlap ok] Storable Bool
- Feldspar.Core.Types: instance [overlap ok] Storable Float
- Feldspar.Core.Types: instance [overlap ok] Storable Int
- Feldspar.Core.Types: instance [overlap ok] Storable Signed16
- Feldspar.Core.Types: instance [overlap ok] Storable Signed32
- Feldspar.Core.Types: instance [overlap ok] Storable Signed8
- Feldspar.Core.Types: instance [overlap ok] Storable Unsigned16
- Feldspar.Core.Types: instance [overlap ok] Storable Unsigned32
- Feldspar.Core.Types: instance [overlap ok] Storable Unsigned8
- Feldspar.Core.Types: instance [overlap ok] Traversable Tuple
- Feldspar.Core.Types: instance [overlap ok] Typeable ()
- Feldspar.Core.Types: instance [overlap ok] Typeable Bool
- Feldspar.Core.Types: instance [overlap ok] Typeable Float
- Feldspar.Core.Types: instance [overlap ok] Typeable Int
- Feldspar.Core.Types: instance [overlap ok] Typeable Signed16
- Feldspar.Core.Types: instance [overlap ok] Typeable Signed32
- Feldspar.Core.Types: instance [overlap ok] Typeable Signed8
- Feldspar.Core.Types: instance [overlap ok] Typeable Unsigned16
- Feldspar.Core.Types: instance [overlap ok] Typeable Unsigned32
- Feldspar.Core.Types: instance [overlap ok] Typeable Unsigned8
- Feldspar.Core.Types: listSize :: (Storable a) => T a -> Size a -> [Range Length]
- Feldspar.Core.Types: mkT :: a -> T a
- Feldspar.Core.Types: showPrimitiveRange :: PrimitiveType -> String
- Feldspar.Core.Types: showStorableSize :: StorableType -> String
- Feldspar.Core.Types: showTuple :: Tuple String -> String
- Feldspar.Core.Types: signed :: PrimitiveType -> Bool
- Feldspar.Core.Types: storableData :: (Storable a) => a -> StorableData
- Feldspar.Core.Types: storableSize :: (Storable a) => a -> Size a
- Feldspar.Core.Types: storableType :: (Storable a) => Size a -> T a -> StorableType
- Feldspar.Core.Types: tuplePath :: Tuple a -> Tuple [Int]
- Feldspar.Core.Types: type Signed16 = Int16
- Feldspar.Core.Types: type Signed32 = Int32
- Feldspar.Core.Types: type Signed8 = Int8
- Feldspar.Core.Types: type Unsigned16 = Word16
- Feldspar.Core.Types: type Unsigned32 = Word32
- Feldspar.Core.Types: type Unsigned8 = Word8
- Feldspar.Core.Types: typeOf :: (Typeable a) => Size a -> T a -> Tuple StorableType
- Feldspar.Core.Types: typeOfStorable :: (Storable a) => Size a -> T a -> Tuple StorableType
- Feldspar.Core.Types: universal :: (Set a) => a
- Feldspar.Core.Types: valueSet :: PrimitiveType -> (Range Integer)
- Feldspar.FixedPoint: abs' :: (Integral b, Bits b) => (Int, Data b) -> (Int, Data b)
- Feldspar.FixedPoint: addFF :: (FixFloatLike a) => Int -> a -> a -> a
- Feldspar.FixedPoint: addFix :: (Integral b, Bits b) => Int -> (Int, Data b) -> (Int, Data b) -> (Int, Data b)
- Feldspar.FixedPoint: addFix' :: (Integral b, Bits b) => (Int, Data b) -> (Int, Data b) -> (Int, Data b)
- Feldspar.FixedPoint: addFix'' :: Int -> Fix -> Fix -> Fix
- Feldspar.FixedPoint: addFix16 :: Int -> Fix16 -> Fix16 -> Fix16
- Feldspar.FixedPoint: addFix32 :: Int -> Fix32 -> Fix32 -> Fix32
- Feldspar.FixedPoint: addFix8 :: Int -> Fix8 -> Fix8 -> Fix8
- Feldspar.FixedPoint: addUFix16 :: Int -> UFix16 -> UFix16 -> UFix16
- Feldspar.FixedPoint: addUFix32 :: Int -> UFix32 -> UFix32 -> UFix32
- Feldspar.FixedPoint: addUFix8 :: Int -> UFix8 -> UFix8 -> UFix8
- Feldspar.FixedPoint: class FixFloatLike a
- Feldspar.FixedPoint: class FromFloat t
- Feldspar.FixedPoint: divFF :: (FixFloatLike a) => Int -> a -> a -> a
- Feldspar.FixedPoint: divFix :: (Integral b, Bits b) => Int -> (Int, Data b) -> (Int, Data b) -> (Int, Data b)
- Feldspar.FixedPoint: divFix' :: Int -> Fix -> Fix -> Fix
- Feldspar.FixedPoint: divFix16 :: Int -> Fix16 -> Fix16 -> Fix16
- Feldspar.FixedPoint: divFix32 :: Int -> Fix32 -> Fix32 -> Fix32
- Feldspar.FixedPoint: divFix8 :: Int -> Fix8 -> Fix8 -> Fix8
- Feldspar.FixedPoint: divUFix16 :: Int -> UFix16 -> UFix16 -> UFix16
- Feldspar.FixedPoint: divUFix32 :: Int -> UFix32 -> UFix32 -> UFix32
- Feldspar.FixedPoint: divUFix8 :: Int -> UFix8 -> UFix8 -> UFix8
- Feldspar.FixedPoint: fix16ToFloat :: Fix16 -> Float
- Feldspar.FixedPoint: fix16ToInt :: Int -> Fix16 -> Data Signed16
- Feldspar.FixedPoint: fix32ToFloat :: Fix32 -> Float
- Feldspar.FixedPoint: fix32ToInt :: Int -> Fix32 -> Data Signed32
- Feldspar.FixedPoint: fix8ToFloat :: Fix8 -> Float
- Feldspar.FixedPoint: fix8ToInt :: Int -> Fix8 -> Data Signed8
- Feldspar.FixedPoint: fixToFloat :: (Integral a, Integral b) => (a, Data b) -> Float
- Feldspar.FixedPoint: fixToInt :: Int -> Fix -> Data Int
- Feldspar.FixedPoint: fl01toFix :: (Integral a, Integral b) => Bool -> Int -> Float -> (a, Data b) -> Bool -> (a, Data b)
- Feldspar.FixedPoint: fl01toFix' :: Float -> Fix -> Bool -> Fix
- Feldspar.FixedPoint: fl01toFix16 :: Float -> Fix16 -> Bool -> Fix16
- Feldspar.FixedPoint: fl01toFix32 :: Float -> Fix32 -> Bool -> Fix32
- Feldspar.FixedPoint: fl01toFix8 :: Float -> Fix8 -> Bool -> Fix8
- Feldspar.FixedPoint: fl01toUFix16 :: Float -> UFix16 -> Bool -> UFix16
- Feldspar.FixedPoint: fl01toUFix32 :: Float -> UFix32 -> Bool -> UFix32
- Feldspar.FixedPoint: fl01toUFix8 :: Float -> UFix8 -> Bool -> UFix8
- Feldspar.FixedPoint: float :: (FromFloat t) => Float -> t
- Feldspar.FixedPoint: floatToFix :: Float -> Fix
- Feldspar.FixedPoint: floatToFix16 :: Float -> Fix16
- Feldspar.FixedPoint: floatToFix16' :: Int -> Float -> Fix16
- Feldspar.FixedPoint: floatToFix32 :: Float -> Fix32
- Feldspar.FixedPoint: floatToFix32' :: Int -> Float -> Fix32
- Feldspar.FixedPoint: floatToFix8 :: Float -> Fix8
- Feldspar.FixedPoint: floatToFix8' :: Int -> Float -> Fix8
- Feldspar.FixedPoint: floatToUFix16 :: Float -> UFix16
- Feldspar.FixedPoint: floatToUFix16' :: Int -> Float -> UFix16
- Feldspar.FixedPoint: floatToUFix32 :: Float -> UFix32
- Feldspar.FixedPoint: floatToUFix32' :: Int -> Float -> UFix32
- Feldspar.FixedPoint: floatToUFix8 :: Float -> UFix8
- Feldspar.FixedPoint: floatToUFix8' :: Int -> Float -> UFix8
- Feldspar.FixedPoint: fromInteger' :: (Integral b, Bits b) => Integer -> (Int, Data b)
- Feldspar.FixedPoint: fromRational' :: (Integral b, Bits b, Num (Int, Data b)) => Bool -> Int -> (Float -> (Int, Data b)) -> (Integer -> (Int, Data b)) -> Rational -> (Int, Data b)
- Feldspar.FixedPoint: inBounds :: Bool -> Int -> Int -> Bool
- Feldspar.FixedPoint: instance [overlap ok] FixFloatLike (Data Float)
- Feldspar.FixedPoint: instance [overlap ok] FixFloatLike Fix
- Feldspar.FixedPoint: instance [overlap ok] FixFloatLike Fix16
- Feldspar.FixedPoint: instance [overlap ok] FixFloatLike Fix32
- Feldspar.FixedPoint: instance [overlap ok] FixFloatLike Fix8
- Feldspar.FixedPoint: instance [overlap ok] FixFloatLike UFix16
- Feldspar.FixedPoint: instance [overlap ok] FixFloatLike UFix32
- Feldspar.FixedPoint: instance [overlap ok] FixFloatLike UFix8
- Feldspar.FixedPoint: instance [overlap ok] Fractional Fix
- Feldspar.FixedPoint: instance [overlap ok] Fractional Fix16
- Feldspar.FixedPoint: instance [overlap ok] Fractional Fix32
- Feldspar.FixedPoint: instance [overlap ok] Fractional Fix8
- Feldspar.FixedPoint: instance [overlap ok] Fractional UFix16
- Feldspar.FixedPoint: instance [overlap ok] Fractional UFix32
- Feldspar.FixedPoint: instance [overlap ok] Fractional UFix8
- Feldspar.FixedPoint: instance [overlap ok] FromFloat (Data Float)
- Feldspar.FixedPoint: instance [overlap ok] FromFloat Fix
- Feldspar.FixedPoint: instance [overlap ok] FromFloat Fix16
- Feldspar.FixedPoint: instance [overlap ok] FromFloat Fix32
- Feldspar.FixedPoint: instance [overlap ok] FromFloat Fix8
- Feldspar.FixedPoint: instance [overlap ok] FromFloat UFix16
- Feldspar.FixedPoint: instance [overlap ok] FromFloat UFix32
- Feldspar.FixedPoint: instance [overlap ok] FromFloat UFix8
- Feldspar.FixedPoint: instance [overlap ok] Num Fix
- Feldspar.FixedPoint: instance [overlap ok] Num Fix16
- Feldspar.FixedPoint: instance [overlap ok] Num Fix32
- Feldspar.FixedPoint: instance [overlap ok] Num Fix8
- Feldspar.FixedPoint: instance [overlap ok] Num UFix16
- Feldspar.FixedPoint: instance [overlap ok] Num UFix32
- Feldspar.FixedPoint: instance [overlap ok] Num UFix8
- Feldspar.FixedPoint: intToFix :: Int -> Data Int -> Fix
- Feldspar.FixedPoint: intToFix16 :: Int -> Data Signed16 -> Fix16
- Feldspar.FixedPoint: intToFix32 :: Int -> Data Signed32 -> Fix32
- Feldspar.FixedPoint: intToFix8 :: Int -> Data Signed8 -> Fix8
- Feldspar.FixedPoint: intToUFix16 :: Int -> Data Unsigned16 -> UFix16
- Feldspar.FixedPoint: intToUFix32 :: Int -> Data Unsigned32 -> UFix32
- Feldspar.FixedPoint: intToUFix8 :: Int -> Data Unsigned8 -> UFix8
- Feldspar.FixedPoint: leftShift :: (Bits a) => Data a -> Int -> Data a
- Feldspar.FixedPoint: mulFix' :: (Integral b, Bits b) => (Int, Data b) -> (Int, Data b) -> (Int, Data b)
- Feldspar.FixedPoint: negate' :: (Integral b, Bits b) => (Int, Data b) -> (Int, Data b)
- Feldspar.FixedPoint: recip' :: (Integral b, Bits b) => Int -> (Int, Data b) -> (Int, Data b)
- Feldspar.FixedPoint: recipFF :: (FixFloatLike a) => Int -> a -> a
- Feldspar.FixedPoint: recipFix :: (Integral b, Bits b) => Int -> (Int, Data b) -> (Int, Data b)
- Feldspar.FixedPoint: recipFix' :: Int -> Fix -> Fix
- Feldspar.FixedPoint: recipFix16 :: Int -> Fix16 -> Fix16
- Feldspar.FixedPoint: recipFix32 :: Int -> Fix32 -> Fix32
- Feldspar.FixedPoint: recipFix8 :: Int -> Fix8 -> Fix8
- Feldspar.FixedPoint: recipUFix16 :: Int -> UFix16 -> UFix16
- Feldspar.FixedPoint: recipUFix32 :: Int -> UFix32 -> UFix32
- Feldspar.FixedPoint: recipUFix8 :: Int -> UFix8 -> UFix8
- Feldspar.FixedPoint: rightShift :: (Bits a) => Data a -> Int -> Data a
- Feldspar.FixedPoint: signum' :: (Integral b, Bits b) => (Int, Data b) -> (Int, Data b)
- Feldspar.FixedPoint: toExp16 :: Int -> Fix16 -> Fix16
- Feldspar.FixedPoint: toExp32 :: Int -> Fix32 -> Fix32
- Feldspar.FixedPoint: toExp8 :: Int -> Fix8 -> Fix8
- Feldspar.FixedPoint: toExpU16 :: Int -> UFix16 -> UFix16
- Feldspar.FixedPoint: toExpU32 :: Int -> UFix32 -> UFix32
- Feldspar.FixedPoint: toExpU8 :: Int -> UFix8 -> UFix8
- Feldspar.FixedPoint: type Fix = (Int, Data Int)
- Feldspar.FixedPoint: type Fix16 = (Int, Data Signed16)
- Feldspar.FixedPoint: type Fix32 = (Int, Data Signed32)
- Feldspar.FixedPoint: type Fix8 = (Int, Data Signed8)
- Feldspar.FixedPoint: type UFix16 = (Int, Data Unsigned16)
- Feldspar.FixedPoint: type UFix32 = (Int, Data Unsigned32)
- Feldspar.FixedPoint: type UFix8 = (Int, Data Unsigned8)
- Feldspar.FixedPoint: uFix16ToFloat :: UFix16 -> Float
- Feldspar.FixedPoint: uFix16ToInt :: Int -> UFix16 -> Data Unsigned16
- Feldspar.FixedPoint: uFix32ToFloat :: UFix32 -> Float
- Feldspar.FixedPoint: uFix32ToInt :: Int -> UFix32 -> Data Unsigned32
- Feldspar.FixedPoint: uFix8ToFloat :: UFix8 -> Float
- Feldspar.FixedPoint: uFix8ToInt :: Int -> UFix8 -> Data Unsigned8
- Feldspar.FixedPoint: zeroOneToFix :: Float -> Fix
- Feldspar.FixedPoint: zeroOneToFix16 :: Float -> Fix16
- Feldspar.FixedPoint: zeroOneToFix32 :: Float -> Fix32
- Feldspar.FixedPoint: zeroOneToFix8 :: Float -> Fix8
- Feldspar.FixedPoint: zeroOneToUFix16 :: Float -> UFix16
- Feldspar.FixedPoint: zeroOneToUFix32 :: Float -> UFix32
- Feldspar.FixedPoint: zeroOneToUFix8 :: Float -> UFix8
- Feldspar.Haskell: (-$-) :: (HaskellValue a) => String -> a -> String
- Feldspar.Haskell: (-=-) :: (HaskellValue patt, HaskellValue def) => patt -> def -> String
- Feldspar.Haskell: class HaskellType a
- Feldspar.Haskell: class HaskellValue a
- Feldspar.Haskell: haskellType :: (HaskellType a) => a -> String
- Feldspar.Haskell: haskellValue :: (HaskellValue a) => a -> String
- Feldspar.Haskell: ifThenElse :: (HaskellValue c, HaskellValue t, HaskellValue e) => c -> t -> e -> String
- Feldspar.Haskell: indent :: Int -> String -> String
- Feldspar.Haskell: instance [overlap ok] HaskellValue Int
- Feldspar.Haskell: instance [overlap ok] HaskellValue String
- Feldspar.Haskell: local :: String -> String -> String
- Feldspar.Haskell: newline :: String
- Feldspar.Haskell: opApp :: (HaskellValue a, HaskellValue b) => String -> a -> b -> String
- Feldspar.Haskell: unlinesNoTrail :: [String] -> String
- Feldspar.Matrix: (**) :: (Mul a b) => a -> b -> Prod a b
- Feldspar.Matrix: instance [overlap ok] (Numeric a) => Mul (DVector a) (DVector a)
- Feldspar.Matrix: instance [overlap ok] (Numeric a) => Mul (DVector a) (Data a)
- Feldspar.Matrix: instance [overlap ok] (Numeric a) => Mul (DVector a) (Matrix a)
- Feldspar.Matrix: instance [overlap ok] (Numeric a) => Mul (Data a) (DVector a)
- Feldspar.Matrix: instance [overlap ok] (Numeric a) => Mul (Data a) (Data a)
- Feldspar.Matrix: instance [overlap ok] (Numeric a) => Mul (Data a) (Matrix a)
- Feldspar.Matrix: instance [overlap ok] (Numeric a) => Mul (Matrix a) (DVector a)
- Feldspar.Matrix: instance [overlap ok] (Numeric a) => Mul (Matrix a) (Data a)
- Feldspar.Matrix: instance [overlap ok] (Numeric a) => Mul (Matrix a) (Matrix a)
- Feldspar.Matrix: instance [overlap ok] ElemWise (DVector a)
- Feldspar.Matrix: instance [overlap ok] ElemWise (Data a)
- Feldspar.Matrix: instance [overlap ok] ElemWise (Matrix a)
- Feldspar.Matrix: mul :: (Numeric a) => Matrix a -> Matrix a -> Matrix a
- Feldspar.Range: (/\) :: (Ord a) => Range a -> Range a -> Range a
- Feldspar.Range: (\/) :: (Ord a) => Range a -> Range a -> Range a
- Feldspar.Range: instance [overlap ok] (Arbitrary a, Ord a, Num a) => Arbitrary (Range a)
- Feldspar.Range: instance [overlap ok] (Ord a) => Eq (Range a)
- Feldspar.Range: instance [overlap ok] (Ord a, Num a) => Monoid (Range a)
- Feldspar.Range: instance [overlap ok] (Ord a, Num a) => Num (Range a)
- Feldspar.Range: instance [overlap ok] (Ord a, Show a) => Show (Range a)
- Feldspar.Range: instance [overlap ok] Random Word32
- Feldspar.Range: isBounded :: (Ord a) => Range a -> Bool
- Feldspar.Range: liftMaybe2 :: (a -> a -> a) -> Maybe a -> Maybe a -> Maybe a
- Feldspar.Range: lowBound :: (Bounded a, Ord a) => Range a -> a
- Feldspar.Range: prop_arith1 :: (forall a. (Num a) => a -> a) -> Range Int -> Property
- Feldspar.Range: prop_arith2 :: (forall a. (Num a) => a -> a -> a) -> Range Int -> Range Int -> Property
- Feldspar.Range: rangeProp1 :: (Ord a, Bounded a) => (a -> a -> Range a) -> Range a -> Range a
- Feldspar.Range: rangeProp2 :: (Ord a, Bounded a) => (a -> a -> a -> a -> Range a) -> Range a -> Range a -> Range a
- Feldspar.Range: rangePropSafety1 :: (Ord a, Show a, Random a, Bounded a, Ord b) => (a -> b) -> (Range a -> Range b) -> Range a -> Property
- Feldspar.Range: uppBound :: (Bounded a, Ord a) => Range a -> a
- Feldspar.Stream: dropWhile :: (t -> Data Bool) -> Stream t -> Stream t
- Feldspar.Stream: filter :: (a -> Data Bool) -> Stream a -> Stream a
- Feldspar.Stream: instance [overlap ok] RandomAccess (Data Int -> Data a)
- Feldspar.Stream: instance [overlap ok] RandomAccess (Stream a)
- Feldspar.Stream: partition :: (a -> Data Bool) -> Stream a -> (Stream a, Stream a)
- Feldspar.Stream: recurrence :: (Storable a) => DVector a -> ((Int -> Data a) -> Data a) -> Stream (Data a)
- Feldspar.Utils: (!!!) :: (Ord a) => Map a [b] -> a -> [b]
- Feldspar.Utils: allEqual :: (Eq a) => [a] -> Bool
- Feldspar.Utils: appendFirstLine :: String -> String -> String
- Feldspar.Utils: invertMap :: (Ord a, Ord b) => Map a b -> Map b [a]
- Feldspar.Utils: showSeq :: String -> [String] -> String -> String
- Feldspar.Utils: topSort :: (Ord a) => Map a [a] -> [a]
- Feldspar.Vector: boundVector :: Int -> Vector a -> Vector a
- Feldspar.Vector: dropWhile :: (a -> Data Bool) -> Vector a -> Vector a
- Feldspar.Vector: index :: Vector a -> Data Ix -> a
- Feldspar.Vector: instance [overlap ok] (Storable a) => Computable (Vector (Data a))
- Feldspar.Vector: instance [overlap ok] (Storable a) => Computable (Vector (Vector (Data a)))
- Feldspar.Vector: instance [overlap ok] RandomAccess (Vector a)
- Feldspar.Vector: modifyLength :: (Data Length -> Data Length) -> Vector a -> Vector a
- Feldspar.Vector: setLength :: Data Length -> Vector a -> Vector a
- Feldspar.Vector: type Ix = Int
+ Feldspar.Core: (:+) :: !a -> !a -> Complex a
+ Feldspar.Core: (?) :: Syntactic a => Data Bool -> (a, a) -> a
+ Feldspar.Core: DefaultInt :: Int32 -> DefaultInt
+ Feldspar.Core: DefaultWord :: Word32 -> DefaultWord
+ Feldspar.Core: EdgeSize :: Size a -> EdgeSize role a
+ Feldspar.Core: class (MultiEdge a Feldspar EdgeSize, Set (Info a), Type (Internal a), MetaType (Role a) (Internal a)) => Syntactic a
+ Feldspar.Core: class (Eq a, Show a, Typeable a, Eq (Size a), Show (Size a), Set (Size a)) => Type a where { type family Size a; }
+ Feldspar.Core: condition :: Syntactic a => Data Bool -> a -> a -> a
+ Feldspar.Core: data RealFloat a => Complex a :: * -> *
+ Feldspar.Core: data EdgeSize role a
+ Feldspar.Core: drawExpr :: Syntactic a => a -> IO ()
+ Feldspar.Core: drawExpr2 :: (Syntactic a, Syntactic b) => (a -> b) -> IO ()
+ Feldspar.Core: edgeSize :: EdgeSize role a -> Size a
+ Feldspar.Core: forLoop :: Syntactic st => Data Length -> st -> (Data Index -> st -> st) -> st
+ Feldspar.Core: force :: Syntactic a => a -> a
+ Feldspar.Core: fullProp :: FullProp a => a
+ Feldspar.Core: function1 :: (Type a, Type b) => String -> (Size a -> Size b) -> (a -> b) -> (Data a -> Data b)
+ Feldspar.Core: newtype DefaultInt
+ Feldspar.Core: newtype DefaultWord
+ Feldspar.Core: noinline :: (Syntactic a, Syntactic b) => String -> (a -> b) -> (a -> b)
+ Feldspar.Core: noinline2 :: (Syntactic a, Syntactic b, Syntactic c) => String -> (a -> b -> c) -> (a -> b -> c)
+ Feldspar.Core: parallel' :: Type a => Data Length -> (Data Index -> Data a) -> Data [a] -> Data [a]
+ Feldspar.Core: parallel'' :: Type a => Bool -> Data Length -> (Data Index -> Data a) -> Data [a] -> Data [a]
+ Feldspar.Core: resizeData :: Type a => Size a -> Data a -> Data a
+ Feldspar.Core: sequential :: (Type a, Syntactic st) => Data Length -> st -> (Data Index -> st -> (Data a, st)) -> (st -> Data [a]) -> Data [a]
+ Feldspar.Core: setLength :: Type a => Data Length -> Data [a] -> Data [a]
+ Feldspar.Core: type Index = DefaultWord
+ Feldspar.Core: viewLiteral :: Syntactic a => a -> Maybe (Internal a)
+ Feldspar.Core.Constructs: (?) :: Syntactic a => Data Bool -> (a, a) -> a
+ Feldspar.Core.Constructs: array :: Type a => Size a -> a -> Data a
+ Feldspar.Core.Constructs: cap :: Type a => Size a -> Data a -> Data a
+ Feldspar.Core.Constructs: condition :: Syntactic a => Data Bool -> a -> a -> a
+ Feldspar.Core.Constructs: false :: Data Bool
+ Feldspar.Core.Constructs: forLoop :: Syntactic st => Data Length -> st -> (Data Index -> st -> st) -> st
+ Feldspar.Core.Constructs: function :: (Syntactic a, Type b) => Bool -> String -> (Info a -> Size b) -> (Internal a -> b) -> (a -> Data b)
+ Feldspar.Core.Constructs: function1 :: (Type a, Type b) => String -> (Size a -> Size b) -> (a -> b) -> (Data a -> Data b)
+ Feldspar.Core.Constructs: function2 :: (Type a, Type b, Type c) => String -> (Size a -> Size b -> Size c) -> (a -> b -> c) -> (Data a -> Data b -> Data c)
+ Feldspar.Core.Constructs: ifThenElse :: Syntactic a => Data Bool -> a -> a -> a
+ Feldspar.Core.Constructs: noinline :: (Syntactic a, Syntactic b) => String -> (a -> b) -> (a -> b)
+ Feldspar.Core.Constructs: noinline2 :: (Syntactic a, Syntactic b, Syntactic c) => String -> (a -> b -> c) -> (a -> b -> c)
+ Feldspar.Core.Constructs: parallel :: Type a => Data Length -> (Data Index -> Data a) -> Data [a]
+ Feldspar.Core.Constructs: parallel' :: Type a => Data Length -> (Data Index -> Data a) -> Data [a] -> Data [a]
+ Feldspar.Core.Constructs: parallel'' :: Type a => Bool -> Data Length -> (Data Index -> Data a) -> Data [a] -> Data [a]
+ Feldspar.Core.Constructs: sequential :: (Type a, Syntactic st) => Data Length -> st -> (Data Index -> st -> (Data a, st)) -> (st -> Data [a]) -> Data [a]
+ Feldspar.Core.Constructs: setLength :: Type a => Data Length -> Data [a] -> Data [a]
+ Feldspar.Core.Constructs: true :: Data Bool
+ Feldspar.Core.Constructs: unit :: Data ()
+ Feldspar.Core.Constructs: value :: Type a => a -> Data a
+ Feldspar.Core.Constructs: value' :: Type a => Size a -> a -> Data a
+ Feldspar.Core.Constructs: viewGetIx :: Typeable a => Data Index -> Data a -> Maybe (Data [a])
+ Feldspar.Core.Functions: (!) :: RandomAccess a => a -> Data Index -> Element a
+ Feldspar.Core.Functions: arrayLen :: Type a => Data Length -> [a] -> Data [a]
+ Feldspar.Core.Functions: class RandomAccess a where { type family Element a; }
+ Feldspar.Core.Functions: getIx :: Type a => Data [a] -> Data Index -> Data a
+ Feldspar.Core.Functions: getLength :: Type a => Data [a] -> Data Length
+ Feldspar.Core.Functions: rotateLU :: Bits a => Data a -> Data Index -> Data a
+ Feldspar.Core.Functions: rotateRU :: Bits a => Data a -> Data Index -> Data a
+ Feldspar.Core.Functions: setIx :: Type a => Data [a] -> Data Index -> Data a -> Data [a]
+ Feldspar.Core.Functions: shiftLU :: Bits a => Data a -> Data Index -> Data a
+ Feldspar.Core.Functions: shiftRU :: Bits a => Data a -> Data Index -> Data a
+ Feldspar.Core.Functions.Array: (!) :: RandomAccess a => a -> Data Index -> Element a
+ Feldspar.Core.Functions.Array: arrayLen :: Type a => Data Length -> [a] -> Data [a]
+ Feldspar.Core.Functions.Array: class RandomAccess a where { type family Element a; }
+ Feldspar.Core.Functions.Array: getIx :: Type a => Data [a] -> Data Index -> Data a
+ Feldspar.Core.Functions.Array: getLength :: Type a => Data [a] -> Data Length
+ Feldspar.Core.Functions.Array: instance Type a => RandomAccess (Data [a])
+ Feldspar.Core.Functions.Array: setIx :: Type a => Data [a] -> Data Index -> Data a -> Data [a]
+ Feldspar.Core.Functions.Bits: (.&.) :: Bits a => Data a -> Data a -> Data a
+ Feldspar.Core.Functions.Bits: (.|.) :: Bits a => Data a -> Data a -> Data a
+ Feldspar.Core.Functions.Bits: (<<) :: Bits a => Data a -> Data Index -> Data a
+ Feldspar.Core.Functions.Bits: (>>) :: Bits a => Data a -> Data Index -> Data a
+ Feldspar.Core.Functions.Bits: (⊕) :: Bits a => Data a -> Data a -> Data a
+ Feldspar.Core.Functions.Bits: allOnes :: Bits a => a
+ Feldspar.Core.Functions.Bits: bit :: Bits a => Data Index -> Data a
+ Feldspar.Core.Functions.Bits: bitCount :: Bits a => Data a -> Data Index
+ Feldspar.Core.Functions.Bits: bitScan :: Bits a => Data a -> Data Index
+ Feldspar.Core.Functions.Bits: bitSize :: Bits a => Data a -> Data Index
+ Feldspar.Core.Functions.Bits: class (Bits a, Type a, FullProp (Size a)) => Bits a
+ Feldspar.Core.Functions.Bits: clearBit :: Bits a => Data a -> Data Index -> Data a
+ Feldspar.Core.Functions.Bits: complement :: Bits a => Data a -> Data a
+ Feldspar.Core.Functions.Bits: complementBit :: Bits a => Data a -> Data Index -> Data a
+ Feldspar.Core.Functions.Bits: evalBitCount :: Bits b => b -> Word
+ Feldspar.Core.Functions.Bits: evalBitScan :: Bits b => b -> Word
+ Feldspar.Core.Functions.Bits: evalReverseBits :: Bits b => b -> b
+ Feldspar.Core.Functions.Bits: instance Bits DefaultInt
+ Feldspar.Core.Functions.Bits: instance Bits DefaultWord
+ Feldspar.Core.Functions.Bits: instance Bits Int16
+ Feldspar.Core.Functions.Bits: instance Bits Int32
+ Feldspar.Core.Functions.Bits: instance Bits Int8
+ Feldspar.Core.Functions.Bits: instance Bits Word16
+ Feldspar.Core.Functions.Bits: instance Bits Word32
+ Feldspar.Core.Functions.Bits: instance Bits Word8
+ Feldspar.Core.Functions.Bits: isAllOnes :: Bits a => a -> Bool
+ Feldspar.Core.Functions.Bits: isSigned :: Bits a => Data a -> Data Bool
+ Feldspar.Core.Functions.Bits: liftInt :: (a -> Int -> b) -> (a -> DefaultInt -> b)
+ Feldspar.Core.Functions.Bits: liftIntWord :: (a -> Int -> b) -> (a -> DefaultWord -> b)
+ Feldspar.Core.Functions.Bits: optAnd :: Bits a => (Size a -> Size a -> Size a) -> Data a -> Data a -> Data a
+ Feldspar.Core.Functions.Bits: optOr :: Bits a => (Size a -> Size a -> Size a) -> Data a -> Data a -> Data a
+ Feldspar.Core.Functions.Bits: optXor :: Bits a => (Size a -> Size a -> Size a) -> Data a -> Data a -> Data a
+ Feldspar.Core.Functions.Bits: optZero :: (Type n, Num n) => (a -> Data n -> a) -> a -> Data n -> a
+ Feldspar.Core.Functions.Bits: reverseBits :: Bits a => Data a -> Data a
+ Feldspar.Core.Functions.Bits: rotateL :: Bits a => Data a -> Data DefaultInt -> Data a
+ Feldspar.Core.Functions.Bits: rotateLU :: Bits a => Data a -> Data Index -> Data a
+ Feldspar.Core.Functions.Bits: rotateR :: Bits a => Data a -> Data DefaultInt -> Data a
+ Feldspar.Core.Functions.Bits: rotateRU :: Bits a => Data a -> Data Index -> Data a
+ Feldspar.Core.Functions.Bits: setBit :: Bits a => Data a -> Data Index -> Data a
+ Feldspar.Core.Functions.Bits: shiftL :: Bits a => Data a -> Data DefaultInt -> Data a
+ Feldspar.Core.Functions.Bits: shiftLU :: Bits a => Data a -> Data Index -> Data a
+ Feldspar.Core.Functions.Bits: shiftR :: Bits a => Data a -> Data DefaultInt -> Data a
+ Feldspar.Core.Functions.Bits: shiftRU :: Bits a => Data a -> Data Index -> Data a
+ Feldspar.Core.Functions.Bits: testBit :: Bits a => Data a -> Data Index -> Data Bool
+ Feldspar.Core.Functions.Bits: xor :: Bits a => Data a -> Data a -> Data a
+ Feldspar.Core.Functions.Complex: (+.) :: (Numeric a, RealFloat a) => Data a -> Data a -> Data (Complex a)
+ Feldspar.Core.Functions.Complex: cis :: (Numeric a, RealFloat a) => Data a -> Data (Complex a)
+ Feldspar.Core.Functions.Complex: complex :: (Numeric a, RealFloat a) => Data a -> Data a -> Data (Complex a)
+ Feldspar.Core.Functions.Complex: conjugate :: (Numeric a, RealFloat a) => Data (Complex a) -> Data (Complex a)
+ Feldspar.Core.Functions.Complex: imagPart :: (Numeric a, RealFloat a) => Data (Complex a) -> Data a
+ Feldspar.Core.Functions.Complex: iunit :: (Numeric a, RealFloat a) => Data (Complex a)
+ Feldspar.Core.Functions.Complex: magnitude :: (Numeric a, RealFloat a) => Data (Complex a) -> Data a
+ Feldspar.Core.Functions.Complex: mkPolar :: (Numeric a, RealFloat a) => Data a -> Data a -> Data (Complex a)
+ Feldspar.Core.Functions.Complex: phase :: (Numeric a, RealFloat a) => Data (Complex a) -> Data a
+ Feldspar.Core.Functions.Complex: polar :: (Numeric a, RealFloat a) => Data (Complex a) -> (Data a, Data a)
+ Feldspar.Core.Functions.Complex: realPart :: (Numeric a, RealFloat a) => Data (Complex a) -> Data a
+ Feldspar.Core.Functions.Conversion: b2i :: Integral a => Data Bool -> Data a
+ Feldspar.Core.Functions.Conversion: ceiling :: Integral a => Data Float -> Data a
+ Feldspar.Core.Functions.Conversion: f2i :: Integral a => Data Float -> Data a
+ Feldspar.Core.Functions.Conversion: floor :: Integral a => Data Float -> Data a
+ Feldspar.Core.Functions.Conversion: i2f :: (Integral a, (Size a) ~ (Range a)) => Data a -> Data Float
+ Feldspar.Core.Functions.Conversion: i2n :: (Integral a, Numeric b, (Size a) ~ (Range a)) => Data a -> Data b
+ Feldspar.Core.Functions.Conversion: round :: Integral a => Data Float -> Data a
+ Feldspar.Core.Functions.Conversion: truncate :: Integral a => Data Float -> Data a
+ Feldspar.Core.Functions.Eq: (/=) :: Eq a => Data a -> Data a -> Data Bool
+ Feldspar.Core.Functions.Eq: (==) :: Eq a => Data a -> Data a -> Data Bool
+ Feldspar.Core.Functions.Eq: class Type a => Eq a
+ Feldspar.Core.Functions.Eq: defaultEq :: Eq a => Data a -> Data a -> Data Bool
+ Feldspar.Core.Functions.Eq: defaultNeq :: Eq a => Data a -> Data a -> Data Bool
+ Feldspar.Core.Functions.Eq: instance (Eq a, Eq b) => Eq (a, b)
+ Feldspar.Core.Functions.Eq: instance (Eq a, Eq b, Eq c) => Eq (a, b, c)
+ Feldspar.Core.Functions.Eq: instance (Eq a, Eq b, Eq c, Eq d) => Eq (a, b, c, d)
+ Feldspar.Core.Functions.Eq: instance (Eq a, RealFloat a) => Eq (Complex a)
+ Feldspar.Core.Functions.Eq: instance Eq ()
+ Feldspar.Core.Functions.Eq: instance Eq Bool
+ Feldspar.Core.Functions.Eq: instance Eq DefaultInt
+ Feldspar.Core.Functions.Eq: instance Eq DefaultWord
+ Feldspar.Core.Functions.Eq: instance Eq Float
+ Feldspar.Core.Functions.Eq: instance Eq Int16
+ Feldspar.Core.Functions.Eq: instance Eq Int32
+ Feldspar.Core.Functions.Eq: instance Eq Int8
+ Feldspar.Core.Functions.Eq: instance Eq Word16
+ Feldspar.Core.Functions.Eq: instance Eq Word32
+ Feldspar.Core.Functions.Eq: instance Eq Word8
+ Feldspar.Core.Functions.Eq: instance Eq a => Eq [a]
+ Feldspar.Core.Functions.Eq: optEq :: (Eq a, BoundedInt b, (Size a) ~ (Range b)) => Data a -> Data a -> Data Bool
+ Feldspar.Core.Functions.Eq: optNeq :: (Eq a, BoundedInt b, (Size a) ~ (Range b)) => Data a -> Data a -> Data Bool
+ Feldspar.Core.Functions.Floating: instance (Fractional' a, Floating a) => Floating (Data a)
+ Feldspar.Core.Functions.Fractional: class (Fractional a, Numeric a) => Fractional' a
+ Feldspar.Core.Functions.Fractional: divFrac :: Fractional' a => Data a -> Data a -> Data a
+ Feldspar.Core.Functions.Fractional: fromRationalFrac :: Fractional' a => Rational -> Data a
+ Feldspar.Core.Functions.Fractional: instance (Fractional' a, RealFloat a) => Fractional' (Complex a)
+ Feldspar.Core.Functions.Fractional: instance Fractional' Float
+ Feldspar.Core.Functions.Fractional: instance Fractional' a => Fractional (Data a)
+ Feldspar.Core.Functions.Integral: (^) :: Integral a => Data a -> Data a -> Data a
+ Feldspar.Core.Functions.Integral: class (Numeric a, BoundedInt a, Bits a, Ord a) => Integral a
+ Feldspar.Core.Functions.Integral: defaultDiv :: Integral a => Data a -> Data a -> Data a
+ Feldspar.Core.Functions.Integral: defaultMod :: Integral a => Data a -> Data a -> Data a
+ Feldspar.Core.Functions.Integral: defaultQuot :: Integral a => Data a -> Data a -> Data a
+ Feldspar.Core.Functions.Integral: div :: Integral a => Data a -> Data a -> Data a
+ Feldspar.Core.Functions.Integral: instance Integral DefaultInt
+ Feldspar.Core.Functions.Integral: instance Integral DefaultWord
+ Feldspar.Core.Functions.Integral: instance Integral Int16
+ Feldspar.Core.Functions.Integral: instance Integral Int32
+ Feldspar.Core.Functions.Integral: instance Integral Int8
+ Feldspar.Core.Functions.Integral: instance Integral Word16
+ Feldspar.Core.Functions.Integral: instance Integral Word32
+ Feldspar.Core.Functions.Integral: instance Integral Word8
+ Feldspar.Core.Functions.Integral: mod :: Integral a => Data a -> Data a -> Data a
+ Feldspar.Core.Functions.Integral: optExp :: Integral a => (Size a -> Size a -> Size a) -> Data a -> Data a -> Data a
+ Feldspar.Core.Functions.Integral: optMod :: (Integral a, BoundedInt b, (Size a) ~ (Range b)) => Data a -> Data a -> Data a
+ Feldspar.Core.Functions.Integral: optQuot :: (Integral a, BoundedInt a, (Size a) ~ (Range a)) => Data a -> Data a -> Data a
+ Feldspar.Core.Functions.Integral: optRem :: (Integral a, BoundedInt a, (Size a) ~ (Range a)) => Data a -> Data a -> Data a
+ Feldspar.Core.Functions.Integral: optSignedExp :: (Integral a, Signed a, BoundedInt b, (Size a) ~ (Range b)) => Data a -> Data a -> Data a
+ Feldspar.Core.Functions.Integral: quot :: Integral a => Data a -> Data a -> Data a
+ Feldspar.Core.Functions.Integral: rem :: Integral a => Data a -> Data a -> Data a
+ Feldspar.Core.Functions.Logic: (&&) :: Data Bool -> Data Bool -> Data Bool
+ Feldspar.Core.Functions.Logic: (&&*) :: Data Bool -> Data Bool -> Data Bool
+ Feldspar.Core.Functions.Logic: (||) :: Data Bool -> Data Bool -> Data Bool
+ Feldspar.Core.Functions.Logic: (||*) :: Data Bool -> Data Bool -> Data Bool
+ Feldspar.Core.Functions.Logic: not :: Data Bool -> Data Bool
+ Feldspar.Core.Functions.Num: absNum :: Numeric a => Data a -> Data a
+ Feldspar.Core.Functions.Num: addNum :: Numeric a => Data a -> Data a -> Data a
+ Feldspar.Core.Functions.Num: class (Type a, Num a, FullProp (Size a)) => Numeric a
+ Feldspar.Core.Functions.Num: defaultAbs :: Numeric a => (Size a -> Size a) -> Data a -> Data a
+ Feldspar.Core.Functions.Num: defaultAdd :: Numeric a => (Size a -> Size a -> Size a) -> Data a -> Data a -> Data a
+ Feldspar.Core.Functions.Num: defaultMul :: Numeric a => (Size a -> Size a -> Size a) -> Data a -> Data a -> Data a
+ Feldspar.Core.Functions.Num: defaultSignum :: Numeric a => (Size a -> Size a) -> Data a -> Data a
+ Feldspar.Core.Functions.Num: defaultSub :: Numeric a => (Size a -> Size a -> Size a) -> Data a -> Data a -> Data a
+ Feldspar.Core.Functions.Num: fromIntegerNum :: Numeric a => Integer -> Data a
+ Feldspar.Core.Functions.Num: instance (Type a, RealFloat a) => Numeric (Complex a)
+ Feldspar.Core.Functions.Num: instance Numeric DefaultInt
+ Feldspar.Core.Functions.Num: instance Numeric DefaultWord
+ Feldspar.Core.Functions.Num: instance Numeric Float
+ Feldspar.Core.Functions.Num: instance Numeric Int16
+ Feldspar.Core.Functions.Num: instance Numeric Int32
+ Feldspar.Core.Functions.Num: instance Numeric Int8
+ Feldspar.Core.Functions.Num: instance Numeric Word16
+ Feldspar.Core.Functions.Num: instance Numeric Word32
+ Feldspar.Core.Functions.Num: instance Numeric Word8
+ Feldspar.Core.Functions.Num: instance Numeric a => Num (Data a)
+ Feldspar.Core.Functions.Num: mulNum :: Numeric a => Data a -> Data a -> Data a
+ Feldspar.Core.Functions.Num: optAbs :: (Numeric a, BoundedInt b, (Size a) ~ (Range b)) => Data a -> Data a
+ Feldspar.Core.Functions.Num: optAdd :: (Numeric a, Num (Size a)) => Data a -> Data a -> Data a
+ Feldspar.Core.Functions.Num: optMul :: (Numeric a, Num (Size a)) => Data a -> Data a -> Data a
+ Feldspar.Core.Functions.Num: optSignum :: (Numeric a, BoundedInt b, (Size a) ~ (Range b)) => Data a -> Data a
+ Feldspar.Core.Functions.Num: optSub :: (Numeric a, Num (Size a)) => Data a -> Data a -> Data a
+ Feldspar.Core.Functions.Num: rangeProp :: (Bounded a, Integral a, (Size a) ~ (Range a)) => Range Integer -> Tagged a (Size a)
+ Feldspar.Core.Functions.Num: rangeToSize :: Numeric a => Range Integer -> Tagged a (Size a)
+ Feldspar.Core.Functions.Num: signumNum :: Numeric a => Data a -> Data a
+ Feldspar.Core.Functions.Num: subNum :: Numeric a => Data a -> Data a -> Data a
+ Feldspar.Core.Functions.Ord: (<) :: Ord a => Data a -> Data a -> Data Bool
+ Feldspar.Core.Functions.Ord: (<=) :: Ord a => Data a -> Data a -> Data Bool
+ Feldspar.Core.Functions.Ord: (>) :: Ord a => Data a -> Data a -> Data Bool
+ Feldspar.Core.Functions.Ord: (>=) :: Ord a => Data a -> Data a -> Data Bool
+ Feldspar.Core.Functions.Ord: class (Eq a, Ord a) => Ord a
+ Feldspar.Core.Functions.Ord: instance Ord ()
+ Feldspar.Core.Functions.Ord: instance Ord Bool
+ Feldspar.Core.Functions.Ord: instance Ord DefaultInt
+ Feldspar.Core.Functions.Ord: instance Ord DefaultWord
+ Feldspar.Core.Functions.Ord: instance Ord Float
+ Feldspar.Core.Functions.Ord: instance Ord Int16
+ Feldspar.Core.Functions.Ord: instance Ord Int32
+ Feldspar.Core.Functions.Ord: instance Ord Int8
+ Feldspar.Core.Functions.Ord: instance Ord Word16
+ Feldspar.Core.Functions.Ord: instance Ord Word32
+ Feldspar.Core.Functions.Ord: instance Ord Word8
+ Feldspar.Core.Functions.Ord: max :: Ord a => Data a -> Data a -> Data a
+ Feldspar.Core.Functions.Ord: min :: Ord a => Data a -> Data a -> Data a
+ Feldspar.Core.Functions.Ord: optGT :: (Ord a, BoundedInt b, (Size a) ~ (Range b)) => Data a -> Data a -> Data Bool
+ Feldspar.Core.Functions.Ord: optGTE :: (Ord a, BoundedInt b, (Size a) ~ (Range b)) => Data a -> Data a -> Data Bool
+ Feldspar.Core.Functions.Ord: optLT :: (Ord a, BoundedInt b, (Size a) ~ (Range b)) => Data a -> Data a -> Data Bool
+ Feldspar.Core.Functions.Ord: optLTE :: (Ord a, BoundedInt b, (Size a) ~ (Range b)) => Data a -> Data a -> Data Bool
+ Feldspar.Core.Functions.Ord: optMax :: (Ord a, BoundedInt b, (Size a) ~ (Range b)) => Data a -> Data a -> Data a
+ Feldspar.Core.Functions.Ord: optMin :: (Ord a, BoundedInt b, (Size a) ~ (Range b)) => Data a -> Data a -> Data a
+ Feldspar.Core.Functions.Trace: trace :: Numeric a => Int -> Data a -> Data a
+ Feldspar.Core.Functions.Tuple: getFst :: (Type a, Type b) => Data (a, b) -> Data a
+ Feldspar.Core.Functions.Tuple: getSnd :: (Type a, Type b) => Data (a, b) -> Data b
+ Feldspar.Core.Functions.Tuple: matchPair :: (Type a, Type b) => Data (a, b) -> (Data a, Data b)
+ Feldspar.Core.Functions.Tuple: pair :: (Type a, Type b) => Data a -> Data b -> Data (a, b)
+ Feldspar.Core.Representation: Condition :: Feldspar (In () -> In ra -> In ra -> Out ra) (Bool -> a -> a -> a)
+ Feldspar.Core.Representation: Data :: FeldNetwork (In ()) a -> Data a
+ Feldspar.Core.Representation: EdgeSize :: Size a -> EdgeSize role a
+ Feldspar.Core.Representation: ForLoop :: Feldspar (In () -> In rst -> (Out () -> Out rst -> In rst) -> Out rst) (Length -> st -> (Index -> st -> st) -> st)
+ Feldspar.Core.Representation: Function :: String -> (a -> b) -> Feldspar (In ra -> Out ()) (a -> b)
+ Feldspar.Core.Representation: Literal :: a -> Feldspar (Out ()) a
+ Feldspar.Core.Representation: NoInline :: String -> Feldspar ((Out ra -> In rb) -> (In ra -> Out rb)) ((a -> b) -> (a -> b))
+ Feldspar.Core.Representation: Pair :: Feldspar (In () -> In () -> Out ()) (a -> b -> (a, b))
+ Feldspar.Core.Representation: Parallel :: Feldspar (In () -> (Out () -> In ()) -> In () -> Out ()) (Length -> (Index -> a) -> [a] -> [a])
+ Feldspar.Core.Representation: Sequential :: Feldspar (In () -> In rst -> (Out () -> Out rst -> In ((), rst)) -> (Out rst -> In ()) -> Out ()) (Length -> st -> (Index -> st -> (a, st)) -> (st -> [a]) -> [a])
+ Feldspar.Core.Representation: SetIx :: Feldspar (In () -> In () -> In () -> Out ()) (Index -> a -> [a] -> [a])
+ Feldspar.Core.Representation: SetLength :: Feldspar (In () -> In () -> Out ()) (Length -> [a] -> [a])
+ Feldspar.Core.Representation: class (MultiEdge a Feldspar EdgeSize, Set (Info a), Type (Internal a), MetaType (Role a) (Internal a)) => Syntactic a
+ Feldspar.Core.Representation: data EdgeSize role a
+ Feldspar.Core.Representation: data Feldspar role a
+ Feldspar.Core.Representation: dataNode :: Data a -> FeldNetwork (Out ()) a
+ Feldspar.Core.Representation: dataSize :: Type a => Data a -> Size a
+ Feldspar.Core.Representation: drawExpr :: Syntactic a => a -> IO ()
+ Feldspar.Core.Representation: drawExpr2 :: (Syntactic a, Syntactic b) => (a -> b) -> IO ()
+ Feldspar.Core.Representation: edgeSize :: EdgeSize role a -> Size a
+ Feldspar.Core.Representation: edgeType :: EdgeSize () a -> TypeRep
+ Feldspar.Core.Representation: eqLiteral :: (Typeable a, Typeable b, Eq b) => a -> b -> Bool
+ Feldspar.Core.Representation: eval :: Syntactic a => a -> Internal a
+ Feldspar.Core.Representation: evalForLoop :: Length -> st -> (Index -> st -> st) -> st
+ Feldspar.Core.Representation: evalParallel :: Length -> (Index -> a) -> [a] -> [a]
+ Feldspar.Core.Representation: evalSequential :: Length -> st -> (Index -> st -> (a, st)) -> (st -> [a]) -> [a]
+ Feldspar.Core.Representation: evalSetIx :: Index -> a -> [a] -> [a]
+ Feldspar.Core.Representation: evalSetLength :: Length -> [a] -> [a]
+ Feldspar.Core.Representation: feldSharing :: (Typeable ra, Typeable a) => FeldNetwork ra a -> FeldNetwork ra a
+ Feldspar.Core.Representation: force :: Syntactic a => a -> a
+ Feldspar.Core.Representation: getInfo :: Syntactic a => a -> Info a
+ Feldspar.Core.Representation: instance (Syntactic a, Syntactic b) => Syntactic (a, b)
+ Feldspar.Core.Representation: instance (Syntactic a, Syntactic b, Syntactic c) => Syntactic (a, b, c)
+ Feldspar.Core.Representation: instance (Syntactic a, Syntactic b, Syntactic c, Syntactic d) => Syntactic (a, b, c, d)
+ Feldspar.Core.Representation: instance EdgeInfo (Data a)
+ Feldspar.Core.Representation: instance Eq (Data a)
+ Feldspar.Core.Representation: instance Eq (Size a) => Eq (EdgeSize role a)
+ Feldspar.Core.Representation: instance Eval Feldspar
+ Feldspar.Core.Representation: instance ExprEq Feldspar
+ Feldspar.Core.Representation: instance ExprShow EdgeSize
+ Feldspar.Core.Representation: instance ExprShow Feldspar
+ Feldspar.Core.Representation: instance Show (Data a)
+ Feldspar.Core.Representation: instance Type a => MultiEdge (Data a) Feldspar EdgeSize
+ Feldspar.Core.Representation: instance Type a => Set (EdgeSize role a)
+ Feldspar.Core.Representation: instance Type a => Syntactic (Data a)
+ Feldspar.Core.Representation: isArrayLit :: FeldNetwork ra a -> Bool
+ Feldspar.Core.Representation: isElem :: FeldNetwork ra a -> Bool
+ Feldspar.Core.Representation: isEmpty :: FeldNetwork ra a -> Bool
+ Feldspar.Core.Representation: isMulti :: FeldNetwork ra a -> Bool
+ Feldspar.Core.Representation: isSelector :: FeldNetwork ra a -> Bool
+ Feldspar.Core.Representation: lambda :: (Syntactic a, Syntactic b) => Info a -> (a -> b) -> FeldNetwork (Out (Role a) -> In (Role b)) (Internal a -> Internal b)
+ Feldspar.Core.Representation: metaTypes :: MetaType ra a => expr (Out ra) a -> [([Int], TypeRep)]
+ Feldspar.Core.Representation: newtype Data a
+ Feldspar.Core.Representation: nodeData :: Type a => Size a -> FeldNetwork (Out ()) a -> Data a
+ Feldspar.Core.Representation: resTypes :: FeldNetwork ra a -> [([Int], TypeRep)]
+ Feldspar.Core.Representation: resizeData :: Type a => Size a -> Data a -> Data a
+ Feldspar.Core.Representation: sameType :: (Typeable a, Typeable b) => a -> b -> Bool
+ Feldspar.Core.Representation: showExprTree :: Syntactic a => a -> String
+ Feldspar.Core.Representation: showExprTree2 :: (Syntactic a, Syntactic b) => (a -> b) -> String
+ Feldspar.Core.Representation: type FeldNetwork = Network EdgeSize Feldspar
+ Feldspar.Core.Representation: unData :: Data a -> FeldNetwork (In ()) a
+ Feldspar.Core.Representation: variable :: Syntactic a => Info a -> Ident -> a
+ Feldspar.Core.Representation: viewLiteral :: Syntactic a => a -> Maybe (Internal a)
+ Feldspar.Core.Types: ArrayData :: [DataRep] -> DataRep
+ Feldspar.Core.Types: ArrayType :: (Range Length) -> TypeRep -> TypeRep
+ Feldspar.Core.Types: ComplexData :: DataRep -> DataRep -> DataRep
+ Feldspar.Core.Types: ComplexType :: TypeRep -> TypeRep
+ Feldspar.Core.Types: DefaultInt :: Int32 -> DefaultInt
+ Feldspar.Core.Types: DefaultWord :: Word32 -> DefaultWord
+ Feldspar.Core.Types: StructData :: [DataRep] -> DataRep
+ Feldspar.Core.Types: StructType :: [TypeRep] -> TypeRep
+ Feldspar.Core.Types: class FullProp a
+ Feldspar.Core.Types: class MetaType role a
+ Feldspar.Core.Types: class Signed a
+ Feldspar.Core.Types: class (Eq a, Show a, Typeable a, Eq (Size a), Show (Size a), Set (Size a)) => Type a where { type family Size a; }
+ Feldspar.Core.Types: data DataRep
+ Feldspar.Core.Types: data TypeRep
+ Feldspar.Core.Types: dataRep :: Type a => a -> DataRep
+ Feldspar.Core.Types: fullProp :: FullProp a => a
+ Feldspar.Core.Types: instance (Eq a, Eq b) => Eq (a :> b)
+ Feldspar.Core.Types: instance (MetaType ra a, MetaType rb b) => MetaType (ra, rb) (a, b)
+ Feldspar.Core.Types: instance (MetaType ra a, MetaType rb b, MetaType rc c) => MetaType (ra, rb, rc) (a, b, c)
+ Feldspar.Core.Types: instance (MetaType ra a, MetaType rb b, MetaType rc c, MetaType rd d) => MetaType (ra, rb, rc, rd) (a, b, c, d)
+ Feldspar.Core.Types: instance (Ord a, Ord b) => Ord (a :> b)
+ Feldspar.Core.Types: instance (Set a, Set b) => Set (a :> b)
+ Feldspar.Core.Types: instance (Show a, Show b) => Show (a :> b)
+ Feldspar.Core.Types: instance (Type a, RealFloat a) => Type (Complex a)
+ Feldspar.Core.Types: instance (Type a, Type b) => Type (a, b)
+ Feldspar.Core.Types: instance (Type a, Type b, Type c) => Type (a, b, c)
+ Feldspar.Core.Types: instance (Type a, Type b, Type c, Type d) => Type (a, b, c, d)
+ Feldspar.Core.Types: instance Bits DefaultInt
+ Feldspar.Core.Types: instance Bits DefaultWord
+ Feldspar.Core.Types: instance Bounded DefaultInt
+ Feldspar.Core.Types: instance Bounded DefaultWord
+ Feldspar.Core.Types: instance BoundedInt a => FullProp (Range a)
+ Feldspar.Core.Types: instance Enum DefaultInt
+ Feldspar.Core.Types: instance Enum DefaultWord
+ Feldspar.Core.Types: instance Eq DataRep
+ Feldspar.Core.Types: instance Eq DefaultInt
+ Feldspar.Core.Types: instance Eq DefaultWord
+ Feldspar.Core.Types: instance FullProp ()
+ Feldspar.Core.Types: instance FullProp b => FullProp (a -> b)
+ Feldspar.Core.Types: instance Integral DefaultInt
+ Feldspar.Core.Types: instance Integral DefaultWord
+ Feldspar.Core.Types: instance Num DefaultInt
+ Feldspar.Core.Types: instance Num DefaultWord
+ Feldspar.Core.Types: instance Ord DefaultInt
+ Feldspar.Core.Types: instance Ord DefaultWord
+ Feldspar.Core.Types: instance Real DefaultInt
+ Feldspar.Core.Types: instance Real DefaultWord
+ Feldspar.Core.Types: instance Show DataRep
+ Feldspar.Core.Types: instance Show DefaultInt
+ Feldspar.Core.Types: instance Show DefaultWord
+ Feldspar.Core.Types: instance Signed DefaultInt
+ Feldspar.Core.Types: instance Signed Int16
+ Feldspar.Core.Types: instance Signed Int32
+ Feldspar.Core.Types: instance Signed Int8
+ Feldspar.Core.Types: instance Type ()
+ Feldspar.Core.Types: instance Type Bool
+ Feldspar.Core.Types: instance Type DefaultInt
+ Feldspar.Core.Types: instance Type DefaultWord
+ Feldspar.Core.Types: instance Type Float
+ Feldspar.Core.Types: instance Type Int16
+ Feldspar.Core.Types: instance Type Int32
+ Feldspar.Core.Types: instance Type Int8
+ Feldspar.Core.Types: instance Type Word16
+ Feldspar.Core.Types: instance Type Word32
+ Feldspar.Core.Types: instance Type Word8
+ Feldspar.Core.Types: instance Type a => MetaType () a
+ Feldspar.Core.Types: instance Type a => Type [a]
+ Feldspar.Core.Types: instance Typeable DefaultInt
+ Feldspar.Core.Types: instance Typeable DefaultWord
+ Feldspar.Core.Types: intRange :: TypeRep -> Range a
+ Feldspar.Core.Types: isNil :: Type a => a -> Bool
+ Feldspar.Core.Types: listTypes :: MetaType role a => [Int] -> Proxy role -> Proxy a -> [([Int], TypeRep)]
+ Feldspar.Core.Types: newtype DefaultInt
+ Feldspar.Core.Types: newtype DefaultWord
+ Feldspar.Core.Types: sizeOf :: Type a => a -> Size a
+ Feldspar.Core.Types: type Index = DefaultWord
+ Feldspar.Core.Types: typeRep :: Type a => Tagged a (Size a) -> TypeRep
+ Feldspar.Core.Types: typeRep' :: Type a => a -> TypeRep
+ Feldspar.Core.Wrap: Data' :: Data a -> Data' s a
+ Feldspar.Core.Wrap: class Wrap t w
+ Feldspar.Core.Wrap: data D0 :: *
+ Feldspar.Core.Wrap: data D1 :: *
+ Feldspar.Core.Wrap: data D2 :: *
+ Feldspar.Core.Wrap: data D3 :: *
+ Feldspar.Core.Wrap: data D4 :: *
+ Feldspar.Core.Wrap: data D5 :: *
+ Feldspar.Core.Wrap: data D6 :: *
+ Feldspar.Core.Wrap: data D7 :: *
+ Feldspar.Core.Wrap: data D8 :: *
+ Feldspar.Core.Wrap: data D9 :: *
+ Feldspar.Core.Wrap: data Data' s a
+ Feldspar.Core.Wrap: instance EdgeInfo (Data' s a)
+ Feldspar.Core.Wrap: instance Type a => MultiEdge (Data' s a) Feldspar EdgeSize
+ Feldspar.Core.Wrap: instance Type a => Syntactic (Data' s a)
+ Feldspar.Core.Wrap: instance Wrap (Data a) (Data a)
+ Feldspar.Core.Wrap: instance Wrap t u => Wrap (Data a -> t) (Data a -> u)
+ Feldspar.Core.Wrap: unData' :: Data' s a -> Data a
+ Feldspar.Core.Wrap: wrap :: Wrap t w => t -> w
+ Feldspar.DSL.Expression: class Eval expr
+ Feldspar.DSL.Expression: class ExprEq expr
+ Feldspar.DSL.Expression: class ExprShow expr
+ Feldspar.DSL.Expression: data Empty role a
+ Feldspar.DSL.Expression: eval :: Eval expr => expr role a -> a
+ Feldspar.DSL.Expression: exprCast :: (Typeable ra, Typeable a, Typeable rb, Typeable b) => expr ra a -> Maybe (expr rb b)
+ Feldspar.DSL.Expression: exprEq :: ExprEq expr => expr ra a -> expr rb b -> Bool
+ Feldspar.DSL.Expression: exprShow :: ExprShow expr => expr role a -> String
+ Feldspar.DSL.Expression: instance Eq (Empty role a)
+ Feldspar.DSL.Expression: instance Eval Empty
+ Feldspar.DSL.Expression: instance ExprEq Empty
+ Feldspar.DSL.Expression: instance ExprShow Empty
+ Feldspar.DSL.Expression: printExpr :: ExprShow expr => expr role a -> IO ()
+ Feldspar.DSL.Lambda: (:$:) :: Lam expr (ra -> rb) (a -> b) -> Lam expr ra a -> Lam expr rb b
+ Feldspar.DSL.Lambda: Inject :: expr role a -> Lam expr role a
+ Feldspar.DSL.Lambda: Lambda :: (Lam expr ra a -> Lam expr rb b) -> Lam expr (ra -> rb) (a -> b)
+ Feldspar.DSL.Lambda: Let :: String -> Lam expr (ra -> (ra -> rb) -> rb) (a -> (a -> b) -> b)
+ Feldspar.DSL.Lambda: Value :: a -> Lam expr role a
+ Feldspar.DSL.Lambda: Variable :: Ident -> Lam expr role a
+ Feldspar.DSL.Lambda: data Lam expr role a
+ Feldspar.DSL.Lambda: drawLambda :: ExprShow expr => Lam expr role a -> IO ()
+ Feldspar.DSL.Lambda: exprEqLam :: ExprEq expr => Lam expr ra a -> Lam expr rb b -> State Integer Bool
+ Feldspar.DSL.Lambda: exprShowApp :: ExprShow expr => [String] -> Lam expr role a -> State Integer String
+ Feldspar.DSL.Lambda: exprShowLam :: ExprShow expr => Lam expr role a -> State Integer String
+ Feldspar.DSL.Lambda: freshVar :: String -> State Integer (Lam expr role a)
+ Feldspar.DSL.Lambda: instance Eval expr => Eval (Lam expr)
+ Feldspar.DSL.Lambda: instance ExprEq expr => Eq (Lam expr role a)
+ Feldspar.DSL.Lambda: instance ExprEq expr => ExprEq (Lam expr)
+ Feldspar.DSL.Lambda: instance ExprShow (Lam expr) => Show (Lam expr role a)
+ Feldspar.DSL.Lambda: instance ExprShow expr => ExprShow (Lam expr)
+ Feldspar.DSL.Lambda: isLet :: Lam expr role a -> Bool
+ Feldspar.DSL.Lambda: isVar :: Lam expr role a -> Bool
+ Feldspar.DSL.Lambda: lamToTree :: ExprShow expr => Lam expr role a -> State Integer (Tree String)
+ Feldspar.DSL.Lambda: lamToTreeApp :: ExprShow expr => Forest String -> Lam expr role a -> State Integer (Tree String)
+ Feldspar.DSL.Lambda: let_ :: (Typeable ra, Typeable a, Typeable rb, Typeable b) => String -> Lam expr ra a -> (Lam expr ra a -> Lam expr rb b) -> Lam expr rb b
+ Feldspar.DSL.Lambda: shallowApply :: Lam expr (ra -> rb) (a -> b) -> Lam expr ra a -> Lam expr rb b
+ Feldspar.DSL.Lambda: showLamTree :: ExprShow expr => Lam expr role a -> String
+ Feldspar.DSL.Lambda: type Ident = String
+ Feldspar.DSL.Lambda: viewInfix :: String -> Maybe String
+ Feldspar.DSL.Network: Edge :: edge () a -> Connection edge node (Out () -> In ()) (a -> a)
+ Feldspar.DSL.Network: Group2 :: Connection e n (In ra -> In rb -> In (ra, rb)) (a -> b -> (a, b))
+ Feldspar.DSL.Network: Group3 :: Connection e n (In ra -> In rb -> In rc -> In (ra, rb, rc)) (a -> b -> c -> (a, b, c))
+ Feldspar.DSL.Network: Group4 :: Connection e n (In ra -> In rb -> In rc -> In rd -> In (ra, rb, rc, rd)) (a -> b -> c -> d -> (a, b, c, d))
+ Feldspar.DSL.Network: Match21 :: Connection e n (Out (ra, rb) -> Out ra) ((a, b) -> a)
+ Feldspar.DSL.Network: Match22 :: Connection e n (Out (ra, rb) -> Out rb) ((a, b) -> b)
+ Feldspar.DSL.Network: Match31 :: Connection e n (Out (ra, rb, rc) -> Out ra) ((a, b, c) -> a)
+ Feldspar.DSL.Network: Match32 :: Connection e n (Out (ra, rb, rc) -> Out rb) ((a, b, c) -> b)
+ Feldspar.DSL.Network: Match33 :: Connection e n (Out (ra, rb, rc) -> Out rc) ((a, b, c) -> c)
+ Feldspar.DSL.Network: Match41 :: Connection e n (Out (ra, rb, rc, rd) -> Out ra) ((a, b, c, d) -> a)
+ Feldspar.DSL.Network: Match42 :: Connection e n (Out (ra, rb, rc, rd) -> Out rb) ((a, b, c, d) -> b)
+ Feldspar.DSL.Network: Match43 :: Connection e n (Out (ra, rb, rc, rd) -> Out rc) ((a, b, c, d) -> c)
+ Feldspar.DSL.Network: Match44 :: Connection e n (Out (ra, rb, rc, rd) -> Out rd) ((a, b, c, d) -> d)
+ Feldspar.DSL.Network: Node :: node role a -> Connection edge node role a
+ Feldspar.DSL.Network: class EdgeInfo a where { type family Info a; }
+ Feldspar.DSL.Network: class (Typeable (Role a), Typeable (Internal a), EdgeInfo a) => MultiEdge a node edge | a -> node edge where { type family Role a; type family Internal a; }
+ Feldspar.DSL.Network: countEdges :: Network edge node (In role) a -> Int
+ Feldspar.DSL.Network: data Connection edge node role a
+ Feldspar.DSL.Network: data In role
+ Feldspar.DSL.Network: data Out role
+ Feldspar.DSL.Network: edgeCast :: (MultiEdge a node edge, MultiEdge b node edge, (Internal a) ~ (Internal b), (Role a) ~ (Role b)) => a -> b
+ Feldspar.DSL.Network: edgeInfo :: EdgeInfo a => a -> Info a
+ Feldspar.DSL.Network: fromInEdge :: MultiEdge a node edge => Network edge node (In (Role a)) (Internal a) -> a
+ Feldspar.DSL.Network: fromOutEdge :: MultiEdge a node edge => Info a -> Network edge node (Out (Role a)) (Internal a) -> a
+ Feldspar.DSL.Network: instance (EdgeInfo a, EdgeInfo b) => EdgeInfo (a, b)
+ Feldspar.DSL.Network: instance (EdgeInfo a, EdgeInfo b, EdgeInfo c) => EdgeInfo (a, b, c)
+ Feldspar.DSL.Network: instance (EdgeInfo a, EdgeInfo b, EdgeInfo c, EdgeInfo d) => EdgeInfo (a, b, c, d)
+ Feldspar.DSL.Network: instance (ExprEq edge, ExprEq node) => Eq (Connection edge node role a)
+ Feldspar.DSL.Network: instance (ExprShow edge, ExprShow node) => ExprShow (Connection edge node)
+ Feldspar.DSL.Network: instance (MultiEdge a node edge, MultiEdge b node edge) => MultiEdge (a, b) node edge
+ Feldspar.DSL.Network: instance (MultiEdge a node edge, MultiEdge b node edge, MultiEdge c node edge) => MultiEdge (a, b, c) node edge
+ Feldspar.DSL.Network: instance (MultiEdge a node edge, MultiEdge b node edge, MultiEdge c node edge, MultiEdge d node edge) => MultiEdge (a, b, c, d) node edge
+ Feldspar.DSL.Network: instance EdgeInfo (Network edge node (In ()) a)
+ Feldspar.DSL.Network: instance Eval node => Eval (Connection edge node)
+ Feldspar.DSL.Network: instance ExprEq node => ExprEq (Connection edge node)
+ Feldspar.DSL.Network: instance Typeable a => MultiEdge (Network edge node (In ()) a) node edge
+ Feldspar.DSL.Network: instance Typeable1 In
+ Feldspar.DSL.Network: instance Typeable1 Out
+ Feldspar.DSL.Network: isEdge :: Network edge node ra a -> Bool
+ Feldspar.DSL.Network: isMatch :: Connection edge node (ra -> rb) (a -> b) -> Bool
+ Feldspar.DSL.Network: isNode :: Network edge node ra a -> Bool
+ Feldspar.DSL.Network: listEdge :: (forall c. [Int] -> Network edge node (In ()) c -> b) -> Network edge node (In ra) a -> [b]
+ Feldspar.DSL.Network: mapEdge :: Applicative app => (forall b. [Int] -> Network edge node (In ()) b -> app b) -> Network edge node (In ra) a -> app a
+ Feldspar.DSL.Network: matchPath :: Network edge node (Out ()) a -> [Int]
+ Feldspar.DSL.Network: prop_edge1 :: (Eval node, MultiEdge a node edge, Eq (Internal a)) => Network edge node (In (Role a)) (Internal a) -> Bool
+ Feldspar.DSL.Network: prop_edge2 :: (Eval node, MultiEdge a node edge, Eq (Internal a)) => Info a -> Network edge node (Out (Role a)) (Internal a) -> Bool
+ Feldspar.DSL.Network: toEdge :: MultiEdge a node edge => a -> Network edge node (In (Role a)) (Internal a)
+ Feldspar.DSL.Network: traceVar :: Network edge node (Out ()) a -> Maybe Ident
+ Feldspar.DSL.Network: type Network edge node = Lam (Connection edge node)
+ Feldspar.DSL.Network: undoEdge :: Network edge node (In ()) a -> Network edge node (Out ()) a
+ Feldspar.DSL.Sharing: Env :: Bool -> Bool -> (SomeLam expr -> Integer) -> Env expr
+ Feldspar.DSL.Sharing: Params :: (SomeLam expr -> Bool) -> (SomeLam expr -> Bool) -> (SomeLam expr -> Bool) -> Params expr
+ Feldspar.DSL.Sharing: SomeLam :: (Lam expr ra a) -> SomeLam expr
+ Feldspar.DSL.Sharing: choose :: (Typeable ra, Typeable a) => Params expr -> Env expr -> Lam expr ra a -> Maybe (SomeLam expr)
+ Feldspar.DSL.Sharing: compound :: Lam expr ra a -> Bool
+ Feldspar.DSL.Sharing: count :: (ExprEq expr, Typeable ra, Typeable a, Typeable rb, Typeable b) => Lam expr ra a -> Lam expr rb b -> Integer
+ Feldspar.DSL.Sharing: countM :: (ExprEq expr, Typeable ra, Typeable a, Typeable rb, Typeable b) => Lam expr ra a -> Lam expr rb b -> State Integer Integer
+ Feldspar.DSL.Sharing: countNonEq :: (ExprEq expr, Typeable ra, Typeable a, Typeable rb, Typeable b) => Lam expr ra a -> Lam expr rb b -> State Integer Integer
+ Feldspar.DSL.Sharing: counter :: Env expr -> SomeLam expr -> Integer
+ Feldspar.DSL.Sharing: data Env expr
+ Feldspar.DSL.Sharing: data Params expr
+ Feldspar.DSL.Sharing: data SomeLam expr
+ Feldspar.DSL.Sharing: descend :: (ExprEq expr, Typeable ra, Typeable a) => Params expr -> Lam expr ra a -> Lam expr ra a
+ Feldspar.DSL.Sharing: inLambda :: Env expr -> Bool
+ Feldspar.DSL.Sharing: independent :: Lam expr ra a -> Bool
+ Feldspar.DSL.Sharing: initEnv :: (ExprEq expr, Typeable ra, Typeable a) => Lam expr ra a -> Env expr
+ Feldspar.DSL.Sharing: isFunction :: Typeable a => Lam expr ra a -> Bool
+ Feldspar.DSL.Sharing: liftable :: (Typeable ra, Typeable a) => Params expr -> Env expr -> Lam expr ra a -> Bool
+ Feldspar.DSL.Sharing: necessary :: Params expr -> SomeLam expr -> Bool
+ Feldspar.DSL.Sharing: sharing :: (ExprEq expr, Typeable ra, Typeable a) => Params expr -> Lam expr ra a -> Lam expr ra a
+ Feldspar.DSL.Sharing: sharingPoint :: Params expr -> SomeLam expr -> Bool
+ Feldspar.DSL.Sharing: simpleParams :: Params expr
+ Feldspar.DSL.Sharing: simpleSharing :: (ExprEq expr, Typeable ra, Typeable a) => Lam expr ra a -> Lam expr ra a
+ Feldspar.DSL.Sharing: subExpr :: Env expr -> Bool
+ Feldspar.DSL.Sharing: substitute :: (ExprEq expr, Typeable ra, Typeable a, Typeable rb, Typeable b) => Lam expr ra a -> Lam expr ra a -> Lam expr rb b -> Lam expr rb b
+ Feldspar.DSL.Sharing: sufficient :: Params expr -> SomeLam expr -> Bool
+ Feldspar.DSL.Val: Val :: String -> a -> Val role a
+ Feldspar.DSL.Val: data Val role a
+ Feldspar.DSL.Val: expr1 :: Lam Val (() -> ()) (Int -> Int)
+ Feldspar.DSL.Val: expr2 :: Lam Val (() -> ()) (Int -> Int)
+ Feldspar.DSL.Val: function :: (Typeable ra, Typeable a) => String -> (a -> b) -> (Lam Val ra a -> Lam Val rb b)
+ Feldspar.DSL.Val: function2 :: (Typeable ra, Typeable a, Typeable rb, Typeable b) => String -> (a -> b -> c) -> (Lam Val ra a -> Lam Val rb b -> Lam Val rc c)
+ Feldspar.DSL.Val: instance (Num a, Typeable a) => Num (Lam Val () a)
+ Feldspar.DSL.Val: instance Eval Val
+ Feldspar.DSL.Val: instance ExprEq Val
+ Feldspar.DSL.Val: instance ExprShow Val
+ Feldspar.DSL.Val: int :: Int -> Lam Val () Int
+ Feldspar.DSL.Val: simpleVal :: Show a => a -> Lam Val () a
+ Feldspar.FixedPoint: (?!) :: (Syntactic a, Splittable a) => Data Bool -> (a, a) -> a
+ Feldspar.FixedPoint: Fix :: Data DefaultInt -> Data a -> Fix a
+ Feldspar.FixedPoint: class Splittable t => Fixable t
+ Feldspar.FixedPoint: data Fix a
+ Feldspar.FixedPoint: exponent :: Fix a -> Data DefaultInt
+ Feldspar.FixedPoint: fix :: Fixable t => Data DefaultInt -> t -> t
+ Feldspar.FixedPoint: fixFold :: Splittable a => (a -> b -> a) -> a -> Vector b -> a
+ Feldspar.FixedPoint: freezeFix :: Type a => Fix a -> Data (DefaultInt, a)
+ Feldspar.FixedPoint: freezeFix' :: Bits a => DefaultInt -> Fix a -> Data a
+ Feldspar.FixedPoint: getExp :: Fixable t => t -> Data DefaultInt
+ Feldspar.FixedPoint: instance (Range a ~ Size a, Bounded a, Numeric a, Bits a, Ord a, Real a) => Num (Fix a)
+ Feldspar.FixedPoint: instance (Range a ~ Size a, Bounded a, Numeric a, Bits a, Ord a, Real a, Integral a) => Fractional (Fix a)
+ Feldspar.FixedPoint: instance (Type a, Bits a) => Splittable (Fix a)
+ Feldspar.FixedPoint: instance Bits a => Fixable (Fix a)
+ Feldspar.FixedPoint: instance Eq (Fix a)
+ Feldspar.FixedPoint: instance Fixable (Data Float)
+ Feldspar.FixedPoint: instance Show (Fix a)
+ Feldspar.FixedPoint: instance Type a => EdgeInfo (Fix a)
+ Feldspar.FixedPoint: instance Type a => MultiEdge (Fix a) Feldspar EdgeSize
+ Feldspar.FixedPoint: instance Type a => Splittable (Data a)
+ Feldspar.FixedPoint: instance Type a => Syntactic (Fix a)
+ Feldspar.FixedPoint: mantissa :: Fix a -> Data a
+ Feldspar.FixedPoint: unfreezeFix :: Type a => Data (DefaultInt, a) -> Fix a
+ Feldspar.FixedPoint: unfreezeFix' :: DefaultInt -> Data a -> Fix a
+ Feldspar.Matrix: (***) :: Mul a b => a -> b -> Prod a b
+ Feldspar.Matrix: instance (ElemWise a, Syntactic (Vector a)) => ElemWise (Vector a)
+ Feldspar.Matrix: instance (Wrap t u, Type a, Nat row, Nat col) => Wrap (Matrix a -> t) (Data' (row, col) [[a]] -> u)
+ Feldspar.Matrix: instance Numeric a => Mul (DVector a) (DVector a)
+ Feldspar.Matrix: instance Numeric a => Mul (DVector a) (Data a)
+ Feldspar.Matrix: instance Numeric a => Mul (DVector a) (Matrix a)
+ Feldspar.Matrix: instance Numeric a => Mul (Data a) (DVector a)
+ Feldspar.Matrix: instance Numeric a => Mul (Data a) (Data a)
+ Feldspar.Matrix: instance Numeric a => Mul (Data a) (Matrix a)
+ Feldspar.Matrix: instance Numeric a => Mul (Matrix a) (DVector a)
+ Feldspar.Matrix: instance Numeric a => Mul (Matrix a) (Data a)
+ Feldspar.Matrix: instance Numeric a => Mul (Matrix a) (Matrix a)
+ Feldspar.Matrix: instance Type a => ElemWise (Data a)
+ Feldspar.Matrix: instance Type a => Wrap (Matrix a) (Data [[a]])
+ Feldspar.Matrix: unfreezeMatrix' :: Type a => Length -> Length -> Data [[a]] -> Matrix a
+ Feldspar.Range: TC :: String -> t -> TestCase
+ Feldspar.Range: atAllTypes :: Monad m => (forall t. (BoundedInt t, Random t, Arbitrary t, Typeable t) => t -> m a) -> m ()
+ Feldspar.Range: bits :: Bits b => b -> Int
+ Feldspar.Range: class (Eq a, Ord a, Show a, Num a, Bounded a, Integral a, Bits a) => BoundedInt a
+ Feldspar.Range: correctShiftRU :: Bits a => a -> Word32 -> a
+ Feldspar.Range: data TestCase
+ Feldspar.Range: handleSign :: BoundedInt a => (Range a -> b) -> (Range a -> b) -> (Range a -> b)
+ Feldspar.Range: instance (BoundedInt a, Arbitrary a) => Arbitrary (Range a)
+ Feldspar.Range: instance (Eq a, Ord a, Show a, Num a, Bounded a, Integral a, Bits a) => BoundedInt a
+ Feldspar.Range: instance BoundedInt a => Num (Range a)
+ Feldspar.Range: instance BoundedInt a => Set (Range a)
+ Feldspar.Range: instance Eq a => Eq (Range a)
+ Feldspar.Range: instance Random Int8
+ Feldspar.Range: instance Random Word32
+ Feldspar.Range: instance Random Word8
+ Feldspar.Range: instance Show a => Show (Range a)
+ Feldspar.Range: mapMonotonic2 :: (a -> b -> c) -> Range a -> Range b -> Range c
+ Feldspar.Range: maxPlus :: BoundedInt a => a -> a -> a
+ Feldspar.Range: prop_propagation1 :: (BoundedInt t, Random t) => t -> (forall a. Num a => a -> a) -> Range t -> Property
+ Feldspar.Range: prop_propagation2 :: (BoundedInt t, Random t) => t -> (forall a. Num a => a -> a -> a) -> Range t -> Range t -> Property
+ Feldspar.Range: rangeAbs :: BoundedInt a => Range a -> Range a
+ Feldspar.Range: rangeAdd :: BoundedInt a => Range a -> Range a -> Range a
+ Feldspar.Range: rangeAnd :: BoundedInt a => Range a -> Range a -> Range a
+ Feldspar.Range: rangeExp :: BoundedInt a => Range a -> Range a -> Range a
+ Feldspar.Range: rangeExpSigned :: BoundedInt a => Range a -> Range a -> Range a
+ Feldspar.Range: rangeExpUnsigned :: BoundedInt a => Range a -> Range a -> Range a
+ Feldspar.Range: rangeIntersection :: BoundedInt a => Range a -> Range a -> Range a
+ Feldspar.Range: rangeMulSigned :: BoundedInt a => Range a -> Range a -> Range a
+ Feldspar.Range: rangeMulUnsigned :: BoundedInt a => Range a -> Range a -> Range a
+ Feldspar.Range: rangeNeg :: BoundedInt a => Range a -> Range a
+ Feldspar.Range: rangeOr :: BoundedInt a => Range a -> Range a -> Range a
+ Feldspar.Range: rangePropagationSafetyPre2 :: (Random t, BoundedInt t, Random t2, BoundedInt t2, BoundedInt a) => t -> (t -> t2 -> a) -> (Range t -> Range t2 -> Range a) -> (t -> t2 -> Bool) -> Range t -> Range t2 -> Property
+ Feldspar.Range: rangeQuot :: BoundedInt a => Range a -> Range a -> Range a
+ Feldspar.Range: rangeQuotU :: BoundedInt a => Range a -> Range a -> Range a
+ Feldspar.Range: rangeShiftLU :: BoundedInt a => Range a -> Range Word32 -> Range a
+ Feldspar.Range: rangeShiftRU :: BoundedInt a => Range a -> Range Word32 -> Range a
+ Feldspar.Range: rangeSignum :: BoundedInt a => Range a -> Range a
+ Feldspar.Range: rangeSignumSigned :: BoundedInt a => Range a -> Range a
+ Feldspar.Range: rangeSignumUnsigned :: BoundedInt a => Range a -> Range a
+ Feldspar.Range: rangeSub :: BoundedInt a => Range a -> Range a -> Range a
+ Feldspar.Range: rangeTy :: Range t -> t -> Range t
+ Feldspar.Range: rangeUnion :: BoundedInt a => Range a -> Range a -> Range a
+ Feldspar.Range: rangeXor :: BoundedInt a => Range a -> Range a -> Range a
+ Feldspar.Range: typedTests :: (BoundedInt a, Random a, Arbitrary a, Integral a) => a -> [TestCase]
+ Feldspar.Set: (/\) :: Set a => a -> a -> a
+ Feldspar.Set: (\/) :: Set a => a -> a -> a
+ Feldspar.Set: class Eq a => Set a
+ Feldspar.Set: cutOffAt :: Set a => Int -> Widening a
+ Feldspar.Set: empty :: Set a => a
+ Feldspar.Set: fixedPoint :: Set a => (a -> a) -> a -> a
+ Feldspar.Set: indexedFixedPoint :: Set a => (Int -> a -> a) -> a -> (a, Int)
+ Feldspar.Set: instance (Set a, Set b) => Set (a, b)
+ Feldspar.Set: instance (Set a, Set b, Set c) => Set (a, b, c)
+ Feldspar.Set: instance (Set a, Set b, Set c, Set d) => Set (a, b, c, d)
+ Feldspar.Set: instance Set ()
+ Feldspar.Set: intersections :: Set a => [a] -> a
+ Feldspar.Set: type Widening a = (Int -> a -> a) -> (Int -> a -> a)
+ Feldspar.Set: unions :: Set a => [a] -> a
+ Feldspar.Set: universal :: Set a => a
+ Feldspar.Stream: downsample :: Syntactic a => Data Index -> Stream a -> Stream a
+ Feldspar.Stream: duplicate :: Syntactic a => Data Index -> Stream a -> Stream a
+ Feldspar.Stream: instance Syntactic a => RandomAccess (Stream a)
+ Feldspar.Stream: mapNth :: Syntactic a => (a -> a) -> Data Index -> Data Index -> Stream a -> Stream a
+ Feldspar.Stream: maps :: Syntactic a => [(a -> a)] -> Stream a -> Stream a
+ Feldspar.Stream: recurrenceIO :: (Type a, Type b) => DVector a -> Stream (Data a) -> DVector b -> (DVector a -> DVector b -> Data b) -> Stream (Data b)
+ Feldspar.Stream: recurrenceO :: Type a => DVector a -> (DVector a -> Data a) -> Stream (Data a)
+ Feldspar.Stream: streamAsVector :: (Type a, Type b) => (Stream (Data a) -> Stream (Data b)) -> (Vector (Data a) -> Vector (Data b))
+ Feldspar.Stream: streamAsVectorSize :: (Type a, Type b) => (Stream (Data a) -> Stream (Data b)) -> (Data Length -> Data Length) -> (Vector (Data a) -> Vector (Data b))
+ Feldspar.Vector: Empty :: Vector a
+ Feldspar.Vector: continuation :: Vector a -> Vector a
+ Feldspar.Vector: instance (Role a ~ (), Info a ~ EdgeSize () (Internal a), Syntactic a) => EdgeInfo (Vector a)
+ Feldspar.Vector: instance (Role a ~ (), Info a ~ EdgeSize () (Internal a), Syntactic a) => MultiEdge (Vector a) Feldspar EdgeSize
+ Feldspar.Vector: instance (Role a ~ (), Info a ~ EdgeSize () (Internal a), Syntactic a) => Syntactic (Vector a)
+ Feldspar.Vector: instance (Wrap t u, Type a, Nat s) => Wrap (DVector a -> t) (Data' s [a] -> u)
+ Feldspar.Vector: instance Syntactic a => RandomAccess (Vector a)
+ Feldspar.Vector: instance Type a => Wrap (Vector (Data a)) (Data [a])
+ Feldspar.Vector: mergeSegments :: Syntactic a => Vector a -> Vector a
+ Feldspar.Vector: permute' :: (Data Length -> Data Index -> Data Index) -> (Vector a -> Vector a)
+ Feldspar.Vector: rotateVecL :: Syntactic a => Data Index -> Vector a -> Vector a
+ Feldspar.Vector: rotateVecR :: Syntactic a => Data Index -> Vector a -> Vector a
+ Feldspar.Vector: segmentIndex :: Vector a -> Data Index -> a
+ Feldspar.Vector: segmentLength :: Vector a -> Data Length
+ Feldspar.Vector: segments :: Vector a -> [Vector a]
+ Feldspar.Vector: unfreezeVector' :: Type a => Length -> Data [a] -> Vector (Data a)
+ Feldspar.Vector: zip' :: Vector a -> Vector b -> Vector (a, b)
- Feldspar.Core: Range :: Maybe a -> Maybe a -> Range a
+ Feldspar.Core: Range :: a -> a -> Range a
- Feldspar.Core: array :: (Storable a) => Size a -> a -> Data a
+ Feldspar.Core: array :: Type a => Size a -> a -> Data a
- Feldspar.Core: cap :: (Storable a, (Size a) ~ (Range b), Ord b) => Range b -> Data a -> Data a
+ Feldspar.Core: cap :: Type a => Size a -> Data a -> Data a
- Feldspar.Core: data (Ord a) => Range a
+ Feldspar.Core: data Range a
- Feldspar.Core: dataSize :: Data a -> Size a
+ Feldspar.Core: dataSize :: Type a => Data a -> Size a
- Feldspar.Core: eval :: (Computable a) => a -> Internal a
+ Feldspar.Core: eval :: Syntactic a => a -> Internal a
- Feldspar.Core: function :: (Storable a, Storable b) => String -> (Size a -> Size b) -> (a -> b) -> (Data a -> Data b)
+ Feldspar.Core: function :: (Syntactic a, Type b) => Bool -> String -> (Info a -> Size b) -> (Internal a -> b) -> (a -> Data b)
- Feldspar.Core: function2 :: (Storable a, Storable b, Storable c) => String -> (Size a -> Size b -> Size c) -> (a -> b -> c) -> (Data a -> Data b -> Data c)
+ Feldspar.Core: function2 :: (Type a, Type b, Type c) => String -> (Size a -> Size b -> Size c) -> (a -> b -> c) -> (Data a -> Data b -> Data c)
- Feldspar.Core: ifThenElse :: (Computable a, Computable b) => Data Bool -> (a -> b) -> (a -> b) -> (a -> b)
+ Feldspar.Core: ifThenElse :: Syntactic a => Data Bool -> a -> a -> a
- Feldspar.Core: lowerBound :: Range a -> Maybe a
+ Feldspar.Core: lowerBound :: Range a -> a
- Feldspar.Core: parallel :: (Storable a) => Data Length -> (Data Int -> Data a) -> Data [a]
+ Feldspar.Core: parallel :: Type a => Data Length -> (Data Index -> Data a) -> Data [a]
- Feldspar.Core: type Length = Int
+ Feldspar.Core: type Length = DefaultWord
- Feldspar.Core: upperBound :: Range a -> Maybe a
+ Feldspar.Core: upperBound :: Range a -> a
- Feldspar.Core: value :: (Storable a) => a -> Data a
+ Feldspar.Core: value :: Type a => a -> Data a
- Feldspar.Core.Functions: (.&.) :: (Bits a) => Data a -> Data a -> Data a
+ Feldspar.Core.Functions: (.&.) :: Bits a => Data a -> Data a -> Data a
- Feldspar.Core.Functions: (.|.) :: (Bits a) => Data a -> Data a -> Data a
+ Feldspar.Core.Functions: (.|.) :: Bits a => Data a -> Data a -> Data a
- Feldspar.Core.Functions: (/=) :: (Eq a) => Data a -> Data a -> Data Bool
+ Feldspar.Core.Functions: (/=) :: Eq a => Data a -> Data a -> Data Bool
- Feldspar.Core.Functions: (<) :: (Ord a) => Data a -> Data a -> Data Bool
+ Feldspar.Core.Functions: (<) :: Ord a => Data a -> Data a -> Data Bool
- Feldspar.Core.Functions: (<<) :: (Bits a) => Data a -> Data Int -> Data a
+ Feldspar.Core.Functions: (<<) :: Bits a => Data a -> Data Index -> Data a
- Feldspar.Core.Functions: (<=) :: (Ord a) => Data a -> Data a -> Data Bool
+ Feldspar.Core.Functions: (<=) :: Ord a => Data a -> Data a -> Data Bool
- Feldspar.Core.Functions: (==) :: (Eq a) => Data a -> Data a -> Data Bool
+ Feldspar.Core.Functions: (==) :: Eq a => Data a -> Data a -> Data Bool
- Feldspar.Core.Functions: (>) :: (Ord a) => Data a -> Data a -> Data Bool
+ Feldspar.Core.Functions: (>) :: Ord a => Data a -> Data a -> Data Bool
- Feldspar.Core.Functions: (>=) :: (Ord a) => Data a -> Data a -> Data Bool
+ Feldspar.Core.Functions: (>=) :: Ord a => Data a -> Data a -> Data Bool
- Feldspar.Core.Functions: (>>) :: (Bits a) => Data a -> Data Int -> Data a
+ Feldspar.Core.Functions: (>>) :: Bits a => Data a -> Data Index -> Data a
- Feldspar.Core.Functions: (^) :: (Integral a) => Data a -> Data a -> Data a
+ Feldspar.Core.Functions: (^) :: Integral a => Data a -> Data a -> Data a
- Feldspar.Core.Functions: (⊕) :: (Bits a) => Data a -> Data a -> Data a
+ Feldspar.Core.Functions: (⊕) :: Bits a => Data a -> Data a -> Data a
- Feldspar.Core.Functions: bit :: (Bits a) => Data Int -> Data a
+ Feldspar.Core.Functions: bit :: Bits a => Data Index -> Data a
- Feldspar.Core.Functions: bitCount :: (Bits a) => Data a -> Data Int
+ Feldspar.Core.Functions: bitCount :: Bits a => Data a -> Data Index
- Feldspar.Core.Functions: bitScan :: (Bits a) => Data a -> Data Int
+ Feldspar.Core.Functions: bitScan :: Bits a => Data a -> Data Index
- Feldspar.Core.Functions: bitSize :: (Bits a) => Data a -> Data Int
+ Feldspar.Core.Functions: bitSize :: Bits a => Data a -> Data Index
- Feldspar.Core.Functions: class (Bits a, Storable a) => Bits a
+ Feldspar.Core.Functions: class (Bits a, Type a, FullProp (Size a)) => Bits a
- Feldspar.Core.Functions: class (Eq a, Storable a) => Eq a
+ Feldspar.Core.Functions: class Type a => Eq a
- Feldspar.Core.Functions: class (Fractional a, Storable a) => Fractional' a
+ Feldspar.Core.Functions: class (Fractional a, Numeric a) => Fractional' a
- Feldspar.Core.Functions: class (Numeric a, Integral a, Ord a, Storable a) => Integral a
+ Feldspar.Core.Functions: class (Numeric a, BoundedInt a, Bits a, Ord a) => Integral a
- Feldspar.Core.Functions: class (Num a, Storable a) => Numeric a
+ Feldspar.Core.Functions: class (Type a, Num a, FullProp (Size a)) => Numeric a
- Feldspar.Core.Functions: class (Ord a, Eq a, Storable a) => Ord a
+ Feldspar.Core.Functions: class (Eq a, Ord a) => Ord a
- Feldspar.Core.Functions: clearBit :: (Bits a) => Data a -> Data Int -> Data a
+ Feldspar.Core.Functions: clearBit :: Bits a => Data a -> Data Index -> Data a
- Feldspar.Core.Functions: complement :: (Bits a) => Data a -> Data a
+ Feldspar.Core.Functions: complement :: Bits a => Data a -> Data a
- Feldspar.Core.Functions: complementBit :: (Bits a) => Data a -> Data Int -> Data a
+ Feldspar.Core.Functions: complementBit :: Bits a => Data a -> Data Index -> Data a
- Feldspar.Core.Functions: div :: (Integral a) => Data a -> Data a -> Data a
+ Feldspar.Core.Functions: div :: Integral a => Data a -> Data a -> Data a
- Feldspar.Core.Functions: isSigned :: (Bits a) => Data a -> Data Bool
+ Feldspar.Core.Functions: isSigned :: Bits a => Data a -> Data Bool
- Feldspar.Core.Functions: max :: (Ord a) => Data a -> Data a -> Data a
+ Feldspar.Core.Functions: max :: Ord a => Data a -> Data a -> Data a
- Feldspar.Core.Functions: min :: (Ord a) => Data a -> Data a -> Data a
+ Feldspar.Core.Functions: min :: Ord a => Data a -> Data a -> Data a
- Feldspar.Core.Functions: mod :: (Integral a) => Data a -> Data a -> Data a
+ Feldspar.Core.Functions: mod :: Integral a => Data a -> Data a -> Data a
- Feldspar.Core.Functions: quot :: (Integral a) => Data a -> Data a -> Data a
+ Feldspar.Core.Functions: quot :: Integral a => Data a -> Data a -> Data a
- Feldspar.Core.Functions: rem :: (Integral a) => Data a -> Data a -> Data a
+ Feldspar.Core.Functions: rem :: Integral a => Data a -> Data a -> Data a
- Feldspar.Core.Functions: reverseBits :: (Bits a) => Data a -> Data a
+ Feldspar.Core.Functions: reverseBits :: Bits a => Data a -> Data a
- Feldspar.Core.Functions: rotateL :: (Bits a) => Data a -> Data Int -> Data a
+ Feldspar.Core.Functions: rotateL :: Bits a => Data a -> Data DefaultInt -> Data a
- Feldspar.Core.Functions: rotateR :: (Bits a) => Data a -> Data Int -> Data a
+ Feldspar.Core.Functions: rotateR :: Bits a => Data a -> Data DefaultInt -> Data a
- Feldspar.Core.Functions: setBit :: (Bits a) => Data a -> Data Int -> Data a
+ Feldspar.Core.Functions: setBit :: Bits a => Data a -> Data Index -> Data a
- Feldspar.Core.Functions: shiftL :: (Bits a) => Data a -> Data Int -> Data a
+ Feldspar.Core.Functions: shiftL :: Bits a => Data a -> Data DefaultInt -> Data a
- Feldspar.Core.Functions: shiftR :: (Bits a) => Data a -> Data Int -> Data a
+ Feldspar.Core.Functions: shiftR :: Bits a => Data a -> Data DefaultInt -> Data a
- Feldspar.Core.Functions: testBit :: (Bits a) => Data a -> Data Int -> Data Bool
+ Feldspar.Core.Functions: testBit :: Bits a => Data a -> Data Index -> Data Bool
- Feldspar.Core.Functions: xor :: (Bits a) => Data a -> Data a -> Data a
+ Feldspar.Core.Functions: xor :: Bits a => Data a -> Data a -> Data a
- Feldspar.Core.Types: BoolData :: Bool -> PrimitiveData
+ Feldspar.Core.Types: BoolData :: Bool -> DataRep
- Feldspar.Core.Types: BoolType :: PrimitiveType
+ Feldspar.Core.Types: BoolType :: TypeRep
- Feldspar.Core.Types: FloatData :: Float -> PrimitiveData
+ Feldspar.Core.Types: FloatData :: Float -> DataRep
- Feldspar.Core.Types: FloatType :: (Range Float) -> PrimitiveType
+ Feldspar.Core.Types: FloatType :: TypeRep
- Feldspar.Core.Types: IntData :: Integer -> PrimitiveData
+ Feldspar.Core.Types: IntData :: Integer -> DataRep
- Feldspar.Core.Types: IntType :: Bool -> Int -> (Range Integer) -> PrimitiveType
+ Feldspar.Core.Types: IntType :: Range a -> TypeRep
- Feldspar.Core.Types: UserType :: String -> PrimitiveType
+ Feldspar.Core.Types: UserType :: String -> TypeRep
- Feldspar.Core.Types: type Length = Int
+ Feldspar.Core.Types: type Length = DefaultWord
- Feldspar.Matrix: class ElemWise a where { type family Elem a; }
+ Feldspar.Matrix: class Syntactic a => ElemWise a where { type family Elem a; }
- Feldspar.Matrix: diagonal :: Matrix a -> Vector (Data a)
+ Feldspar.Matrix: diagonal :: Type a => Matrix a -> Vector (Data a)
- Feldspar.Matrix: elemWise :: (ElemWise a) => (Elem a -> Elem a -> Elem a) -> a -> a -> a
+ Feldspar.Matrix: elemWise :: ElemWise a => (Elem a -> Elem a -> Elem a) -> a -> a -> a
- Feldspar.Matrix: flatten :: Matrix a -> Vector (Data a)
+ Feldspar.Matrix: flatten :: Type a => Matrix a -> Vector (Data a)
- Feldspar.Matrix: freezeMatrix :: (Storable a) => Matrix a -> Data [[a]]
+ Feldspar.Matrix: freezeMatrix :: Type a => Matrix a -> Data [[a]]
- Feldspar.Matrix: indexedMat :: Data Int -> Data Int -> (Data Int -> Data Int -> Data a) -> Matrix a
+ Feldspar.Matrix: indexedMat :: Data Length -> Data Length -> (Data Index -> Data Index -> Data a) -> Matrix a
- Feldspar.Matrix: matrix :: (Storable a) => [[a]] -> Matrix a
+ Feldspar.Matrix: matrix :: Type a => [[a]] -> Matrix a
- Feldspar.Matrix: mulMat :: (Numeric a) => Matrix a -> Matrix a -> Matrix a
+ Feldspar.Matrix: mulMat :: Numeric a => Matrix a -> Matrix a -> Matrix a
- Feldspar.Matrix: transpose :: Matrix a -> Matrix a
+ Feldspar.Matrix: transpose :: Type a => Matrix a -> Matrix a
- Feldspar.Matrix: unfreezeMatrix :: (Storable a) => Data Length -> Data Length -> Data [[a]] -> Matrix a
+ Feldspar.Matrix: unfreezeMatrix :: Type a => Data [[a]] -> Matrix a
- Feldspar.Range: Range :: Maybe a -> Maybe a -> Range a
+ Feldspar.Range: Range :: a -> a -> Range a
- Feldspar.Range: data (Ord a) => Range a
+ Feldspar.Range: data Range a
- Feldspar.Range: disjoint :: (Ord a, Num a) => Range a -> Range a -> Bool
+ Feldspar.Range: disjoint :: BoundedInt a => Range a -> Range a -> Bool
- Feldspar.Range: emptyRange :: (Ord a, Num a) => Range a
+ Feldspar.Range: emptyRange :: BoundedInt a => Range a
- Feldspar.Range: fromRange :: (Random a, Bounded a, Ord a) => Range a -> Gen a
+ Feldspar.Range: fromRange :: Random a => Range a -> Gen a
- Feldspar.Range: fullRange :: (Ord a) => Range a
+ Feldspar.Range: fullRange :: BoundedInt a => Range a
- Feldspar.Range: inRange :: (Ord a) => a -> Range a -> Bool
+ Feldspar.Range: inRange :: BoundedInt a => a -> Range a -> Bool
- Feldspar.Range: isEmpty :: (Ord a) => Range a -> Bool
+ Feldspar.Range: isEmpty :: BoundedInt a => Range a -> Bool
- Feldspar.Range: isFull :: (Ord a) => Range a -> Bool
+ Feldspar.Range: isFull :: BoundedInt a => Range a -> Bool
- Feldspar.Range: isNatural :: (Ord a, Num a) => Range a -> Bool
+ Feldspar.Range: isNatural :: BoundedInt a => Range a -> Bool
- Feldspar.Range: isNegative :: (Ord a, Num a) => Range a -> Bool
+ Feldspar.Range: isNegative :: BoundedInt a => Range a -> Bool
- Feldspar.Range: isSingleton :: (Ord a) => Range a -> Bool
+ Feldspar.Range: isSingleton :: BoundedInt a => Range a -> Bool
- Feldspar.Range: isSubRangeOf :: (Ord a) => Range a -> Range a -> Bool
+ Feldspar.Range: isSubRangeOf :: BoundedInt a => Range a -> Range a -> Bool
- Feldspar.Range: lowerBound :: Range a -> Maybe a
+ Feldspar.Range: lowerBound :: Range a -> a
- Feldspar.Range: mapMonotonic :: (Ord a, Ord b) => (a -> b) -> Range a -> Range b
+ Feldspar.Range: mapMonotonic :: (a -> b) -> Range a -> Range b
- Feldspar.Range: maxOrUnsigned :: (Ord a, Num a, Bits a) => a -> a -> a -> a -> a
+ Feldspar.Range: maxOrUnsigned :: BoundedInt a => a -> a -> a -> a -> a
- Feldspar.Range: minOrUnsigned :: (Ord a, Num a, Bits a) => a -> a -> a -> a -> a
+ Feldspar.Range: minOrUnsigned :: BoundedInt a => a -> a -> a -> a -> a
- Feldspar.Range: naturalRange :: (Ord a, Num a) => Range a
+ Feldspar.Range: naturalRange :: BoundedInt a => Range a
- Feldspar.Range: negativeRange :: (Ord a, Num a) => Range a
+ Feldspar.Range: negativeRange :: BoundedInt a => Range a
- Feldspar.Range: range :: (Ord a) => a -> a -> Range a
+ Feldspar.Range: range :: a -> a -> Range a
- Feldspar.Range: rangeAddSigned :: (Ord a, Num a, Bounded a, Bits a) => Range a -> Range a -> Range a
+ Feldspar.Range: rangeAddSigned :: BoundedInt a => Range a -> Range a -> Range a
- Feldspar.Range: rangeAddUnsigned :: (Ord a, Num a, Bounded a) => Range a -> Range a -> Range a
+ Feldspar.Range: rangeAddUnsigned :: BoundedInt a => Range a -> Range a -> Range a
- Feldspar.Range: rangeAndUnsignedCheap :: (Ord a, Num a, Bounded a) => Range a -> Range a -> Range a
+ Feldspar.Range: rangeAndUnsignedCheap :: BoundedInt a => Range a -> Range a -> Range a
- Feldspar.Range: rangeByRange :: (Ord a) => Range a -> Range a -> Range a
+ Feldspar.Range: rangeByRange :: Range a -> Range a -> Range a
- Feldspar.Range: rangeGap :: (Ord a, Num a) => Range a -> Range a -> Range a
+ Feldspar.Range: rangeGap :: BoundedInt a => Range a -> Range a -> Range a
- Feldspar.Range: rangeLess :: (Ord a) => Range a -> Range a -> Bool
+ Feldspar.Range: rangeLess :: BoundedInt a => Range a -> Range a -> Bool
- Feldspar.Range: rangeLessEq :: (Ord a) => Range a -> Range a -> Bool
+ Feldspar.Range: rangeLessEq :: BoundedInt a => Range a -> Range a -> Bool
- Feldspar.Range: rangeMax :: (Ord a) => Range a -> Range a -> Range a
+ Feldspar.Range: rangeMax :: BoundedInt a => Range a -> Range a -> Range a
- Feldspar.Range: rangeMin :: (Ord a) => Range a -> Range a -> Range a
+ Feldspar.Range: rangeMin :: BoundedInt a => Range a -> Range a -> Range a
- Feldspar.Range: rangeMod :: (Num a, Ord a, Enum a) => Range a -> Range a -> Range a
+ Feldspar.Range: rangeMod :: BoundedInt a => Range a -> Range a -> Range a
- Feldspar.Range: rangeMul :: (Ord a, Num a) => Range a -> Range a -> Range a
+ Feldspar.Range: rangeMul :: BoundedInt a => Range a -> Range a -> Range a
- Feldspar.Range: rangeNegSigned :: (Ord a, Num a, Bounded a) => Range a -> Range a
+ Feldspar.Range: rangeNegSigned :: BoundedInt a => Range a -> Range a
- Feldspar.Range: rangeNegUnsigned :: (Ord a, Num a, Bounded a) => Range a -> Range a
+ Feldspar.Range: rangeNegUnsigned :: BoundedInt a => Range a -> Range a
- Feldspar.Range: rangeOp :: (Ord a) => (Range a -> Range a) -> (Range a -> Range a)
+ Feldspar.Range: rangeOp :: BoundedInt a => (Range a -> Range a) -> (Range a -> Range a)
- Feldspar.Range: rangeOp2 :: (Ord a) => (Range a -> Range a -> Range a) -> (Range a -> Range a -> Range a)
+ Feldspar.Range: rangeOp2 :: BoundedInt a => (Range a -> Range a -> Range a) -> (Range a -> Range a -> Range a)
- Feldspar.Range: rangeOrUnsignedAccurate :: (Ord a, Num a, Bits a, Bounded a) => Range a -> Range a -> Range a
+ Feldspar.Range: rangeOrUnsignedAccurate :: BoundedInt a => Range a -> Range a -> Range a
- Feldspar.Range: rangeOrUnsignedCheap :: (Ord a, Num a, Bounded a) => Range a -> Range a -> Range a
+ Feldspar.Range: rangeOrUnsignedCheap :: BoundedInt a => Range a -> Range a -> Range a
- Feldspar.Range: rangePropagationSafetyPre :: (Random a, Ord a, Show a, Bounded a, Random b, Ord b, Show b, Bounded b, Ord c) => (a -> b -> c) -> (Range a -> Range b -> Range c) -> (a -> b -> Bool) -> Range a -> Range b -> Property
+ Feldspar.Range: rangePropagationSafetyPre :: (Random t, BoundedInt t, BoundedInt a) => t -> (t -> t -> a) -> (Range t -> Range t -> Range a) -> (t -> t -> Bool) -> Range t -> Range t -> Property
- Feldspar.Range: rangeRem :: (Num a, Ord a, Enum a) => Range a -> Range a -> Range a
+ Feldspar.Range: rangeRem :: BoundedInt a => Range a -> Range a -> Range a
- Feldspar.Range: rangeSize :: (Ord a, Num a) => Range a -> Maybe a
+ Feldspar.Range: rangeSize :: BoundedInt a => Range a -> a
- Feldspar.Range: rangeSubUnsigned :: (Ord a, Num a, Bounded a) => Range a -> Range a -> Range a
+ Feldspar.Range: rangeSubUnsigned :: BoundedInt a => Range a -> Range a -> Range a
- Feldspar.Range: rangeXorUnsigned :: (Ord a, Num a, Bounded a) => Range a -> Range a -> Range a
+ Feldspar.Range: rangeXorUnsigned :: BoundedInt a => Range a -> Range a -> Range a
- Feldspar.Range: showBound :: (Show a) => Maybe a -> String
+ Feldspar.Range: showBound :: BoundedInt a => a -> String
- Feldspar.Range: showRange :: (Show a, Ord a) => Range a -> String
+ Feldspar.Range: showRange :: BoundedInt a => Range a -> String
- Feldspar.Range: singletonRange :: (Ord a) => a -> Range a
+ Feldspar.Range: singletonRange :: a -> Range a
- Feldspar.Range: upperBound :: Range a -> Maybe a
+ Feldspar.Range: upperBound :: Range a -> a
- Feldspar.Stream: cycle :: (Computable a) => Vector a -> Stream a
+ Feldspar.Stream: cycle :: Syntactic a => Vector a -> Stream a
- Feldspar.Stream: drop :: Data Unsigned32 -> Stream a -> Stream a
+ Feldspar.Stream: drop :: Data Length -> Stream a -> Stream a
- Feldspar.Stream: head :: (Computable a) => Stream a -> a
+ Feldspar.Stream: head :: Syntactic a => Stream a -> a
- Feldspar.Stream: interleave :: Stream a -> Stream a -> Stream a
+ Feldspar.Stream: interleave :: Syntactic a => Stream a -> Stream a -> Stream a
- Feldspar.Stream: intersperse :: a -> Stream a -> Stream a
+ Feldspar.Stream: intersperse :: Syntactic a => a -> Stream a -> Stream a
- Feldspar.Stream: iterate :: (Computable a) => (a -> a) -> a -> Stream a
+ Feldspar.Stream: iterate :: Syntactic a => (a -> a) -> a -> Stream a
- Feldspar.Stream: map :: (Computable a, Computable b) => (a -> b) -> Stream a -> Stream b
+ Feldspar.Stream: map :: (Syntactic a, Syntactic b) => (a -> b) -> Stream a -> Stream b
- Feldspar.Stream: mapAccum :: (Computable acc, Computable b) => (acc -> a -> (acc, b)) -> acc -> Stream a -> Stream b
+ Feldspar.Stream: mapAccum :: (Syntactic acc, Syntactic b) => (acc -> a -> (acc, b)) -> acc -> Stream a -> Stream b
- Feldspar.Stream: recurrenceI :: (Storable a, Storable b) => DVector a -> Stream (Data a) -> DVector b -> ((Data Int -> Data a) -> (Data Int -> Data b) -> Data b) -> Stream (Data b)
+ Feldspar.Stream: recurrenceI :: (Type a, Type b) => DVector a -> Stream (Data a) -> (DVector a -> Data b) -> Stream (Data b)
- Feldspar.Stream: repeat :: (Computable a) => a -> Stream a
+ Feldspar.Stream: repeat :: Syntactic a => a -> Stream a
- Feldspar.Stream: scan :: (Computable a) => (a -> b -> a) -> a -> Stream b -> Stream a
+ Feldspar.Stream: scan :: Syntactic a => (a -> b -> a) -> a -> Stream b -> Stream a
- Feldspar.Stream: splitAt :: (Storable a) => Data Int -> Stream (Data a) -> (Data [a], Stream (Data a))
+ Feldspar.Stream: splitAt :: Type a => Data Length -> Stream (Data a) -> (Data [a], Stream (Data a))
- Feldspar.Stream: tail :: (Computable a) => Stream a -> Stream a
+ Feldspar.Stream: tail :: Syntactic a => Stream a -> Stream a
- Feldspar.Stream: take :: (Storable a) => Data Int -> Stream (Data a) -> Data [a]
+ Feldspar.Stream: take :: Type a => Data Length -> Stream (Data a) -> Data [a]
- Feldspar.Stream: unfold :: (Computable a, Computable c) => (c -> (a, c)) -> c -> Stream a
+ Feldspar.Stream: unfold :: (Syntactic a, Syntactic c) => (c -> (a, c)) -> c -> Stream a
- Feldspar.Stream: unzip :: (Computable a, Computable b) => Stream (a, b) -> (Stream a, Stream b)
+ Feldspar.Stream: unzip :: (Syntactic a, Syntactic b) => Stream (a, b) -> (Stream a, Stream b)
- Feldspar.Stream: zipWith :: (Computable c) => (a -> b -> c) -> Stream a -> Stream b -> Stream c
+ Feldspar.Stream: zipWith :: Syntactic c => (a -> b -> c) -> Stream a -> Stream b -> Stream c
- Feldspar.Vector: (++) :: (Computable a) => Vector a -> Vector a -> Vector a
+ Feldspar.Vector: (++) :: Vector a -> Vector a -> Vector a
- Feldspar.Vector: (...) :: Data Int -> Data Int -> Vector (Data Int)
+ Feldspar.Vector: (...) :: Data Index -> Data Index -> Vector (Data Index)
- Feldspar.Vector: Indexed :: Data Length -> (Data Ix -> a) -> Vector a
+ Feldspar.Vector: Indexed :: Data Length -> (Data Index -> a) -> Vector a -> Vector a
- Feldspar.Vector: drop :: Data Int -> Vector a -> Vector a
+ Feldspar.Vector: drop :: Data Length -> Vector a -> Vector a
- Feldspar.Vector: enumFromTo :: Data Int -> Data Int -> Vector (Data Int)
+ Feldspar.Vector: enumFromTo :: Data Index -> Data Index -> Vector (Data Index)
- Feldspar.Vector: fold :: (Computable a) => (a -> b -> a) -> a -> Vector b -> a
+ Feldspar.Vector: fold :: Syntactic a => (a -> b -> a) -> a -> Vector b -> a
- Feldspar.Vector: fold1 :: (Computable a) => (a -> a -> a) -> Vector a -> a
+ Feldspar.Vector: fold1 :: Type a => (Data a -> Data a -> Data a) -> Vector (Data a) -> Data a
- Feldspar.Vector: freezeVector :: (Storable a) => Vector (Data a) -> Data [a]
+ Feldspar.Vector: freezeVector :: Type a => Vector (Data a) -> Data [a]
- Feldspar.Vector: head :: Vector a -> a
+ Feldspar.Vector: head :: Syntactic a => Vector a -> a
- Feldspar.Vector: indexed :: Data Length -> (Data Ix -> a) -> Vector a
+ Feldspar.Vector: indexed :: Data Length -> (Data Index -> a) -> Vector a
- Feldspar.Vector: last :: Vector a -> a
+ Feldspar.Vector: last :: Syntactic a => Vector a -> a
- Feldspar.Vector: maximum :: (Ord a) => Vector (Data a) -> Data a
+ Feldspar.Vector: maximum :: Ord a => Vector (Data a) -> Data a
- Feldspar.Vector: memorize :: (Storable a) => Vector (Data a) -> Vector (Data a)
+ Feldspar.Vector: memorize :: Syntactic (Vector a) => Vector a -> Vector a
- Feldspar.Vector: minimum :: (Ord a) => Vector (Data a) -> Data a
+ Feldspar.Vector: minimum :: Ord a => Vector (Data a) -> Data a
- Feldspar.Vector: permute :: (Data Length -> Data Ix -> Data Ix) -> (Vector a -> Vector a)
+ Feldspar.Vector: permute :: Syntactic a => (Data Length -> Data Index -> Data Index) -> (Vector a -> Vector a)
- Feldspar.Vector: replicate :: Data Int -> a -> Vector a
+ Feldspar.Vector: replicate :: Data Length -> a -> Vector a
- Feldspar.Vector: reverse :: Vector a -> Vector a
+ Feldspar.Vector: reverse :: Syntactic a => Vector a -> Vector a
- Feldspar.Vector: scalarProd :: (Numeric a) => Vector (Data a) -> Vector (Data a) -> Data a
+ Feldspar.Vector: scalarProd :: Numeric a => Vector (Data a) -> Vector (Data a) -> Data a
- Feldspar.Vector: splitAt :: Data Int -> Vector a -> (Vector a, Vector a)
+ Feldspar.Vector: splitAt :: Data Index -> Vector a -> (Vector a, Vector a)
- Feldspar.Vector: sum :: (Numeric a) => Vector (Data a) -> Data a
+ Feldspar.Vector: sum :: Numeric a => Vector (Data a) -> Data a
- Feldspar.Vector: take :: Data Int -> Vector a -> Vector a
+ Feldspar.Vector: take :: Data Length -> Vector a -> Vector a
- Feldspar.Vector: unfreezeVector :: (Storable a) => Data Length -> Data [a] -> Vector (Data a)
+ Feldspar.Vector: unfreezeVector :: Type a => Data [a] -> Vector (Data a)
- Feldspar.Vector: vector :: (Storable a) => [a] -> Vector (Data a)
+ Feldspar.Vector: vector :: Type a => [a] -> Vector (Data a)
- Feldspar.Vector: zip :: Vector a -> Vector b -> Vector (a, b)
+ Feldspar.Vector: zip :: (Syntactic a, Syntactic b) => Vector a -> Vector b -> Vector (a, b)
- Feldspar.Vector: zipWith :: (a -> b -> c) -> Vector a -> Vector b -> Vector c
+ Feldspar.Vector: zipWith :: (Syntactic a, Syntactic b) => (a -> b -> c) -> Vector a -> Vector b -> Vector c

Files

+ Examples/Effects/Overdrive.hs view
@@ -0,0 +1,23 @@+module Examples.Effects.Overdrive where++import qualified Prelude+import Feldspar+import Feldspar.Vector+import Feldspar.Compiler++-- | Generic (not compilable) overdrive function+overdrive :: (Numeric a, Ord a) => DVector a -> Data a -> Data a -> DVector a+overdrive x mul bound = map (\x -> x * mul) $ map mapFn x+  where+    mapFn elem = (?) (elem > bound) (bound, elseBranch)+      where+        elseBranch = (?) (elem < - bound) (-bound,elem)++-- | Wrapper to fix the type and size of the vectors in overdrive.+overdriveInstance :: Data [Float] -> Data Float -> Data Float -> Data [Float]+overdriveInstance x mul bound =+    freezeVector $ overdrive (unfreezeVector' 256 x) mul bound+    +-- | Wrapper to fix the type and size of the vectors in overdrive.+overdrive_wrapped :: Data' D256 [Float] -> Data Float -> Data Float -> Data [Float]+overdrive_wrapped = wrap (overdrive :: DVector Float -> Data Float -> Data Float -> DVector Float)
+ Examples/Effects/ShiftByOneOctave.hs view
@@ -0,0 +1,25 @@+module Examples.Effects.ShiftByOneOctave where++import qualified Prelude+import Feldspar+import Feldspar.Vector+import Feldspar.Compiler++-- | Generic (not compilable) algorithm to double the frequency of a signal.+-- This is an approximate solution without using FFT.+shiftByOneOctave :: (Fractional' a) => DVector a -> DVector a+shiftByOneOctave inp = half ++ half+    where+        half = everySecond $ map avg $ zip inp $ tail inp+        everySecond xs = indexed (length xs `div` 2) $ \idx -> xs ! (2*idx)+        avg (x,y) = (x + y) / 2++-- | Wrapper to fix the type and size of the vectors in shiftByOneOctave.+shiftByOneOctaveInstance :: Data [Float] -> Data [Float]+shiftByOneOctaveInstance input = freezeVector $ shiftByOneOctave input'+    where+        input' = unfreezeVector' 256 input++-- | Wrapper to fix the type and size of the vectors in shiftByOneOctave.+shiftByOneOctave_wrapped :: Data' D256 [Float] ->  Data [Float]+shiftByOneOctave_wrapped = wrap (shiftByOneOctave :: DVector Float -> DVector Float)
+ Examples/Math/Convolution.hs view
@@ -0,0 +1,22 @@+module Examples.Math.Convolution where++import qualified Prelude+import Feldspar+import Feldspar.Vector+import Feldspar.Compiler+import Feldspar.Matrix++-- | Generic (not compilable) convolution function+convolution :: (Numeric a) => DVector a -> DVector a -> DVector a+convolution kernel input = map ((scalarProd kernel) . reverse) $ inits input++-- | Wrappers to define the size and element type of vectors in 'convolution'+convolutionInstance :: Data [Float] -> Data [Float] -> Data [Float]+convolutionInstance kernel input = freezeVector $ convolution kernel' input'+    where+        input'  = unfreezeVector' 256 input+        kernel' = unfreezeVector'  16 kernel++-- | Wrappers to define the size and element type of vectors in 'convolution'+convolution_wrapped :: Data' D16 [Float] ->  Data' D256 [Float] ->  Data [Float]+convolution_wrapped = wrap (convolution :: DVector Float -> DVector Float -> DVector Float)
+ Examples/Math/Fft.hs view
@@ -0,0 +1,124 @@+module Examples.Math.Fft where++import qualified Prelude as P+import Feldspar+import Feldspar.Vector+import Feldspar.Matrix+import Feldspar.Compiler++-- | Wrapper to define the size of vectors in 'fft'+fftInstance :: Data [Complex Float] -> Data [Complex Float]+fftInstance = freezeVector . fft . unfreezeVector' 256++-- | Wrapper to define the size of vectors in 'fft'+fft_wrapped ::Data' D256 [Complex Float] ->  Data [Complex Float]+fft_wrapped = wrap fft++-- | Wrapper to define the size of vectors in 'ifft'+ifftInstance :: Data [Complex Float] -> Data [Complex Float]+ifftInstance = freezeVector . ifft . unfreezeVector' 256++-- | Wrapper to define the size of vectors in 'ifft'+ifft_wrapped ::Data' D256 [Complex Float] ->  Data [Complex Float]+ifft_wrapped = wrap ifft+++-- =================== INTERFACE ==================================+-- | Radix-2 Decimation-In-Frequeny Fast Fourier Transformation of the given complex vector+--   The given vector must be power-of-two sized, (for example 2, 4, 8, 16, 32, etc.)+fft :: DVector (Complex Float) -> DVector (Complex Float)+fft v = bitRev (loglen-1) $ fftCore (loglen-1) v+    where loglen = f2i $ logBase 2 $ i2f $  length v++-- | Radix-2 Decimation-In-Frequeny Inverse Fast Fourier Transformation of the given complex vector+--   The given vector must be power-of-two sized, (for example 2, 4, 8, 16, 32, etc.)+ifft :: DVector (Complex Float) -> DVector (Complex Float)+ifft v = bitRev (loglen-1) $ ifftCore (loglen-1) v+    where loglen = f2i $ logBase 2 $ i2f $ length v+-- ================================================================+++++-- | fftCore function uses 2^(n+1) input vector.+--	 Output from the last stage needs to be bit reversed using bitRev function (if required)+fftCore ::  Data Index ->  DVector (Complex Float) -> DVector (Complex Float) +fftCore n v = composeOn stage (reverse (0...n)) v++stage k (Indexed l ixf Empty) = (Indexed l ixf' Empty)+  where+    k2 = 1 << k+    ixf' i = condition (testBit i k)   (twid * (b-a))   (a+b)+      where+        a = ixf i+        b = ixf (i `xor` k2)+        twid = cis (-pi*(i2f (lsbs k i)) / i2f k2)++        +-- | ifftCore function uses 2^(n+1) input vector.+--	 Output from the last stage needs to be bit reversed using bitRev function (if required)+ifftCore ::  Data Index ->  DVector (Complex Float) -> DVector (Complex Float) +ifftCore n v = map (/ (complex (i2f (2^(n+1))) 0)) $ composeOn istage (reverse (0...n)) v++istage k (Indexed l ixf Empty) = (Indexed l ixf' Empty)+  where+    k2 = 1 << k+    ixf' i = condition (testBit i k)   (twid * (b-a))   (a+b)+      where+        a = ixf i+        b = ixf (i `xor` k2)+        twid = cis (pi*(i2f (lsbs k i)) / i2f k2)+		++-- | bitRev function transforms the given vector to bitreversal order+--   parameter n is the size of the input vector+bitRev :: Type a => Data Index -> Vector (Data a) -> Vector (Data a)+bitRev n = pipe riffle (1...n)+++-- | Helper functions for fftCore and ifftCore and bitRev+pipe :: (Syntactic a) => (Data Index -> a -> a) -> Vector (Data Index) -> a -> a+pipe = flip.fold.flip++composeOn f is as = fold (flip f) as is++allOnes = complement 0++oneBits n = complement (allOnes << n)++lsbs k i = i .&. oneBits k++par m n f = mat2Vec m n . map f . vec2Mat m n ++-- k at least 1+rotBit :: Data Index -> Data Index -> Data Index+rotBit 0 _ = error "k should be at least 1"+rotBit k i = lefts .|. rights+  where+    ir = i >> 1+    rights = ir .&. (oneBits k)+    lefts  = (((ir >> k) << 1) .|. (i .&. 1)) << k++riffle k (Indexed l ixf Empty) = indexed l (ixf.rotBit k)++vec2Mat :: Data Index -> Data Index -> Vector (Data a) -> Matrix a+vec2Mat m n (Indexed l ixf Empty) = indexedMat (1 << m) (1 << n) ixf'+  where+    ixf' i j = ixf $ (i << n) `xor` j +      +mat2Vec :: Type a => Data Index -> Data Index -> Matrix a -> Vector (Data a)+mat2Vec m n matr = Indexed (1 << m << n) ixf Empty+  where+    ixf i = matr ! y ! x+      where+        y = i >> n+        x = i .&. (oneBits n)+++		+-- Ad-hoc function to generate a power-of-two sequence in order to test fft and ifft+pow2Seq :: Data DefaultWord -> DVector (Complex Float)+pow2Seq n = indexed (2 ^ n) (\i ->complex (i2f i) 0 )+++
+ Examples/Simple/Basics.hs view
@@ -0,0 +1,43 @@+module Examples.Simple.Basics where++import qualified Prelude+import Feldspar+import Feldspar.Vector+import Feldspar.Compiler++-- Identity function for 32 bit integers.+example1 :: Data Int32 -> Data Int32+example1 = id++-- Constant function+example2 :: Data Int32+example2 = 2++-- A constant core vector+example3 :: Data [Int32]+example3 = value [42,1,2,3]++-- Examples showing some of the integer and boolean operations:++example4 :: Data Int32 -> Data Int32+example4 x = negate x++example5 :: Data Int32 -> Data Int32 -> Data Int32+example5 x y = x + y++example6 :: Data Int32 -> Data Int32 -> Data Bool+example6 x y = x == y++example7 :: Data Bool+example7 = 2 /= (2 :: Data Int32) -- Type of numeric literals sometimes have to be written explicitly.++example8 :: Data Bool -> Data Bool+example8 b = not b++-- Examples on using conditionals:++example9 :: Data Int32 -> Data Int32+example9 a = condition (a<5) (3*(a+a)) (30*(a+20))++example10 :: Data Int32 -> Data Int32+example10 a = condition (a<5) (3*(a+a)) (30*(a+a))
+ Examples/Simple/Complex.hs view
@@ -0,0 +1,35 @@+module Examples.Simple.Complex where++import qualified Prelude+import Feldspar+import Feldspar.Vector+import Feldspar.Compiler++-- | Creation of complex values, addition and conjugation.+complex1 :: Data (Complex Float)+complex1 = conjugate $ value (3 :+ 4) + value (0 :+ 9)++-- | Constant vector containing complex values.+complex2 :: Data [Complex Float]+complex2 = wrap $ vector+    [ 3 :+ 4 :: Complex Float,    0 :+ 9,    (-13) :+ (-4), 32 :+ 22+    , 0 :+ 0,    10 :+ 9,   3 :+ (-2),     21 :+ 3+    , 10 :+ 4,   2 :+ 2,    0 :+ 1,        0 :+ (-10)+    , (-1) :+ 0, 3 :+ (-3), 5 :+ 55+    ]++-- | Sum of a complex vector.+complex3 :: Data' D256 [Complex Float] -> Data (Complex Float)+complex3 = wrap (sum :: DVector (Complex Float) -> Data (Complex Float))+ +-- | Generic (not compilable) pairwise multiplication of vectors.+complex4 :: (Syntactic a, Num a) => Vector a -> Vector a -> Vector a+complex4 = zipWith (*)++-- | Instance of the generic algorithm for complex values and fixed length arrays.+complex4' :: Data' D256 [Complex Float] -> Data' D256 [Complex Float] -> Data [Complex Float]+complex4' = wrap (complex4 :: DVector (Complex Float) -> DVector (Complex Float) -> DVector (Complex Float))++-- | Real parts of a complex vector.+complex5 :: Data' D256 [Complex Float] -> Data [Float]+complex5 = wrap $ map (realPart :: Data (Complex Float) -> Data Float)
+ Examples/Simple/Fixedpoint.hs view
@@ -0,0 +1,112 @@+module Examples.Simple.Fixedpoint where++import Prelude ()+import qualified Prelude as P+import Feldspar+import Feldspar.FixedPoint+import Feldspar.Compiler+import Feldspar.Vector++-- | Generic (not compilable) adder+fpex1 :: (Num a) => a -> a -> a+fpex1 x y = x + y++-- | Wrapper for 'fpex1' using fixed-point numbers+-- (with type Int32, input exponents are (-2) and (-3), +--                     while the output exponent is (-4))+fpex1Fix32 :: Data Int32 -> Data Int32 -> Data Int32+fpex1Fix32 x y = freezeFix' (-2) $ fpex1 ((unfreezeFix' (-3) x)) +                                        ((unfreezeFix' (-4) y))++-- | Wrapper for 'fpex1' using floating-point numbers+fpex1Float :: Data Float -> Data Float -> Data Float+fpex1Float x y = fpex1 x y++-- | Generic (not compilable) division+fpex2 :: (Fractional a, Fixable a) => a -> a -> a+fpex2 x y = x / y++-- | Wrapper for 'fpex2' using fixed-point numbers+fpex2Fix32 :: Data Int32 -> Data Int32 -> Data Int32+fpex2Fix32 x y = freezeFix' (-4) $ fpex2 ((unfreezeFix' (-8) x)) +                                        ((unfreezeFix' (-4) y))++-- | Wrapper for 'fpex3' using floating-point numbers+fpex2Float :: Data Float -> Data Float -> Data Float+fpex2Float x y = fpex2 x y++-- | Generic (not compilable) function adding 0.25 to the input+fpex3 :: (Num a,Fractional a,Fixable a) => a -> a+fpex3 x = x + (fix (-2) 0.25)++-- | Wrapper for 'fpex3' using fixed-point numbers (with type Int32)+fpex3Fix32 :: Data Int32 -> Data Int32+fpex3Fix32 x = freezeFix' (-4) $ fpex3 $ unfreezeFix' (-2) x++-- | Wrapper for 'fpex3' using floating-point numbers+fpex3Float :: Data Float -> Data Float+fpex3Float x = fpex3 x++-- | Generic (not compilable) function increasing each element of the input vector+fpex4 :: (Num a) => +         a -> Vector a -> Vector a+fpex4 x = map (x+)++-- | Wrapper for 'fpex4' using fixed-point numbers (with type Int32)+fpex4Fix32 :: Data Int32 -> DVector Int32 -> DVector Int32+fpex4Fix32 x xs = map (freezeFix' (-4)) $ fpex4 x' xs'+   where+      xs' :: Vector (Fix Int32)+      xs' = map (unfreezeFix' (-6)) xs+      x'  :: Fix Int32+      x'  = unfreezeFix' (-8) x++-- | Wrapper for 'fpex4' using floating-point numbers+fpex4Float :: Data Float -> Data [Float] -> Data [Float]+fpex4Float x xs = freezeVector $ fpex4 x xs'+   where+      xs' = unfreezeVector' 256 xs+      ++-- | Generic (not compilable) average function+fpex5 :: (Num a,Fractional a) => a -> a -> a+fpex5 x y = (x + y) / 2 ++-- | Wrapper for 'fpex5' using fixed-point numbers (with type Int32)+fpex5Fix32 :: Data Int32 -> Data Int32 -> Data Int32+fpex5Fix32 x y = freezeFix' (-5)  $ fpex5 x' y'+  where+    x' = unfreezeFix' (-4) x+    y' = unfreezeFix' (-6) y++-- | Wrapper for 'fpex5' using floating-point numbers+fpex5Float :: Data Float -> Data Float -> Data Float+fpex5Float x y = fpex5 x y++-- | Generic (not compilable) function with condition+fpex6 :: (Fractional a, Syntactic a, Fixable a) => Data Bool -> a -> a+fpex6 cond x = cond ?! (x, x+100.256)++-- | Wrapper for 'fpex6' using fixed-point numbers (with type Int32)+fpex6Fix32 :: Data Bool -> Data Int32 -> Data Int32+fpex6Fix32 cond = freezeFix' (-2) . fpex6 cond . unfreezeFix' (-3)++-- | Wrapper for 'fpex6' using floating-point numbers+fpex6Float :: Data Bool -> Data Float -> Data Float+fpex6Float = fpex6++-- | Generic (not compilable) scalar product function+fpScalarProd :: (Num a, Syntactic a, Fixable a) =>+                Vector a -> Vector a -> a+fpScalarProd x y = fixFold (+) (fix (-8) 0) $ zipWith (*) x y++-- | Wrapper for 'fpScalarProd' using fixed-point numbers (with type Int32)+fpScalarProdFix32 :: DVector Int32 -> DVector Int32 -> Data Int32+fpScalarProdFix32 x y = freezeFix' (-8) $ fpScalarProd x' y'+  where+    x' = map (unfreezeFix' (-6)) x+    y' = map (unfreezeFix' (-4)) y++-- | Wrapper for 'fpScalarProd' using floating-point numbers+fpScalarProdFloat :: DVector Float -> DVector Float -> Data Float+fpScalarProdFloat = fpScalarProd
+ Examples/Simple/Matrices.hs view
@@ -0,0 +1,26 @@+module Examples.Simple.Matrices where++import qualified Prelude+import Feldspar+import Feldspar.Vector+import Feldspar.Matrix+import Feldspar.Compiler++-- * Examples on working with matrices.++-- | Generates a parallel matrix.+matrix1 :: Matrix Index+matrix1 = indexed 2 vec+  where+    vec x = indexed 10 ((+x) . (*10))++-- | Generates a parallel matrix (20x100) and transposes it.+matrix2 :: Matrix Index+matrix2 = transpose $ indexed 20 (\x -> indexed 100 ((+x) . (*10)))++-- | Matrix multiplication+matMult ::  Data' (D16,D16) [[Int32]] -> Data' (D16,D16) [[Int32]] -> Data [[Int32]]+matMult = wrap ((***) :: Matrix Int32 -> Matrix Int32 -> Matrix Int32)++matMult' :: Data [[Int32]] -> Data [[Int32]] -> Data [[Int32]]+matMult' m1 m2 = freezeMatrix $ (unfreezeMatrix' 16 16 m1) *** (unfreezeMatrix' 16 16 m2)
+ Examples/Simple/Pairs.hs view
@@ -0,0 +1,23 @@+module Examples.Simple.Pairs where++import Prelude ()+import Feldspar+import Feldspar.Vector+import Feldspar.Compiler++-- | Haskell pairs are compiled to separate variables.+pairs1 :: Data Int32 -> Data Float -> (Data Int32, Data Float)+pairs1 x y = (x,y)++-- | Feldspar pairs are compiled to structs.+pairs2 :: Data Int32 -> Data Float -> Data (Int32,Float)+pairs2 x y = pair x y++-- | Selector functions: getFst, getSnd.+pairs3 :: Data (Int32,Float) -> (Data Int32, Data Float)+pairs3 p = (getFst p, getSnd p)++-- | Zipping two vectors into a vector of pairs.+pairs4 :: Data [Float] -> Data [Int32] -> Data [(Float,Int32)]+pairs4 xs ys = freezeVector $ zipWith pair (unfreezeVector' 256 xs) (unfreezeVector' 256 ys)+
+ Examples/Simple/Sharing.hs view
@@ -0,0 +1,35 @@+module Examples.Simple.Sharing where++import qualified Prelude+import Feldspar+import Feldspar.Vector+import Feldspar.Compiler++-- | Examples on the optimization transformation 'sharing' (also called 'common subexpression elimination').++share1 :: Data Int32 -> Data Int32+share1 v = w + w where+    w = 2 * v++share2 :: Data Int32 -> Data Int32+share2 v = (2*v) + (2*v)++share3 :: Data Int32 -> DVector Int32+share3 v = indexed 10 $ const w where+    w = 2 * v + v++share4 :: Data Int32 -> DVector Int32+share4 v = indexed 10 $ const w where+    w = 2 * q + q where+     q = v + 1++share4' :: Data Int32 -> Data [Int32]+share4' = wrap share4++share5 :: Data Index -> DVector Index+share5 v = indexed 10 $ \ix -> w ix where+    w ix = 2 * v + ix++share5' :: Data Index -> Data [Index]+share5' = wrap share5+
+ Examples/Simple/Streams.hs view
@@ -0,0 +1,25 @@+module Examples.Simple.Streams where++import Prelude ()+import Feldspar+import Feldspar.Vector+import Feldspar.Stream+import Feldspar.Compiler++-- | Generic (not compilable) function to introduce usage of scan function for Streams.+--   'scan f a str' produces a stream by successively applying 'f' to+--   each element of the input stream 'str' and the previous element of+--   the output stream.+stream1 :: (Num a, Syntactic a) => Stream a -> Stream a+stream1 = scan (+) 0++-- | Wrapper to turn the parameters of 'stream1' into vectors.+stream1_1 :: (Numeric a) => DVector a -> DVector a+stream1_1 = streamAsVector stream1++-- | Wrappers to fix the type and size of the streams in  'stream1_1'.+stream1_1' :: Data [Int32] -> Data [Int32]+stream1_1' xs = freezeVector $ stream1_1 $ unfreezeVector' 64 xs++stream1_1_wrapped:: Data' D64 [Int32] -> Data [Int32]+stream1_1_wrapped  = wrap (stream1_1 :: DVector Int32 -> DVector Int32)
+ Examples/Simple/Trace.hs view
@@ -0,0 +1,13 @@+module Examples.Simple.Trace where++import qualified Prelude+import Feldspar+import Feldspar.Vector+import Feldspar.Compiler++--- | Example showing the application of tracing function.+---   Creating three tracing point for each loop cycle,+---   tracing two inputs and result of '+' operation.+ +traceExample :: Data [Int32] -> Data Int32+traceExample xs = fold (\x y -> trace 3 $ trace 1 x + trace 2 y) 0 $ unfreezeVector' 255 xs
+ Examples/Simple/Vectors.hs view
@@ -0,0 +1,60 @@+module Examples.Simple.Vectors where++import qualified Prelude+import Feldspar+import Feldspar.Vector+import Feldspar.Compiler++-- * Examples on working with vectors.++-- | Generates a vector: [1, 2, 3, ... , 16],+-- adds 3 to every element and+-- reverses the vector then+-- multiplies every element by 10.+vector1 :: DVector Index+vector1 = map (*10) $ reverse $ map (+3) $ enumFromTo 1 16++-- | The same computation, but storing each intermediate result into temporal buffers+vector1' :: DVector Index+vector1' = map (*10) $ force $ reverse $ force $ map (+3) $ force $ enumFromTo 1 16++-- | Drops the first 3 elements of a vector+vector2 :: DVector Int32 -> DVector Int32+vector2 = drop 3++-- | Wrappers to `vector2` to provide static information on the input vector size+vector2' :: Data' D10 [Int32] -> Data [Int32]+vector2' = wrap vector2++vector2'' :: Data [Int32] -> Data [Int32]+vector2'' = freezeVector . vector2 . unfreezeVector' 10++-- | Generates a parallel vector of size 10+vector3 :: Data Index -> DVector Index+vector3 a = indexed 10 ((+a) . (*10))++-- | Vector summation.+vector4 :: (Numeric a) => DVector a -> Data a+vector4 xs = fold (+) 0 xs++-- | Wrappers to provide the necessary type information+vector4' :: DVector Int32 -> Data Int32+vector4' = vector4++vector4'' :: DVector Word8 -> Data Word8+vector4'' = vector4++-- | Generic function to increment vector elements+vector5 :: (Numeric a) => DVector a -> DVector a+vector5 = map (+1)++-- | Wrappers to provide necessary type information and input size+vector5' :: DVector Int32 -> DVector Int32+vector5' = vector5++vector5'' :: Data' D64 [Int32] -> Data [Int32]+vector5'' = wrap (vector5 :: DVector Int32 -> DVector Int32)++-- | Concatenation+vector6 :: DVector Int32 -> DVector Int32+vector6 xs = map (+1) xs ++ map (*2) xs
+ Examples/Tutorial/FixedPoint.hs view
@@ -0,0 +1,44 @@+module Fixedpoint where++import qualified Prelude+import Feldspar+import Feldspar.FixedPoint+import Feldspar.Compiler+import Feldspar.Vector++generic :: (Fractional a) => Vector a -> Vector a+generic = map (\x -> x+3.14)++floating :: DVector Float -> DVector Float+floating = generic++fixed :: DVector Int32 -> DVector Int32+fixed = map (freezeFix' (-6)) . generic . map (unfreezeFix' (-4))++emulation :: Vector (Fix Int16) -> Vector (Fix Int16)+emulation = generic++branch1 :: Data Bool -> Data Int32 -> Data Int32 -> Data Int32+branch1 c x y = freezeFix' (-16) $ c ? (x', y')+  where+    x' = unfreezeFix' (-20) x+    y' = unfreezeFix' (-10) y++branch2 :: Data Bool -> Data Int32 -> Data Int32 -> Data Int32+branch2 c x y = freezeFix' (-16) $ c ?! (x', y')+  where+    x' = unfreezeFix' (-20) x+    y' = unfreezeFix' (-10) y++scalarProduct :: (Num a, Syntactic a, Fixable a) =>+              Data DefaultInt -> Vector a -> Vector a -> a+scalarProduct e xs ys = fixFold (+) (fix e 0) $ zipWith (*) xs ys++floatScalarProduct :: DVector Float -> DVector Float -> Data Float+floatScalarProduct = scalarProduct undefined++fixScalarProduct :: DVector Int32 -> DVector Int32 -> Data Int32+fixScalarProduct xs ys = freezeFix' (-18) $ scalarProduct (-16) xs' ys'+  where+    xs' = map (unfreezeFix' (-8)) xs+    ys' = map (unfreezeFix' (-6)) ys
+ Examples/Tutorial/Stream.hs view
@@ -0,0 +1,23 @@+module Examples.Tutorial.Stream where++import qualified Prelude+import Feldspar+import Feldspar.Stream hiding (fir,iir)+import Feldspar.Vector (Vector, DVector+                       , replicate, length, scalarProd, reverse, vector)++fir :: DVector Float ->+       Stream (Data Float) -> Stream (Data Float)+fir b input =+    recurrenceI (replicate (length b) 0) input+                (\input -> scalarProd b (reverse input))++iir :: Data Float -> DVector Float -> DVector Float ->+       Stream (Data Float) -> Stream (Data Float)+iir a0 a b input =+    recurrenceIO (replicate (length b) 0) input+                 (replicate (length a) 0)+      (\input output -> 1 / a0 *+                        ( scalarProd b (reverse input)+                        - scalarProd a (reverse output))+      )
+ Examples/Tutorial/Tutorial.hs view
@@ -0,0 +1,606 @@+{-# LANGUAGE NoMonomorphismRestriction #-}
+
+module Tutorial where
+
+import qualified Prelude as P
+
+import Feldspar
+import Feldspar.Compiler
+import Feldspar.Vector
+
+-- This file contains the examples of vector programming
+-- covered in the draft Feldspar Tutorial
+
+type UInt = Data DefaultWord  -- Feldspar usigned int
+
+type VInt = DVector DefaultInt
+
+
+-- some functions for manipulating bits of indices
+-- Remove those that are not used when tutorial is finshed
+
+complN :: Data Index -> Data Index -> Data Index
+complN k = (`xor` oneBitsN k)
+
+oneBitsN :: Data Index -> Data Index
+oneBitsN  = complement . zeroBitsN
+
+zeroBitsN :: Data Index -> Data Index
+zeroBitsN = (allOnes <<) 
+
+allOnes :: Data Index
+allOnes = complement 0
+
+complTo :: Data Index -> Data Index -> Data Index
+complTo k = (`xor` oneBitsTo k)
+
+flipBit ::  Data Index -> Data Index -> Data Index
+flipBit k = (`xor` (1<<k))
+
+bitZero :: Data Index -> Data Index -> Data Bool
+bitZero k i = (i .&. (1<<k)) == 0
+
+bitOne :: Data Index -> Data Index -> Data Bool
+bitOne k i = (i .&. (1<<k)) /= 0
+
+lsbZero :: Data Index -> Data Bool
+lsbZero i = (i .&. 1) == 0
+
+zeroBitsTo :: Data Index -> Data Index
+zeroBitsTo n = (zeroBitsN n) << 1
+
+oneBitsTo :: Data Index -> Data Index
+oneBitsTo = complement . zeroBitsTo
+
+lsbsTo :: Data Index -> Data Index -> Data Index
+lsbsTo k = (.&. oneBitsTo k)
+
+lsbsN :: Data Index -> Data Index -> Data Index
+lsbsN k i = i .&. oneBitsN k
+
+lsb :: Data Index -> Data Index
+lsb = (.&. 1)
+
+-- lsb moves from position 0 to position k. Bits 1 to k shift one bit right
+rotBitFrom0 :: Data Index -> Data Index -> Data Index
+rotBitFrom0 k i = lefts .|. b .|. rights
+  where
+    r1s = complement l1s
+    l1s = zeroBitsTo k  -- k+1 0s on right, rest 1s
+    b = (i .&. 1) << k
+    rights = (i .&. r1s) >> 1
+    lefts = i .&. l1s 
+
+
+
+
+v1 = value [[1,2],[3,4],[5,(6::Int32)]]
+
+func :: Data Int32 -> Data Int32 -> Data Int32 -> Data Bool
+func a b c = a + b == c
+
+
+testParallel :: Data [Index]
+testParallel = parallel 25 (\i -> 50-(2 * i))
+
+setSize :: (Type a, Type b) => Length -> (Vector (Data a) -> Vector (Data b)) ->
+                 Data [a] -> Vector (Data b)
+setSize n f = f . unfreezeVector' n 
+
+
+
+setSize'' :: (Type a1, Type a2, Type a) => Length -> 
+             (Vector (Data a1) -> Vector (Data a2) -> Data a) ->
+            Data [a1] -> Data [a2] -> Data a
+setSize'' n f as bs = f (unfreezeVector' n as) (unfreezeVector' n bs)
+
+
+scalarProduct1 a b = forLoop (min (length a) (length b)) 0 (\ix sum -> sum + a!ix * b!ix)
+
+-- This function is actually built in as scalarProd
+scalarProduct as bs = sum (zipWith (*) as bs)
+
+
+sc = icompile (setSize'' 256 (scalarProduct :: VInt -> VInt -> Data DefaultInt))
+
+
+sc' = icompile (scalarProduct :: VInt -> VInt -> Data DefaultInt)
+
+countUp :: Data Length -> DVector Index
+countUp n = indexed n id
+
+countUp1 :: Data Length -> DVector Index
+countUp1 n = map (+1) (countUp n)
+
+countUpFrom :: Data Index -> Data Length -> DVector Index
+countUpFrom m n = indexed n (+m)
+
+
+
+countDown :: Data Length -> DVector Index
+countDown n = reverse (countUp n)
+
+ex1 = eval (countUp1 6)
+
+ex2 = eval (countDown 6)
+
+
+revmap0 :: DVector Float -> DVector Float
+revmap0 xs = map (+1) (reverse xs)
+
+revmap :: DVector Float -> DVector Float
+revmap = map (+1) . reverse
+
+-- revmap1 :: DVector a -> DVector a     This type is incorrect
+revmap1 :: (Numeric a) => DVector a -> DVector a
+revmap1 = map (+1) . reverse
+
+ex3' = eval (revmap1 (vector [0..5]))    -- Missing type declaration
+
+ex3 = eval (revmap1 (vector [0..5] :: DVector Int32))
+
+ex4 f n = eval (f (vector [0..n] :: VInt))
+
+
+cx1 = icompile (revmap1 :: VInt -> VInt)
+
+cx2 = icompile (setSize 256 (revmap1 :: VInt -> VInt))
+
+
+halveZip :: (Syntactic a) => (a -> a -> c) -> Vector a -> Vector c
+halveZip f as = ms
+  where
+    (ls,rs) = splitAt halfl as
+    ms = zipWith f ls rs
+    l = length as
+    halfl = div l 2
+
+
+
+
+cx3 = icompile (setSize 256 (halveZip min :: VInt -> VInt))
+
+
+
+
+
+
+propUniv2 _ _ = universal
+
+mmin :: (P.Ord a, Type a) => Data a -> Data a -> Data a
+mmin = function2 "min" propUniv2 P.min 
+
+mmax :: (P.Ord a, Type a) => Data a -> Data a -> Data a
+mmax = function2 "max" propUniv2 P.max
+
+cx4 = icompile (setSize 256  (halveZip mmin :: VInt -> VInt))
+
+cx4' = icompile (setSize 255  (halveZip mmin :: VInt -> VInt))
+
+cx4'' = icompile (setSize 256 ((take 3 . halveZip mmin) :: VInt -> VInt))
+
+
+
+
+both :: (Syntactic a) => (a -> a -> c) -> (a -> a -> c) -> Vector a -> Vector c
+both f g as = fs ++ gs
+  where
+    fs = halveZip f as
+    gs = halveZip g as
+
+
+ex5 n = eval $ (both mmin mmax . reverse) (vector [1..n] :: VInt)
+
+cx5 = icompile (setSize 256 (both mmin mmax :: VInt -> VInt))
+
+cx6 = icompile (setSize 256 (mergeSegments . both mmin mmax :: VInt -> VInt))
+
+
+
+premap :: (Data Index -> Data Index) -> Vector a -> Vector a
+premap f (Indexed l ixf Empty) = indexed l (ixf . f)
+
+swapOE1 :: (Syntactic a) => Vector a -> Vector a
+swapOE1 v = indexed (length v) ixf
+  where
+    ixf i = condition (i `mod` 2 == 0) (v!(i+1)) (v!(i-1))
+
+swapOE2 :: Vector a -> Vector a
+swapOE2 = premap (\i -> condition (i `mod` 2 == 0) (i+1)(i-1))
+
+swapOE3 :: Vector a -> Vector a
+swapOE3 = premap (`xor` 1)
+
+
+
+ex6 = eval (swapOE3 (vector [0..15] :: VInt))
+
+ex7 = eval (swapOE3 (vector [1..17] :: VInt))
+
+cx7'   = icompile $ setSize 256 (swapOE1 :: VInt -> VInt)
+
+cx7''  = icompile $ setSize 256 (swapOE2 :: VInt -> VInt)
+
+cx7''' = icompile $ setSize 256 (swapOE3 :: VInt -> VInt)
+
+
+
+selEvenIx :: Vector a -> Vector a
+selEvenIx as = take l (premap (*2) as)
+  where
+    l = (length as + 1) `div` 2
+
+exer1a = eval (selEvenIx (vector [0..16] :: VInt))
+
+
+cexer1 = icompile (setSize 256 (selEvenIx :: VInt -> VInt))
+
+
+rev1 :: Vector a -> Vector a
+rev1 v = premap (\i -> l-1-i) v
+  where
+    l = length v
+
+
+
+
+
+
+ex8 = eval $ map (complN 4)(vector [0..15])
+
+ex9 = eval $ map (complN 2)(vector [0..15])
+
+
+revi :: Data Index -> Vector a -> Vector a
+revi k = premap (complN k)
+
+ex10 = eval (revi 2 (vector [0..15] :: VInt))
+
+ex11 = eval (revi 2 (vector [0..31] :: VInt))
+
+
+
+cx7 = icompile (setSize 256 (revi 4 . map (+1) :: VInt -> VInt))
+
+
+
+ex12 = eval (fold (+) 0 (vector [0..15] :: VInt))
+
+
+
+
+sumEven :: Vector UInt  -> UInt
+sumEven = sum . map keepEven
+  where
+    keepEven i = condition (i `mod` 2 == 0) i 0
+
+exer2a = eval (sumEven (vector [0..31] :: Vector UInt))
+
+cexer2 = icompile sumEven
+
+
+onCond :: Data Bool -> UInt -> UInt
+onCond b m = m .&. (- (b2i b))
+
+isEven i = i .&. 1 == 0
+
+exer2b i = eval (onCond (isEven i) i)
+
+sumEven1 :: Vector UInt  -> UInt
+sumEven1 = sum . map keepEven1
+  where
+    keepEven1 i = onCond (isEven i) i
+
+cexer2a = icompile sumEven1
+
+pipe :: (Syntactic a) => (Data Index -> a -> a) -> Vector (Data Index) -> a -> a
+pipe = flip . fold . flip 
+
+
+
+fact :: UInt -> UInt
+fact i = pipe f (countUp1 i) 1
+  where
+    f i = (* i)
+
+fact1 :: UInt -> UInt
+fact1 i = pipe f (2...i) 1
+  where
+    f i = (* i)
+
+fact2 :: UInt -> UInt
+fact2 i = pipe f (countUpFrom 2 (i-1)) i
+  where
+    f i = (* i)
+
+
+fact3 :: UInt -> UInt
+fact3 i = pipe f (map (+2) (countUp (i-1))) 1
+  where
+    f i = (* i)
+
+
+fact4 :: UInt -> UInt
+fact4 i = fold1 (*) (countUp1 i)
+
+
+ex13' = eval (fact 5)
+
+
+
+cx8 = icompile fact
+
+cx8' = icompile fact1
+
+cx8'' = icompile fact2
+
+
+
+bitr :: Data Index -> Data Index -> Data Index
+bitr n i = snd (pipe stage (countUp n) (i, i >> n))
+  where
+    stage _ (i,r) = (i>>1, (i .&. 1) .|. (r<<1))
+
+bitRev :: Data Index -> Vector a -> Vector a
+bitRev n = premap (bitr n)
+
+cx9 = icompile (bitRev :: Data Index -> VInt -> VInt)
+
+ex13''  = eval (bitRev 8 (vector [0..255] :: VInt))
+ex13''' = eval (bitRevLog 3 (vector [0..255] :: VInt))
+ex13''''= eval (bitRevH 8 (vector [0..255] :: VInt))
+
+
+mergeBy :: Data Index -> Data Index -> Data Index -> Data Index
+mergeBy m a b = (a .&. m) .|. (b .&. complement m)
+
+
+-- if you know that the number of bits to be reversed is a power
+-- of two, you can do this nice trick
+-- swap adjacent bits, then swap pairs of bits etc.
+-- The number of bits to be reversed is 2^n
+bitrLog :: Data Index -> Data Index -> Data Index
+bitrLog n i = snd (pipe stage (map (1<<) (countDown n))  (allOnes, i))
+  where
+    stage s (mask, v) = (mask', mergeBy mask' (v>>s) (v<<s))
+      where
+        mask' = (mask `xor` (mask << s)) .|. zeroBitsN (1 << n)
+
+bitRevLog :: Data Index -> Vector a -> Vector a
+bitRevLog n = premap (bitrLog n)
+
+cx10 = icompile (bitRevLog :: Data Index -> VInt -> VInt)
+
+
+composeN :: Index -> (a -> a) -> a -> a
+composeN 0 f = id
+composeN n f = (composeN (n-1) f) . f
+
+
+
+
+-- Make this one an exercise!
+composeList :: [ a -> a ] -> a -> a
+composeList [] = id
+composeList (f:fs) = composeList fs . f
+
+
+-- same as bitr but now n is a Haskell level value
+bitrH n i = snd (composeN n stage (i, i >> vn))
+  where
+    stage (i,r) = (i>>1, (i .&. 1) .|. (r<<1))
+    vn = value n
+
+
+bitRevH :: Index -> Vector a -> Vector a
+bitRevH n = premap (bitrH n)
+
+cx11 = icompile (bitRevH 8 :: VInt -> VInt)
+
+
+
+bitrLogH :: Index -> Data Index -> Data Index
+bitrLogH n i = snd (composeList fns (allOnes, i))
+  where
+    fns = [stage (1 << (value ix)) | ix <- P.reverse [0..n-1]]
+    stage s (mask, v) = (mask', mergeBy mask' (v>>s) (v<<s))
+      where
+        mask' = (mask `xor` (mask << s)) .|. zeroBitsN (1 << (value n))
+
+bitRevLogH :: Index -> Vector a -> Vector a
+bitRevLogH n = premap (bitrLogH n)
+
+cx12 = icompile (bitRevLogH 4 :: VInt -> VInt)
+
+
+
+
+
+comb :: (Syntactic a) =>
+        (t -> t -> a) -> (t -> t -> a)
+         -> (Data Index -> Data Bool) -> (Data Index -> Data Index)
+         -> Vector t 
+         -> Vector a
+comb f g c p (Indexed l ixf Empty) = indexed l ixf'
+  where
+    ixf' i = condition (c i) (f a b) (g a b)
+      where
+        a = ixf i
+        b = ixf (p i)
+
+apart :: (Syntactic a) =>
+         (t -> t -> a) -> (t -> t -> a)
+         -> Data Index
+         -> Vector t
+         -> Vector a
+apart f g k = comb f g (bitZero k) (flipBit k)
+
+
+ex13 k = eval (apart mmin mmax k (vector [7,6,5,4,3,2,1,0] :: VInt))
+
+ex14 = [ ex13 (value i) | i <- [0..2] ]
+
+
+batMerge :: (P.Ord a, Type a) => Data Index -> DVector a -> DVector a
+batMerge n = pipe (apart mmin mmax) (countDown n)
+
+halfRev :: (Type a) => Data Index -> DVector a -> DVector a
+halfRev n = premap (\i -> (condition (bitZero n' i) i (complN n' i)))
+  where
+    n' = n-1
+
+-- works on 2^n length sub-arrays
+-- works on 2^n length sub-arrays
+halfRev1 :: (Type a) => Data Index -> DVector a -> DVector a
+halfRev1 n  = premap (\i -> i `xor`  (onCond (bitOne n' i) (oneBitsN n')))
+  where
+    n' = n-1
+
+ex15 = [eval (halfRev1 (value k) (vector [0..15] :: VInt)) | k <- [1..4]]
+
+
+
+merge :: (P.Ord a, Type a) => Data Index -> DVector a -> DVector a
+merge n = batMerge n . halfRev1 n
+
+sortV :: (P.Ord a, Type a) => Data Index -> DVector a -> DVector a
+sortV n = pipe merge (countUp1 n)
+
+ex16 k = eval (sortV k (vector [0,1,2,3,12,5,6,7,1,14,13,12,11,19,9,8] :: VInt))
+
+
+cx13 = icompile (sortV :: Data Index -> VInt -> VInt)
+
+
+
+-- sorter on each 2^n length sub-array of inputs, n > 0
+-- inside the merger, one loop body is unwound to permit fusion with halfRev1
+sort1 :: (P.Ord a, Type a) => Data Index -> DVector a -> DVector a
+sort1 n = pipe merge (countUp1 n)
+  where
+    merge n = batMerge (n-1) . apart mmin mmax (n-1) . halfRev1 n
+
+cx13' = icompile (sort1 :: Data Index -> VInt -> VInt)
+
+
+fex = apart mmin mmax 0 . apart mmin mmax 1 . apart mmin mmax 2
+
+cx14 = icompile (setSize 256 (fex :: VInt -> VInt))
+
+
+fexforce :: (P.Ord a, Type a) => DVector a -> DVector a
+fexforce = apart mmin mmax 0 . force . 
+           apart mmin mmax 1 . force . 
+           apart mmin mmax 2
+
+cx15 = icompile (setSize 256 (fexforce :: VInt -> VInt))
+
+
+fir1 :: Data Float -> Data Float -> DVector Float -> DVector Float
+fir1 a0 a1 vec = map (\(x,y) -> a0*x + a1*y) $ zip vec (tail vec)
+
+lowPass :: Data Float -> DVector Float -> DVector Float
+lowPass x = fir1 x (1-x)
+
+highPass :: Data Float -> DVector Float -> DVector Float
+highPass x = fir1 x (x-1)
+
+bandPass1 :: Data Float -> DVector Float -> DVector Float
+bandPass1 x = highPass x . lowPass x
+
+bandPass2 :: Data Float -> DVector Float -> DVector Float
+bandPass2 x = highPass x . force . lowPass x
+
+
+cx16 = icompile (setSize 256 (lowPass  0.5))
+
+cx17 = icompile (setSize 256 (highPass 0.5))
+
+cx18 = icompile (setSize 256 (bandPass1 0.5))
+
+cx19 = icompile (setSize 256 (bandPass2 0.5))
+
+
+
+
+
+riffle :: Data Index -> Vector a -> Vector a
+riffle k = premap (rotBitFrom0 k)
+
+bitRev1 :: Type a => Data Index -> Vector (Data a) -> Vector (Data a)
+bitRev1 n = pipe riffle (countUp1 n)
+
+
+
+ex17 = eval (riffle 3 (countUp 16))
+
+cx20 = icompile (bitRev1 :: Data Index -> VInt -> VInt)
+
+
+
+combx f g c p x (Indexed l ixf Empty) =  indexed l ixf'
+      where
+        ixf' i = condition (c i) (f ai pi xi) (g pi ai xi)
+          where
+            ai = ixf i
+            pi = ixf (p i)
+            xi = x i
+
+
+pows2 :: Data Length -> DVector Index
+pows2 k = indexed k (1<<)
+
+-- 2^l input FFT. Applies to sub-parts of input vector
+-- of length 2^l. Produces each of the results in bit reversed order.
+-- There is currently no check that the input vector is at least of length 2^l
+fft :: Data Index ->  DVector (Complex Float) -> DVector (Complex Float) 
+fft l = pipe stage (countDown l)
+  where
+    stage k = combx f g (bitZero k) (`xor` p)  twid
+      where
+        p = 1<<k
+        f a b _ = a + b
+        g a b t = t * (a-b)
+        twid i  = cis (-pi*(i2f (lsbsN k i)) / i2f p)
+
+
+
+ex18' = eval ((bitRev 3 . fft 3) (testseq1 3))
+
+
+
+
+-- 2^l input IFFT. Produces output in bit reversed order.
+ifft :: Data Index ->  DVector (Complex Float) -> DVector (Complex Float) 
+ifft l = map (/ (complex (i2f (2^l)) 0)) . pipe stage (countDown l)
+  where
+    stage k = combx f g (bitZero k) (`xor` p)  twid
+      where
+        p = 1<<k
+        f a b _ = a + b
+        g a b t = t * (a-b)
+        twid i  = cis (pi*(i2f (lsbsN k i)) / i2f p)
+
+
+
+
+
+cx21 = icompile fft
+
+testseq :: Data DefaultWord -> DVector (Complex Float)
+testseq n = mergeSegments (seq ++ reverse seq)
+                    where seq = (indexed (2 ^ (n - 1)) (\i -> complex (i2f i) 0 ))
+
+testseq1 :: Data DefaultWord -> DVector (Complex Float)
+testseq1 n = indexed (2^n) (\i -> complex (i2f i) 0 )
+
+
+ex18 k = eval ((bitRev k . ifft k  . bitRev k . fft k) (testseq k) :: DVector (Complex Float) )
+
+
+
+
+
+
+
+
+ Examples/Tutorial/Vector.hs view
@@ -0,0 +1,137 @@+module Vector where++import qualified Prelude+import Feldspar+import Feldspar.Vector+import Feldspar.Matrix++-- Blake crypto++type MessageBlock = DVector Word32 -- 0..15+type Round = Data Index++type State = Matrix Word32 -- 0..3 0..3++co :: DVector Word32+co = vector [0x243F6A88,0x85A308D3,0x13198A2E,0x03707344,+             0xA4093822,0x299F31D0,0x082EFA98,0xEC4E6C89,+	     0x452821E6,0x38D01377,0xBE5466CF,0x34E90C6C,+	     0xC0AC29B7,0xC97C50DD,0x3F84D5B5,0xB5470917]++sigma :: Matrix Index+sigma = matrix+      [[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15]+      ,[14,10,4,8,9,15,13,6,1,12,0,2,11,7,5,3]+      ,[11,8,12,0,5,2,15,13,10,14,3,6,7,1,9,4]+      ,[7,9,3,1,13,12,11,14,2,6,5,10,4,0,15,8]+      ,[9,0,5,7,2,4,10,15,14,1,11,12,6,8,3,13]+      ,[2,12,6,10,0,11,8,3,4,13,7,5,15,14,1,9]+      ,[12,5,1,15,14,13,4,10,0,7,6,3,9,2,8,11]+      ,[13,11,7,14,12,1,3,9,5,0,15,4,8,6,2,10]+      ,[6,15,14,9,11,3,0,8,12,2,13,7,1,4,10,5]+      ,[10,2,8,4,7,6,1,5,15,11,9,14,3,12,13,0]+      ]++blakeRound :: MessageBlock -> State -> Round -> State+blakeRound m state r = +  invDiagonals $+  zipWith (g m r) (4 ... 7) $+  diagonals $+  transpose $+  zipWith (g m r) (0 ... 3) $+  transpose $+  state++g :: MessageBlock -> Round -> Data Index -> DVector Word32 -> DVector Word32+g m r i v = fromList [a'',b'',c'',d'']+  where [a,b,c,d] = toList 4 v+        a'  = a + b + (m!(sigma!r!(2*i)) ⊕ (co!(sigma!r!(2*i+1))))+	d'  = (d ⊕ a') >> 16+	c'  = c + d'+	b'  = (b ⊕ c') >> 12+	a'' = a' + b' + (m!(sigma!r!(2*i+1)) ⊕ (co!(sigma!r!(2*i))))+	d'' = (d' ⊕ a'') >> 8+	c'' = c' + d''+	b'' = (b' ⊕ c'') >> 7++diagonals :: Type a => Matrix a -> Matrix a+diagonals m = map (diag m) (0 ... (length (head m) - 1))++diag :: Type a => Matrix a -> Data Index -> Vector (Data a)+diag m i = zipWith lookup m (i ... (l + i))+  where l = length m - 1+        lookup v i = v ! (i `mod` length v)++invDiagonals :: Type a => Matrix a -> Matrix a+invDiagonals m = zipWith shiftVectorR (0 ... (length m - 1)) (transpose m)++shiftVectorR :: Syntactic a => Data Index -> Vector a -> Vector a+shiftVectorR i v = reverse $ drop i rev ++ take i rev+  where rev = reverse v++fromList :: Type a => [Data a] -> DVector a+fromList ls = unfreezeVector (loop 1 (parallel (value len) (const (Prelude.head ls))))+  where loop i arr +            | i Prelude.< len +                = loop (i+1) (setIx arr (value i) (ls !! (fromIntegral i)))+            | otherwise = arr+        len  = fromIntegral (Prelude.length ls)++toList :: Type a => Index -> Vector (Data a) -> [Data a]+toList n v@(Indexed l ix _) = Prelude.map (v!) $ Prelude.map value [0..n-1]++-- DCT++-- Discrete Cosine Transform type 2 +dct2 :: (DVector Float) -> (DVector Float)+dct2 xn = mat *** xn+    where+      mat = indexedMat (length xn) (length xn) (\k l -> dct2nkl (length xn) k l)+      ++-- Helper function defining all the values in the DCT-2n matrix+dct2nkl :: Data Length -> Data DefaultWord -> Data DefaultWord -> Data Float+dct2nkl n k l = cos ( (k' *(2*l' +1)*pi)/(2*n') )+  where +    n' = i2f n+    k' = i2f k+    l' = i2f l++-- Discrete Cosine Transform type 3 +dct3 :: (DVector Float) -> (DVector Float)+dct3 xn = mat *** xn+    where+      mat = transpose $ indexedMat (length xn) (length xn) (\k l -> dct2nkl (length xn) k l)++-- Discrete Cosine Transform type 4 +dct4 :: (DVector Float) -> (DVector Float)+dct4 xn = mat *** xn+    where+      mat = indexedMat (length xn) (length xn) (\k l -> dct4nkl (length xn) k l)+      ++-- Helper function defining all the values in the DCT-4n matrix+dct4nkl :: Data Length -> Data DefaultWord -> Data DefaultWord -> Data Float+dct4nkl n k l = cos ( ((2*k' +1)*(2*l' +1)*pi)/(4*n') )+  where +    n' = i2f n+    k' = i2f k+    l' = i2f l++-- Low-pass filter++fft = error "No FFT yet"+ifft = fft++lowPassCore :: (Numeric a) => Data Index -> DVector a -> DVector a+lowPassCore k v = take k v ++ replicate (length v - k) 0++lowPass :: Data Index -> DVector Float -> DVector Float+lowPass k = frequencyTrans (lowPassCore k)++frequencyTrans :: (DVector (Complex Float) -> DVector (Complex Float)) +               -> DVector Float +               -> DVector Float+frequencyTrans innerFunction v = map realPart $ ifft+                                 $ innerFunction+                                 $ fft $ map (\a -> complex a 0) v
Feldspar.hs view
@@ -1,49 +1,17 @@------ Copyright (c) 2009-2010, ERICSSON AB All rights reserved.--- --- Redistribution and use in source and binary forms, with or without--- modification, are permitted provided that the following conditions are met:--- ---     * Redistributions of source code must retain the above copyright notice,---       this list of conditions and the following disclaimer.---     * 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 name of the ERICSSON AB nor the names of its contributors---       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 AND CONTRIBUTORS "AS IS"--- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE--- IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE--- ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS--- BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,--- OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF--- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS--- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN--- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)--- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF--- THE POSSIBILITY OF SUCH DAMAGE.------- | Interface to the Feldspar language.+-- | Interface to the essential parts of the Feldspar language. High-level+-- libraries have to be imported separately.  module Feldspar   ( module Feldspar.Prelude   , module Feldspar.Core-  , module Feldspar.Vector-  , module Feldspar.Matrix-  , module Feldspar.FixedPoint   ) where    import qualified Prelude-  -- In order to be able to play with the Feldspar module in GHCi without-  -- getting name clashes.+  -- In order to be able to use the Feldspar module in GHCi without getting name+  -- clashes.  import Feldspar.Prelude import Feldspar.Core-import Feldspar.Vector-import Feldspar.Matrix-import Feldspar.FixedPoint+
Feldspar/Core.hs view
@@ -1,85 +1,82 @@------ Copyright (c) 2009-2010, ERICSSON AB All rights reserved.--- --- Redistribution and use in source and binary forms, with or without--- modification, are permitted provided that the following conditions are met:--- ---     * Redistributions of source code must retain the above copyright notice,---       this list of conditions and the following disclaimer.---     * 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 name of the ERICSSON AB nor the names of its contributors---       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 AND CONTRIBUTORS "AS IS"--- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE--- IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE--- ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS--- BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,--- OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF--- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS--- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN--- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)--- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF--- THE POSSIBILITY OF SUCH DAMAGE.------- | The user interface of the core language+-- | The Feldspar core language  module Feldspar.Core-  ( Range (..)-  , (:>) (..)-  , Set (..)-  , Length-  , Unsigned32-  , Signed32-  , Unsigned16-  , Signed16-  , Unsigned8-  , Signed8-  , Storable-  , Size-  , Data-  , dataSize-  , Computable-  , Internal-  , eval-  , value-  , array-  , arrayLen-  , unit-  , true-  , false-  , size-  , cap-  , function-  , function2-  , function3-  , function4-  , getIx-  , setIx-  , RandomAccess (..)-  , noInline-  , ifThenElse-  , while-  , parallel-  , Program-  , showCore-  , showCoreWithSize-  , printCore-  , printCoreWithSize-  , module Feldspar.Core.Functions-  , trace-  ) where+    (+      -- * Reexported standard modules+      Complex (..)+    , module Data.Int+    , module Data.Word +      -- * DSL library+    , Role+    , Internal+    , Info +      -- * Feldspar types+    , module Feldspar.Set+    , Range (..)+    , (:>) (..)+    , DefaultWord (..)+    , DefaultInt (..)+    , Length+    , Index+    , Type+    , Size+    , fullProp +      -- * Core constructs+    , EdgeSize (..)+    , Data+    , Syntactic+    , dataSize+    , resizeData+    , force+    , eval+    , viewLiteral+    , drawExpr+    , drawExpr2++    , value+    , unit+    , true+    , false+    , array+    , cap+    , function+    , function1+    , function2+    , condition+    , (?)+    , ifThenElse+    , parallel''+    , parallel'+    , parallel+    , forLoop+    , sequential+    , noinline+    , noinline2+    , setLength++    -- * Functions+    , module Feldspar.Core.Functions++    -- * Wrapping+    , module Feldspar.Core.Wrap+    ) where++++import Prelude ()+import Data.Complex+import Data.Int hiding (Int)+import Data.Word++import Feldspar.DSL.Network+import Feldspar.Set import Feldspar.Range import Feldspar.Core.Types-import Feldspar.Core.Expr-import Feldspar.Core.Reify+import Feldspar.Core.Representation+import Feldspar.Core.Constructs import Feldspar.Core.Functions-import Feldspar.Core.Trace+import Feldspar.Core.Wrap 
+ Feldspar/Core/Constructs.hs view
@@ -0,0 +1,245 @@+module Feldspar.Core.Constructs where++++import Data.List+import Data.Typeable++import Feldspar.DSL.Expression+import Feldspar.DSL.Lambda+import Feldspar.DSL.Network+import Feldspar.Set+import Feldspar.Range+import Feldspar.Core.Types+import Feldspar.Core.Representation++++value' :: Type a => Size a -> a -> Data a+value' sz a = nodeData (sz \/ sizeOf a) (Inject $ Node $ Literal a)++-- | A program that computes a constant value+value :: Type a => a -> Data a+value = value' empty++unit :: Data ()+unit = value ()++true :: Data Bool+true = value True++false :: Data Bool+false = value False++-- | Like 'value' but with an extra 'Size' argument that can be used to increase+-- the size beyond the given data.+--+-- Example 1:+--+-- > array (10 :> 20 :> universal) [] :: Data [[DefaultInt]]+--+-- gives an uninitialized 10x20 array of 'DefaultInt' elements.+--+-- Example 2:+--+-- > array (10 :> 20 :> universal) [[1,2,3]] :: Data [[DefaultInt]]+--+-- gives a 10x20 array whose first row is initialized to @[1,2,3]@.+array :: Type a => Size a -> a -> Data a+array = value'++cap :: Type a => Size a -> Data a -> Data a+cap sz a = resizeData (sz /\ dataSize a) a++function :: (Syntactic a, Type b)+    => Bool+    -> String+    -> (Info a     -> Size b)+    -> (Internal a -> b)+    -> (a          -> Data b)+function doConstProp fun sizeProp f a = case viewLiteral a of+    Just a' | doConstProp -> value (f a')+    _                     -> func+  where+    sz   = sizeProp (edgeInfo a)+    func = nodeData sz $ Inject (Node (Function fun f)) :$: toEdge a++function1 :: (Type a, Type b)+    => String+    -> (Size a -> Size b)+    -> (a      -> b)+    -> (Data a -> Data b)+function1 fun sizeProp = function True fun (sizeProp . edgeSize)++function2 :: (Type a, Type b, Type c)+    => String+    -> (Size a -> Size b -> Size c)+    -> (a      -> b      -> c)+    -> (Data a -> Data b -> Data c)+function2 fun sizeProp f = curry $ function True fun sizeProp' (uncurry f)+  where+    sizeProp' (i1,i2) = sizeProp (edgeSize i1) (edgeSize i2)++condition :: Syntactic a+    => Data Bool  -- ^ Condition+    -> a          -- ^ \"Then\" branch+    -> a          -- ^ \"Else\" branch+    -> a+condition cond t e+    | toEdge t == toEdge e           = t  -- TODO This check might be expensive+    | Just True  <- viewLiteral cond = t+    | Just False <- viewLiteral cond = e+    | otherwise+         =  fromOutEdge info+         $  Inject (Node Condition)+        :$: toEdge cond+        :$: toEdge t+        :$: toEdge e+  where+    info = edgeInfo t \/ edgeInfo e++(?) :: Syntactic a+    => Data Bool  -- ^ Condition+    -> (a,a)      -- ^ Alternatives+    -> a+cond ? (t,e) = condition cond t e++infix 1 ?++-- | Identical to 'condition'. Provided for backwards-compatibility, but will be+-- removed in the future.+ifThenElse :: Syntactic a+    => Data Bool  -- ^ Condition+    -> a          -- ^ \"Then\" branch+    -> a          -- ^ \"Else\" branch+    -> a+ifThenElse = condition+{-# DEPRECATED ifThenElse "Please use `condition` or `(?)` instead." #-}++viewGetIx :: Typeable a => Data Index -> Data a -> Maybe (Data [a])+viewGetIx (Data i) (Data a) = case undoEdge a of+    Inject (Node (Function "(!)" _)) :$: (Inject Group2 :$: as :$: i')+        | exprEq i i' -> Data `fmap` exprCast as+    _ -> Nothing++-- | Parallel array with continuation+parallel'' :: Type a =>+    Bool -> Data Length -> (Data Index -> Data a) -> Data [a] -> Data [a]+parallel'' optimize l ixf cont | l == value 0 = cont+parallel'' optimize l ixf cont = case viewGetIx ix body of+    Just arr | optimize, cont == value [] -> setLength l arr+    _+        ->  nodeData szPar+         $  Inject (Node Parallel)+        :$: toEdge l+        :$: lambda (EdgeSize szi) ixf+        :$: toEdge cont+  where+    szl1         = dataSize l+    szi          = rangeByRange 0 (szl1-1)+    ix           = variable (EdgeSize szi) "TODO"+    body         = ixf ix+    sza          = dataSize body+    szl2 :> sza' = dataSize cont+    szPar        = (szl1+szl2) :> (sza \/ sza')+  -- TODO The optimize argument is a hack to work around a problem with having+  --      literals (and other things) as continuations. This is only a problem+  --      if the parallel is a continuation of another parallel or sequential.+  --      If the parallel is the first segment, enabling optimization should be+  --      fine.++-- | Parallel array with continuation+parallel' :: Type a =>+    Data Length -> (Data Index -> Data a) -> Data [a] -> Data [a]+parallel' = parallel'' True++-- | Parallel array+--+-- Since there are no dependencies between the elements, the compiler is free to+-- compute the elements in any order, or even in parallel.+parallel :: Type a+    => Data Length  -- ^ Length of resulting array (outermost level)+    -> (Data Index -> Data a)+                    -- ^ Function that maps each index in the range @[0 .. l-1]@+                    -- to its element+    -> Data [a]+parallel l ixf = parallel' l ixf (value [])++-- | For loop+forLoop :: Syntactic st+    => Data Length  -- ^ Number of iterations+    -> st           -- ^ Initial state+    -> (Data Index -> st -> st)+                    -- ^ Loop body (current index and state to next state)+    -> st           -- ^ Final state+forLoop l init body | l == value 0 = init+forLoop l init body | l == value 1 = body (value 0) init+forLoop l init body+     =  fromOutEdge szst+     $  Inject (Node ForLoop)+    :$: toEdge l+    :$: toEdge init+    :$: Lambda (\i -> lambda szst $ body $ nodeData szi i)+  where+    szi      = rangeByRange 0 (dataSize l)+    szinit   = edgeInfo init+    fn _ sz  = edgeInfo $ body (variable (EdgeSize szi) "ix")+                               (variable sz  "st")+    (szst,_) = indexedFixedPoint (cutOffAt 3 fn) szinit++sequential :: (Type a, Syntactic st)+    => Data Length+    -> st                -- ^ Initial state+    -> (Data Index -> st -> (Data a,st))+                         -- ^ Current loop index and current state to current element+                         -- and next state+    -> (st -> Data [a])  -- ^ Continuation+    -> Data [a]+sequential l init step cont+     =  nodeData szSeq+     $  Inject (Node Sequential)+    :$: toEdge l+    :$: toEdge init+    :$: Lambda (\i -> lambda universal $ step $ nodeData szi i)+    :$: lambda universal cont+  where+    szl1      = dataSize l+    -- szl2 :> _ = dataSize cont+    -- TODO cont needs an argument+    szl2      = universal+    szi       = rangeByRange 0 (szl1-1)+    szSeq     = (szl1+szl2) :> universal  -- TODO Improve++-- | Prevent a function from being inlined+noinline :: (Syntactic a, Syntactic b) => String -> (a -> b) -> (a -> b)+noinline name body a+     =  fromOutEdge szb+     $  Inject (Node (NoInline name))+    :$: lambda sza body+    :$: toEdge a+  where+     sza = getInfo a+     szb = getInfo $ body a++noinline2 :: (Syntactic a, Syntactic b, Syntactic c) =>+    String -> (a -> b -> c) -> (a -> b -> c)+noinline2 name = curry . noinline name . uncurry++setLength :: Type a => Data Length -> Data [a] -> Data [a]+setLength l arr = case (undoEdge (unData l), undoEdge (unData arr)) of+    (Inject (Node (Function "length" _)) :$: a, _)+        | Just b <- exprCast a, b == unData arr -> Data b+    (Inject (Node (Literal n)), Inject (Node (Literal as))) ->+        nodeData (szLen :> szArrElem) $+            Inject $ Node $ Literal $ genericTake n as+    (_, Inject (Node Parallel) :$: _ :$: ixf :$: cont)+        | cont == unData (value []) -> nodeData (szLen :> szArrElem) $+            Inject (Node Parallel) :$: unData l :$: ixf :$: cont+    _ -> nodeData (szLen :> szArrElem) $+        Inject (Node SetLength) :$: toEdge l :$: toEdge arr+  where+    szl                   = dataSize l+    szArrLen :> szArrElem = dataSize arr+    szLen                 = rangeMin szl szArrLen+  -- The only purpose of this function is to enable optimization of 'parallel'.+
− Feldspar/Core/Expr.hs
@@ -1,641 +0,0 @@------ Copyright (c) 2009-2010, ERICSSON AB All rights reserved.--- --- Redistribution and use in source and binary forms, with or without--- modification, are permitted provided that the following conditions are met:--- ---     * Redistributions of source code must retain the above copyright notice,---       this list of conditions and the following disclaimer.---     * 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 name of the ERICSSON AB nor the names of its contributors---       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 AND CONTRIBUTORS "AS IS"--- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE--- IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE--- ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS--- BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,--- OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF--- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS--- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN--- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)--- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF--- THE POSSIBILITY OF SUCH DAMAGE.-----{-# LANGUAGE UndecidableInstances #-}---- | This module gives a representation core programs as typed expressions (see--- 'Expr' / 'Data').--module Feldspar.Core.Expr where----import Data.Function-import Data.Monoid-import Data.Unique--import Feldspar.Range-import Feldspar.Core.Types-import Feldspar.Core.Ref------ | Typed core language expressions. A value of type @`Expr` a@ is a--- representation of a program that computes a value of type @a@.-data Expr a-  where-    Val         :: a -> Expr a  -- XXX Temporary, only used by evalF-    Variable    :: Expr a  -- XXX Risky to rely on obs. sharing for bound variables.-    Value       :: Storable a => a -> Expr a-    Function    :: String -> (a -> b) -> Expr (a -> b)-    Application :: Expr (a -> b) -> Data a -> Expr b-    NoInline    :: String -> Ref (a :-> b) -> (Data a -> Expr b)--    IfThenElse-      :: Data Bool           -- Condition-      -> (a :-> b)           -- If branch-      -> (a :-> b)           -- Else branch-      -> (Data a -> Expr b)--    While-      :: (a :-> Bool)  -- Continue?-      -> (a :-> a)     -- Body-      -> Data a        -- Initial state-      -> Expr a        -- Final state--    Parallel-      :: Storable a-      => Data Length-      -> (Int :-> a)  -- Index mapping-      -> Expr [a]     -- Result vector------ | A wrapper around 'Expr' to allow observable sharing (see--- "Feldspar.Core.Ref") and for memoizing size information.-data Data a = Typeable a => Data-  { dataSize :: Size a-  , dataRef  :: Ref (Expr a)-  }--instance Eq (Data a)-  where-    (==) = (==) `on` dataRef--instance Ord (Data a)-  where-    compare = compare `on` dataRef--data a :-> b = Typeable a =>  -- Typeable needed by evalF-    Lambda (Data a -> Data b) (Data a) (Data b)----dataType :: forall a . Data a -> Tuple StorableType-dataType a@(Data _ _) = typeOf (dataSize a) (T::T a)--dataId :: Data a -> Unique-dataId = refId . dataRef--dataToExpr :: Data a -> Expr a-dataToExpr = deref . dataRef--{-# NOINLINE exprToData #-}-exprToData :: Typeable a => Size a -> Expr a -> Data a-exprToData sz a = Data sz (ref a)--{-# NOINLINE freshVar #-}-freshVar :: Typeable a => Size a -> Data a-freshVar sz = exprToData sz Variable--{-# NOINLINE lambda #-}-lambda :: Typeable a => Size a -> (Data a -> Data b) -> (a :-> b)-lambda sz f = Lambda f var (f var)-  where-    var = freshVar sz-  -- XXX It's assumed that `f` is only going to be applied to an argument whose-  --     size is `sz`.--apply :: (a :-> b) -> Data a -> Data b-apply (Lambda f _ _) = f--resultSize :: (a :-> b) -> Size b-resultSize (Lambda _ _ outp) = dataSize outp----(|$|) :: Expr (a -> b) -> Data a -> Expr b-f |$| a = Application f a---- XXX Document these constructors. Currently, only _function is used for--- ordinary functions. _function2 etc. are only used to construct tuples.-_function-    :: Typeable b-    => String -> (Size a -> Size b) -> (a -> b) -> (Data a -> Data b)-_function fun sizeProp f a = exprToData sz $ Function fun f |$| a-  where-    sz = sizeProp (dataSize a)--_function2-    :: Typeable c-    => String-    -> (Size a -> Size b -> Size c)-    -> (a -> b -> c)-    -> (Data a -> Data b -> Data c)-_function2 fun sizeProp f a b = exprToData sz $ Function fun f |$| a |$| b-  where-    sz = sizeProp (dataSize a) (dataSize b)--_function3-    :: Typeable d-    => String -> (Size a -> Size b -> Size c -> Size d)-    -> (a -> b -> c -> d)-    -> (Data a -> Data b -> Data c -> Data d)-_function3 fun sizeProp f a b c =-    exprToData sz $ Function fun f |$| a |$| b |$| c-  where-    sz = sizeProp (dataSize a) (dataSize b) (dataSize c)--_function4-    :: Typeable e-    => String-    -> (Size a -> Size b -> Size c -> Size d -> Size e)-    -> (a -> b -> c -> d -> e)-    -> (Data a -> Data b -> Data c -> Data d -> Data e)-_function4 fun sizeProp f a b c d =-    exprToData sz $ Function fun f |$| a |$| b |$| c |$| d-  where-    sz = sizeProp (dataSize a) (dataSize b) (dataSize c) (dataSize d)----tup2 :: (Typeable a, Typeable b) => Data a -> Data b -> Data (a,b)-tup2 = _function2 "tup2" (,) (,)--tup3 :: (Typeable a, Typeable b, Typeable c) =>-    Data a -> Data b -> Data c -> Data (a,b,c)-tup3 = _function3 "tup3" (,,) (,,)--tup4 :: (Typeable a, Typeable b, Typeable c, Typeable d) =>-    Data a -> Data b -> Data c -> Data d -> Data (a,b,c,d)-tup4 = _function4 "tup4" (,,,) (,,,)--get21 :: Typeable a => Data (a,b) -> Data a-get21 = _function "getTup21" get get-  where-    get (a,b) = a--get22 :: Typeable b => Data (a,b) -> Data b-get22 = _function "getTup22" get get-  where-    get (a,b) = b--get31 :: Typeable a => Data (a,b,c) -> Data a-get31 = _function "getTup31" get get-  where-    get (a,b,c) = a--get32 :: Typeable b => Data (a,b,c) -> Data b-get32 = _function "getTup32" get get-  where-    get (a,b,c) = b--get33 :: Typeable c => Data (a,b,c) -> Data c-get33 = _function "getTup33" get get-  where-    get (a,b,c) = c--get41 :: Typeable a => Data (a,b,c,d) -> Data a-get41 = _function "getTup41" get get-  where-    get (a,b,c,d) = a--get42 :: Typeable b => Data (a,b,c,d) -> Data b-get42 = _function "getTup42" get get-  where-    get (a,b,c,d) = b--get43 :: Typeable c => Data (a,b,c,d) -> Data c-get43 = _function "getTup43" get get-  where-    get (a,b,c,d) = c--get44 :: Typeable d => Data (a,b,c,d) -> Data d-get44 = _function "getTup44" get get-  where-    get (a,b,c,d) = d------ | Computable types. A computable value completely represents a core program,--- in such a way that @`internalize` `.` `externalize`@ preserves semantics, but--- not necessarily syntax.------ The terminology used in this class comes from thinking of the 'Data' type as--- the \"internal\" core language and the "Feldspar.Core" API as the--- \"external\" core language.-class Typeable (Internal a) => Computable a-  where-    -- | @`Data` (`Internal` a)@ is the internal representation of the type @a@.-    type Internal a--    -- | Convert to internal representation-    internalize :: a -> Data (Internal a)--    -- | Convert to external representation-    externalize :: Data (Internal a) -> a--instance Storable a => Computable (Data a)-  where-    type Internal (Data a) = a--    internalize = id-    externalize = id--instance (Computable a, Computable b) => Computable (a,b)-  where-    type Internal (a,b) = (Internal a, Internal b)--    internalize (a,b) = tup2 (internalize a) (internalize b)--    externalize ab =-        ( externalize (get21 ab)-        , externalize (get22 ab)-        )--instance (Computable a, Computable b, Computable c) => Computable (a,b,c)-  where-    type Internal (a,b,c) = (Internal a, Internal b, Internal c)--    internalize (a,b,c) = tup3-      (internalize a)-      (internalize b)-      (internalize c)--    externalize abc =-        ( externalize (get31 abc)-        , externalize (get32 abc)-        , externalize (get33 abc)-        )--instance-    ( Computable a-    , Computable b-    , Computable c-    , Computable d-    ) =>-      Computable (a,b,c,d)-  where-    type Internal (a,b,c,d) = (Internal a, Internal b, Internal c, Internal d)--    internalize (a,b,c,d) = tup4-      (internalize a)-      (internalize b)-      (internalize c)-      (internalize d)--    externalize abcd =-        ( externalize (get41 abcd)-        , externalize (get42 abcd)-        , externalize (get43 abcd)-        , externalize (get44 abcd)-        )------ | Lower a function to operate on internal representation.-lowerFun :: (Computable a, Computable b) =>-    (a -> b) -> (Data (Internal a) -> Data (Internal b))-lowerFun f = internalize . f . externalize---- | Lift a function to operate on external representation.-liftFun :: (Computable a, Computable b) =>-    (Data (Internal a) -> Data (Internal b)) -> (a -> b)-liftFun f = externalize . f . internalize------ | The semantics of expressions-evalE :: Expr a -> a--evalE (Val a)           = a-evalE Variable          = error "evaluating free variable"-evalE (Value a)         = a-evalE (Function _ f)    = f-evalE (Application f a) = evalE f (evalD a)-evalE (NoInline _ f a)  = evalD (apply (deref f) a)--evalE (IfThenElse c t e a)-    | evalD c   = evalD (apply t a)-    | otherwise = evalD (apply e a)--evalE (While cont body init) =-    head $ dropWhile (evalF cont) $ iterate (evalF body) $ evalD init--evalE (Parallel l ixf) = map (evalF ixf) [0 .. evalD l-1]------ | The semantics of 'Data'-evalD :: Data a -> a-evalD = evalE . dataToExpr--evalF :: (a :-> b) -> (a -> b)-evalF (Lambda f i o) = evalD . f . exprToData (dataSize i) . Val---- | The semantics of any 'Computable' type-eval :: Computable a => a -> Internal a-eval = evalD . internalize------ | A program that computes a constant value-value :: Storable a => a -> Data a-value a = exprToData (storableSize a) (Value a)---- | Like 'value' but with an extra 'Size' argument that can be used to increase--- the size beyond the given data.------ Example 1:------ > array (10 :> 20 :> universal) [] :: Data [[Int]]------ gives an uninitialized 10x20 array of 'Int' elements.------ Example 2:------ > array (10 :> 20 :> universal) [[1,2,3]] :: Data [[Int]]------ gives a 10x20 array whose first row is initialized to @[1,2,3]@.-array :: Storable a => Size a -> a -> Data a-array sz a = exprToData (sz `mappend` storableSize a) (Value a)--arrayLen :: Storable a => Data Length -> [a] -> Data [a]-arrayLen len = array sz-  where-    sz = mapMonotonic fromInteger (dataSize len) :> universal-  -- XXX This function is a temporary solution.--unit :: Data ()-unit = value ()--true :: Data Bool-true = value True--false :: Data Bool-false = value False---- | Returns the size of each level of a multi-dimensional array, starting with--- the outermost level.-size :: forall a . Storable a => Data [a] -> [Range Length]-size = listSize (T::T [a]) . dataSize--cap :: (Storable a, Size a ~ Range b, Ord b) => Range b -> Data a -> Data a-cap szb (Data sz a) = Data (sz /\ szb) a-  -- XXX Should really have the type-  --       cap :: Storable a => Size a -> Data a -> Data a------ | Constructs a one-argument primitive function.------ @`function` fun szf f@:------   * @fun@ is the name of the function.------   * @szf@ computes the output size from the input size.------   * @f@   gives the evaluation semantics.-function-    :: (Storable a, Storable b)-    => String -> (Size a -> Size b) -> (a -> b) -> (Data a -> Data b)--function fun sizeProp f a = case dataToExpr a of-    Value a' -> exprToData sz $ Value (f a')-    _        -> _function fun sizeProp f a-  where-    sz = sizeProp (dataSize a)------ | A two-argument primitive function-function2-    :: ( Storable a-       , Storable b-       , Storable c-       )-    => String-    -> (Size a -> Size b -> Size c)-    -> (a -> b -> c)-    -> (Data a -> Data b -> Data c)--function2 fun sizeProp f a b = case (dataToExpr a, dataToExpr b) of-    (Value a', Value b') -> exprToData sz $ Value (f a' b')-    _ -> _function fun (uncurry sizeProp) (uncurry f) (tup2 a b)-    -- XXX Should perhaps look like this instead:-    -- _ -> _function2 fun sizeProp f a b-  where-    sz = sizeProp (dataSize a) (dataSize b)------ | A three-argument primitive function-function3-    :: ( Storable a-       , Storable b-       , Storable c-       , Storable d-       )-    => String-    -> (Size a -> Size b -> Size c -> Size d)-    -> (a -> b -> c -> d)-    -> (Data a -> Data b -> Data c -> Data d)--function3 fun sizeProp f a b c = case (d2e a, d2e b, d2e c) of-    (Value a', Value b', Value c') -> exprToData sz $ Value (f a' b' c')-    _ -> _function fun (uncurr sizeProp) (uncurr f) (tup3 a b c)-  where-    d2e = dataToExpr-    sz  = sizeProp (dataSize a) (dataSize b) (dataSize c)-    uncurr g (a,b,c) = g a b c------ | A four-argument primitive function-function4-    :: ( Storable a-       , Storable b-       , Storable c-       , Storable d-       , Storable e-       )-    => String-    -> (Size a -> Size b -> Size c -> Size d -> Size e)-    -> (a -> b -> c -> d -> e)-    -> (Data a -> Data b -> Data c -> Data d -> Data e)--function4 fun sizeProp f a b c d = case (d2e a, d2e b, d2e c, d2e d) of-    (Value a', Value b', Value c', Value d') -> exprToData sz $ Value (f a' b' c' d')-    _ -> _function fun (uncurr sizeProp) (uncurr f) (tup4 a b c d)-  where-    d2e = dataToExpr-    sz  = sizeProp (dataSize a) (dataSize b) (dataSize c) (dataSize d)-    uncurr g (a,b,c,d) = g a b c d----- | Look up an index in an array (see also '!')-getIx :: Storable a => Data [a] -> Data Int -> Data a-getIx arr = function2 "(!)" sizeProp f arr-  where-    sizeProp (_:>aSize) _ = aSize--    f as i-        | not (i `inRange` r) = error "getIx: index out of bounds"-        | i >= la             = error "getIx: reading garbage"-        | otherwise           = as !! i-      where-        l:>_ = dataSize arr-        r    = rangeByRange 0 (l-1)-        la   = length as------ | @`setIx` arr i a@:------ Replaces the value at index @i@ in the array @arr@ with the value @a@.-setIx :: Storable a => Data [a] -> Data Int -> Data a -> Data [a]-setIx arr = function3 "setIx" sizeProp f arr-  where-    sizeProp (l:>aSize) _ aSize' = l :> (aSize `mappend` aSize')--    f as i a-        | not (i `inRange` r) = error "setIx: index out of bounds"-        | i > la              = error "setIx: writing past initialized area"-        | otherwise           = take i as ++ [a] ++ drop (i+1) as-      where-        l:>_ = dataSize arr-        r    = rangeByRange 0 (l-1)-        la   = length as----infixl 9 !--class RandomAccess a-  where-    -- | The type of elements in a random access structure-    type Element a--    -- | Index lookup in a random access structure-    (!) :: a -> Data Int -> Element a--instance Storable a => RandomAccess (Data [a])-  where-    type Element (Data [a]) = Data a-    (!) = getIx------ | Constructs a non-primitive, non-inlined function.------ The normal way to make a non-primitive function is to use an ordinary Haskell--- function, for example:------ > myFunc x = x * 4 + 5------ However, such functions are inevitably inlined into the program expression--- when applied. @noInline@ can be thought of as a way to protect a function--- against inlining (but later transformations may choose to inline anyway).------ Ideally, it should be posssible to reuse such a function several times, but--- at the moment this does not work. Every application of a @noInline@ function--- results in a new copy of the function in the core program.-noInline :: (Computable a, Computable b) => String -> (a -> b) -> (a -> b)-noInline fun f a = liftFun (exprToData sz . NoInline fun (ref fLam)) a-  where-    fLam = lambda (dataSize $ internalize a) (lowerFun f)-    sz   = resultSize fLam------ | @`ifThenElse` cond thenFunc elseFunc@:------ Selects between the two functions @thenFunc@ and @elseFunc@ depending on--- whether the condition @cond@ is true or false.-ifThenElse-    :: (Computable a, Computable b)-    => Data Bool -> (a -> b) -> (a -> b) -> (a -> b)--ifThenElse cond t e a = case dataToExpr cond of-    Value True  -> t a-    Value False -> e a-    _           -> liftFun (exprToData szb . IfThenElse cond thenLam elseLam) a-  where-    sza     = dataSize $ internalize a-    thenLam = lambda sza (lowerFun t)-    elseLam = lambda sza (lowerFun e)-    szb     = resultSize thenLam `mappend` resultSize elseLam----whileSized-    :: Computable state-    => Size (Internal state)-    -> Size (Internal state)-    -> (state -> Data Bool)-    -> (state -> state)-    -> (state -> state)--whileSized szInitCont szInitBody cont body =-    liftFun (exprToData szFinal . While contLam bodyLam)-  where-    contLam = lambda szInitCont (lowerFun cont)-    bodyLam = lambda szInitBody (lowerFun body)-    szFinal = universal  -- XXX The best we can do at the moment...------ | While-loop------ @while cont body :: state -> state@:------   * @state@ is the type of the state.------   * @cont@ determines whether or not to continue based on the current state.------   * @body@ computes the next state from the current state.------   * The result is a function from initial state to final state.-while-    :: Computable state-    => (state -> Data Bool)-    -> (state -> state)-    -> (state -> state)--while = whileSized universal universal------ | Parallel array------ @parallel l ixf@:------   * @l@ is the length of the resulting array (outermost level).------   * @ifx@ is a function that maps each index in the range @[0 .. l-1]@ to its---     element.------ Since there are no dependencies between the elements, the compiler is free to--- compute the elements in any order, or even in parallel.-parallel :: Storable a => Data Length -> (Data Int -> Data a) -> Data [a]-parallel l ixf = exprToData szPar $ Parallel l ixfLam-  where-    szl    = dataSize l-    ixfLam = lambda (rangeByRange 0 (szl-1)) ixf-    szPar  = mapMonotonic fromIntegral szl :> resultSize ixfLam-
Feldspar/Core/Functions.hs view
@@ -1,737 +1,40 @@------ Copyright (c) 2009-2010, ERICSSON AB All rights reserved.--- --- Redistribution and use in source and binary forms, with or without--- modification, are permitted provided that the following conditions are met:--- ---     * Redistributions of source code must retain the above copyright notice,---       this list of conditions and the following disclaimer.---     * 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 name of the ERICSSON AB nor the names of its contributors---       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 AND CONTRIBUTORS "AS IS"--- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE--- IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE--- ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS--- BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,--- OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF--- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS--- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN--- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)--- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF--- THE POSSIBILITY OF SUCH DAMAGE.-----{-# LANGUAGE UndecidableInstances #-}---- | Primitive and helper functions supported by Feldspar--module Feldspar.Core.Functions where----import qualified Prelude--import Feldspar.Range-import Feldspar.Core.Types-import Feldspar.Core.Expr-import Feldspar.Core.Reify-import Feldspar.Prelude--import qualified Data.Bits as B--infix  4 ==-infix  4 /=-infix  4 <-infix  4 >-infix  4 <=-infix  4 >=-infixr 3 &&-infixr 3 &&*-infixr 2 ||-infixr 2 ||*-infix  1 ?------ * Misc.--noSizeProp :: a -> ()-noSizeProp _ = ()--noSizeProp2 :: a -> b -> ()-noSizeProp2 _ _ = ()--class (Prelude.Eq a, Storable a) => Eq a where-  (==) :: Data a -> Data a -> Data Bool-  a == b-    | a Prelude.== b = true-    | otherwise      = function2 "(==)" noSizeProp2 (Prelude.==) a b-  (/=) :: Data a -> Data a -> Data Bool-  a /= b-    | a Prelude.== b = false-    | otherwise      = function2 "(/=)" noSizeProp2 (Prelude./=) a b--optEq :: (Storable a, Size a ~ Range b, Prelude.Ord b, Num b) =>-         Data a -> Data a -> Data Bool-optEq a b-    | a Prelude.== b   = true-    | sa `disjoint` sb = false-    | otherwise        = function2 "(==)" noSizeProp2 (Prelude.==) a b-   where-     sa = dataSize a-     sb = dataSize b--optNeq :: (Storable a, Size a ~ Range b, Prelude.Ord b, Num b) =>-         Data a -> Data a -> Data Bool-optNeq a b-    | a Prelude.== b   = false-    | sa `disjoint` sb = true-    | otherwise        = function2 "(/=)" noSizeProp2 (Prelude./=) a b-   where-     sa = dataSize a-     sb = dataSize b--instance Eq Int where-  a == b = optEq  a b-  a /= b = optNeq a b--instance Eq Signed32 where-  a == b = optEq  a b-  a /= b = optNeq a b--instance Eq Unsigned32 where-  a == b = optEq  a b-  a /= b = optNeq a b--instance Eq Signed16 where-  a == b = optEq  a b-  a /= b = optNeq a b--instance Eq Unsigned16 where-  a == b = optEq  a b-  a /= b = optNeq a b--instance Eq Signed8 where-  a == b = optEq  a b-  a /= b = optNeq a b--instance Eq Unsigned8 where-  a == b = optEq  a b-  a /= b = optNeq a b--instance Eq Float where-  a == b = optEq  a b-  a /= b = optNeq a b--instance Eq Bool--instance Eq ()--class (Prelude.Ord a, Eq a, Storable a) => Ord a where-  (<)  :: Data a -> Data a -> Data Bool-  a < b-    | a Prelude.== b = false-    | otherwise      = function2 "(<)" noSizeProp2 (Prelude.<) a b-  (>)  :: Data a -> Data a -> Data Bool-  a > b-    | a Prelude.== b = false-    | otherwise      = function2 "(>)" noSizeProp2 (Prelude.>) a b-  (<=) :: Data a -> Data a -> Data Bool-  a <= b-    | a Prelude.== b = true-    | otherwise      = function2 "(<=)" noSizeProp2 (Prelude.<=) a b-  (>=) :: Data a -> Data a -> Data Bool-  a >= b-    | a Prelude.== b = true-    | otherwise      = function2 "(>=)" noSizeProp2 (Prelude.>=) a b-  min  ::  Data a -> Data a -> Data a-  min a b = a<b ? (a,b)-  max  :: Data a -> Data a -> Data a-  max a b = a>b ? (a,b)--optLT :: (Storable a, Prelude.Ord a, Size a ~ Range b, Prelude.Ord b, Num b) =>-         Data a -> Data a -> Data Bool-optLT a b-    | a Prelude.== b      = false-    | sa `rangeLess`   sb = true-    | sb `rangeLessEq` sa = false-    | otherwise           = function2 "(<)" noSizeProp2 (Prelude.<) a b-    where-      sa = dataSize a-      sb = dataSize b--optGT :: (Storable a, Prelude.Ord a, Size a ~ Range b, Prelude.Ord b, Num b) =>-         Data a -> Data a -> Data Bool-optGT a b-    | a Prelude.== b      = false-    | sb `rangeLess`   sa = true-    | sa `rangeLessEq` sb = false-    | otherwise           = function2 "(>)" noSizeProp2 (Prelude.>) a b-    where-      sa = dataSize a-      sb = dataSize b--optLTE :: (Storable a, Prelude.Ord a, Size a ~ Range b, Prelude.Ord b, Num b) =>-         Data a -> Data a -> Data Bool-optLTE a b-    | a Prelude.== b      = true-    | sa `rangeLessEq` sb = true-    | sb `rangeLess`   sa = false-    | otherwise           = function2 "(<=)" noSizeProp2 (Prelude.<=) a b-    where-      sa = dataSize a-      sb = dataSize b--optGTE :: (Storable a, Prelude.Ord a, Size a ~ Range b, Prelude.Ord b, Num b) =>-         Data a -> Data a -> Data Bool-optGTE a b-    | a Prelude.== b      = true-    | sb `rangeLessEq` sa = true-    | sa `rangeLess`   sb = false-    | otherwise           = function2 "(>=)" noSizeProp2 (Prelude.>=) a b-    where-      sa = dataSize a-      sb = dataSize b--optMin :: (Ord a, Size a ~ Range b, Prelude.Ord b, Num b) =>-          Data a -> Data a -> Data a-optMin a b = cap (rangeMin ra rb) $-    case dataToExpr cond1 of-      Value _ -> cond1 ? (a,b)-      _       -> cond2 ? (b,a)-  where-    cond1 = a<b-    cond2 = b<a-    ra    = dataSize a-    rb    = dataSize b--optMax :: (Ord a, Size a ~ Range b, Prelude.Ord b, Num b) =>-          Data a -> Data a -> Data a-optMax a b = cap (rangeMax ra rb) $-    case dataToExpr cond1 of-      Value _ -> cond1 ? (a,b)-      _       -> cond2 ? (b,a)-  where-    cond1 = a>b-    cond2 = b>a-    ra    = dataSize a-    rb    = dataSize b--instance Ord Int where-  a <  b  = optLT  a b-  a >  b  = optGT  a b-  a <= b  = optLTE a b-  a >= b  = optGTE a b-  min a b = optMin a b-  max a b = optMax a b--instance Ord Unsigned32 where-  a <  b  = optLT  a b-  a >  b  = optGT  a b-  a <= b  = optLTE a b-  a >= b  = optGTE a b-  min a b = optMin a b-  max a b = optMax a b--instance Ord Signed32 where-  a <  b  = optLT  a b-  a >  b  = optGT  a b-  a <= b  = optLTE a b-  a >= b  = optGTE a b-  min a b = optMin a b-  max a b = optMax a b--instance Ord Unsigned16 where-  a <  b  = optLT  a b-  a >  b  = optGT  a b-  a <= b  = optLTE a b-  a >= b  = optGTE a b-  min a b = optMin a b-  max a b = optMax a b--instance Ord Signed16 where-  a <  b  = optLT  a b-  a >  b  = optGT  a b-  a <= b  = optLTE a b-  a >= b  = optGTE a b-  min a b = optMin a b-  max a b = optMax a b--instance Ord Unsigned8 where-  a <  b  = optLT  a b-  a >  b  = optGT  a b-  a <= b  = optLTE a b-  a >= b  = optGTE a b-  min a b = optMin a b-  max a b = optMax a b--instance Ord Signed8 where-  a <  b  = optLT  a b-  a >  b  = optGT  a b-  a <= b  = optLTE a b-  a >= b  = optGTE a b-  min a b = optMin a b-  max a b = optMax a b--instance Ord Float where-  a <  b  = optLT  a b-  a >  b  = optGT  a b-  a <= b  = optLTE a b-  a >= b  = optGTE a b-  min a b = optMin a b-  max a b = optMax a b--not :: Data Bool -> Data Bool-not = function "not" noSizeProp Prelude.not---- | Selects the elements of the pair depending on the condition-(?) :: Computable a => Data Bool -> (a,a) -> a-cond ? (a,b) = ifThenElse cond (const a) (const b) unit--(&&) :: Data Bool -> Data Bool -> Data Bool-x && y = case (dataToExpr x, dataToExpr y) of-           (Value True, _) -> y-           (Value False,_) -> false-           (_, Value True) -> x-           (_,Value False) -> false-           _               -> function2 "(&&)" noSizeProp2 (Prelude.&&) x y--(||) :: Data Bool -> Data Bool -> Data Bool-x || y = case (dataToExpr x, dataToExpr y) of-           (Value True, _) -> true-           (Value False,_) -> y-           (_, Value True) -> true-           (_,Value False) -> y-           _               -> function2 "(||)" noSizeProp2 (Prelude.||) x y---- | Lazy conjunction, second argument only run if necessary-(&&*) :: Computable a =>-    (a -> Data Bool) -> (a -> Data Bool) -> (a -> Data Bool)-(f &&* g) a = ifThenElse (f a) g (const false) a---- | Lazy disjunction, second argument only run if necessary-(||*) :: Computable a =>-    (a -> Data Bool) -> (a -> Data Bool) -> (a -> Data Bool)-(f ||* g) a = ifThenElse (f a) (const true) g a--class (Numeric a, Prelude.Integral a, Ord a, Storable a) =>-    Integral a where-  quot    :: Data a -> Data a -> Data a-  quot    = function2 "quot" (\_ _ -> universal) Prelude.quot-  rem     :: Data a -> Data a -> Data a-  rem     = function2 "rem"  (\_ _ -> universal) Prelude.rem-  div     :: Data a -> Data a -> Data a-  div x y = rem x y /= 0 && (x > 0 && y < 0 || x < 0 && y > 0) ?-            (quotxy - 1, quotxy)-      where quotxy = quot x y-  mod     :: Data a -> Data a -> Data a-  mod x y = remxy  /= 0 && (x > 0 && y < 0 || x < 0 && y > 0) ?-            (remxy + y, remxy)-      where remxy = rem x y-  (^)     :: Data a -> Data a -> Data a-  (^)     = function2 "(^)" (\_ _ -> universal) (Prelude.^)--optRem  :: (Integral a, Size a ~ Range b, Prelude.Ord b, Num b, Enum b) =>-           Data a -> Data a -> Data a-optRem x y-    | abs rx `rangeLess` abs ry = x-    | otherwise                 = function2 "rem"  rangeRem  Prelude.rem x y-    where rx = dataSize x-          ry = dataSize y--optMod :: (Integral a, Size a ~ Range b, Prelude.Ord b, Num b, Enum b) =>-       Data a -> Data a -> Data a-optMod x y = cap (rangeMod rx ry) $-             remxy  /= 0 && (x > 0 && y < 0 || x < 0 && y > 0) ?-             (remxy + y, remxy)-  where remxy = rem x y-        rx    = dataSize x-        ry    = dataSize y--optSignedExp :: (Integral a, Bits a, Storable a,-                Size a ~ Range b, Prelude.Ord b, Num b) =>-                Data a -> Data a -> Data a-optSignedExp m e = case dataToExpr m of-                   -- From Bit Twiddling Hacks-                   -- "Conditionally negate a value without branching"-                   -- Here we negate the value 1 if isOdd is true i.e. when e is-                   -- and odd number-                     Value (-1) -> cap (range (-1) 1) $-                                   let isOdd = e .&. 1-                                   in (1 `xor` (negate isOdd)) + isOdd-                     _ -> optExp m e--optExp :: (Integral a, Storable a) => Data a -> Data a -> Data a-optExp m e = case (dataToExpr m,dataToExpr e) of-               (Value 1,_) -> value 1-               (_,Value 1) -> m-               (_,Value 0) -> value 1-               _           -> function2 "(^)" (\_ _ -> universal) (Prelude.^) m e--instance Integral Int where-  rem = optRem-  mod = optMod-  (^) = optSignedExp--instance Integral Signed32 where-  rem = optRem-  mod = optMod-  (^) = optSignedExp--instance Integral Unsigned32 where-  div = quot-  rem = optRem-  mod = rem-  (^) = optExp--instance Integral Signed16 where-  rem = optRem-  mod = optMod-  (^) = optSignedExp--instance Integral Unsigned16 where-  div = quot-  rem = optRem-  mod = rem-  (^) = optExp--instance Integral Signed8 where-  rem = optRem-  mod = optMod-  (^) = optSignedExp--instance Integral Unsigned8 where-  div = quot-  rem = optRem-  mod = rem-  (^) = optExp------ * Loops---- | For-loop------ @`for` start end init body@:------   * @start@\/@end@ are the start\/end indexes.------   * @init@ is the starting state.------   * @body@ computes the next state given the current loop index (ranging over---     @[start .. end]@) and the current state.-for :: Computable a => Data Int -> Data Int -> a -> (Data Int -> a -> a) -> a-for start end init body = snd $ whileSized szCont szBody cont body' (start,init)-  where-    sziCont = rangeByRange (dataSize start) (dataSize end + 1)-    szCont  = (sziCont,universal)--    sziBody = rangeByRange (dataSize start) (dataSize end)-    szBody  = (sziBody,universal)--    cont  (i,s) = i <= end-    body' (i,s) = (i+1, body i s)+module Feldspar.Core.Functions+    ( module Feldspar.Core.Functions.Logic+    , Eq (..)+    , Ord (..)+    , Numeric+    , Bits (..)+    , (⊕)+    , (<<)+    , (>>)+    , Integral (..)+    , Fractional'+    , module Feldspar.Core.Functions.Complex+    , module Feldspar.Core.Functions.Tuple+    , arrayLen+    , getIx+    , setIx+    , getLength+    , RandomAccess (..)+    , module Feldspar.Core.Functions.Conversion+    , module Feldspar.Core.Functions.Trace+    ) where   --- | A sequential \"unfolding\" of an vector------ @`unfoldCore` l init step@:------   * @l@ is the length of the resulting vector.------   * @init@ is the initial state.------   * @step@ is a function computing a new element and the next state from the---     current index and current state. The index is the position of the new---     element in the output vector.-unfoldCore-    :: (Computable state, Storable a)-    => Data Length-    -> state-    -> (Data Int -> state -> (Data a, state))-    -> (Data [a], state)--unfoldCore l init step = for 0 (l-1) (outp,init) $ \i (o,state) ->-    let (a,state') = step i state-     in (setIx o i a, state')-  where-    outp = array (mapMonotonic fromIntegral (dataSize l) :> universal) []--class (Num a, Storable a) => Numeric a-  where-    fromIntegerNum :: Integer -> Data a-    fromIntegerNum = value . fromInteger--    absNum    :: Data a -> Data a-    signumNum :: Data a -> Data a-    addNum    :: Data a -> Data a -> Data a-    subNum    :: Data a -> Data a -> Data a-    mulNum    :: Data a -> Data a -> Data a--absNum' :: (Numeric a, Num (Size a)) => Data a -> Data a-absNum' = function "abs" abs abs--optAbs :: (Numeric a, Size a ~ Range b, Num b, Prelude.Ord b) =>-          Data a -> Data a-optAbs x | isNatural rx = x-         | otherwise    = absNum' x-  where rx = dataSize x--signumNum' :: (Numeric a, Num (Size a)) => Data a -> Data a-signumNum' = function "signum" signum signum--optSignum :: (Numeric a, Size a ~ Range b, Num b, Prelude.Ord b) => Data a -> Data a-optSignum x | 0  `rangeLess` rx =  1-            | rx `rangeLess` 0  = -1-            | rx Prelude.==  0  =  0-            | otherwise         = signumNum' x-  where rx = dataSize x--optAdd :: (Numeric a, Num (Size a)) => Data a -> Data a -> Data a-optAdd x y = case (dataToExpr x, dataToExpr y) of-               (Value 0, _) -> y-               (_, Value 0) -> x-               _            -> function2 "(+)" (+) (+) x y--optSub  :: (Numeric a, Num (Size a)) => Data a -> Data a -> Data a-optSub x y = case dataToExpr y of-               Value 0 -> x-               _       -> function2 "(-)" (-) (-) x y--optMul :: (Numeric a, Num (Size a)) => Data a -> Data a -> Data a-optMul x y = case (dataToExpr x, dataToExpr y) of-               (Value 0,_) -> value 0-               (_,Value 0) -> value 0-               (Value 1,_) -> y-               (_,Value 1) -> x-               _           -> function2 "(*)" (*) (*) x y--instance Numeric Int-  where-    absNum    = optAbs-    signumNum = optSignum-    addNum    = optAdd-    subNum    = optSub-    mulNum    = optMul--instance Numeric Unsigned32-  where-    absNum    = optAbs-    signumNum = optSignum-    addNum    = optAdd-    subNum    = optSub-    mulNum    = optMul--instance Numeric Signed32-  where-    absNum    = optAbs-    signumNum = optSignum-    addNum    = optAdd-    subNum    = optSub-    mulNum    = optMul--instance Numeric Unsigned16-  where-    absNum    = optAbs-    signumNum = optSignum-    addNum    = optAdd-    subNum    = optSub-    mulNum    = optMul--instance Numeric Signed16-  where-    absNum    = optAbs-    signumNum = optSignum-    addNum    = optAdd-    subNum    = optSub-    mulNum    = optMul--instance Numeric Unsigned8-  where-    absNum    = optAbs-    signumNum = optSignum-    addNum    = optAdd-    subNum    = optSub-    mulNum    = optMul--instance Numeric Signed8-  where-    absNum    = optAbs-    signumNum = optSignum-    addNum    = optAdd-    subNum    = optSub-    mulNum    = optMul--instance Numeric Float-  where-    absNum    = optAbs-    signumNum = optSignum-    addNum    = optAdd-    subNum    = optSub-    mulNum    = optMul--instance Numeric a => Num (Data a)-  where-    fromInteger = fromIntegerNum-    abs         = absNum-    signum      = signumNum-    (+)         = addNum-    (-)         = subNum-    (*)         = mulNum--class (Fractional a, Storable a) => Fractional' a-  where-    fromRationalFrac :: Rational -> Data a-    fromRationalFrac = value . fromRational--    divFrac :: Data a -> Data a -> Data a--instance Fractional' Float-  where-    divFrac = function2 "(/)" (\_ _ -> fullRange) (/)  -- XXX Improve range--instance (Fractional' a, Numeric a) => Fractional (Data a)-  where-    fromRational = fromRationalFrac-    (/)          = divFrac---- * Bit manipulation--infixl 5 <<,>>-infixl 4 ⊕---- | The following class provides functions for bit level manipulation-class (B.Bits a, Storable a) => Bits a-  where-  -- Logical operations-  (.&.)         :: Data a -> Data a -> Data a-  (.&.)         =  optAnd-  (.|.)         :: Data a -> Data a -> Data a-  (.|.)         =  optOr-  xor           :: Data a -> Data a -> Data a-  xor           =  optXor-  (⊕)           :: Data a -> Data a -> Data a-  (⊕)           =  xor-  complement    :: Data a -> Data a-  complement    =  function "complement" (const universal) B.complement--  -- Operations on individual bits-  bit           :: Data Int -> Data a-  bit           =  function "bit" (const universal) B.bit-  setBit        :: Data a -> Data Int -> Data a-  setBit        =  function2 "setBit" (\_ _ -> universal) B.setBit-  clearBit      :: Data a -> Data Int -> Data a-  clearBit      =  function2 "clearBit" (\_ _ -> universal) B.clearBit-  complementBit :: Data a -> Data Int -> Data a-  complementBit =  function2 "complementBit" (\_ _ -> universal) B.complementBit-  testBit       :: Data a -> Data Int -> Data Bool-  testBit       =  function2 "testBit" noSizeProp2 B.testBit--  -- Moving bits around-  shiftL        :: Data a -> Data Int -> Data a-  shiftL        =  optZero (function2 "shiftL" (\_ _ -> universal) B.shiftL)-  (<<)          :: Data a -> Data Int -> Data a-  (<<)          =  shiftL-  shiftR        :: Data a -> Data Int -> Data a-  shiftR        =  optZero (function2 "shiftR" (\_ _ -> universal) B.shiftR)-  (>>)          :: Data a -> Data Int -> Data a-  (>>)          =  shiftR-  rotateL       :: Data a -> Data Int -> Data a-  rotateL       =  optZero (function2 "rotateL" (\_ _ -> universal) B.rotateL)-  rotateR       :: Data a -> Data Int -> Data a-  rotateR       =  optZero (function2 "rotateR" (\_ _ -> universal) B.rotateR)-  reverseBits   :: Data a -> Data a-  reverseBits   =  function "reverseBits" (\_ -> universal) revBits--  -- Bulk bit operations-  -- | Returns the number of leading zeroes for unsigned types.-  -- For signed types it returns the number of unnecessary sign bits-  bitScan       :: Data a -> Data Int-  bitScan       =  function "bitScan" (\_ -> universal) scanLeft-  bitCount      :: Data a -> Data Int-  bitCount      =  function "bitCount" (\_ -> universal) countBits--  -- Queries about the type-  bitSize       :: Data a -> Data Int-  bitSize       =  function "bitSize" (const naturalRange) B.bitSize-  isSigned      :: Data a -> Data Bool-  isSigned      =  function "isSigned" noSizeProp B.isSigned--optAnd :: (B.Bits a, Storable a) => Data a -> Data a -> Data a-optAnd x y = case (dataToExpr x, dataToExpr y) of-               (Value 0, _) -> value 0-               (_, Value 0) -> value 0-               (Value x, _) | allOnes x -> y-               (_, Value y) | allOnes y -> x-               _            -> function2 "(.&.)" (\_ _ -> universal) (B..&.) x y--optOr :: (B.Bits a, Storable a) => Data a -> Data a -> Data a-optOr x y = case (dataToExpr x, dataToExpr y) of-              (Value 0, _) -> y-              (_, Value 0) -> x-              (Value x, _) | allOnes x -> value (B.complement 0)-              (_, Value y) | allOnes y -> value (B.complement 0)-              _            -> function2 "(.|.)" (\_ _ -> universal) (B..|.) x y--optXor :: (Bits a, B.Bits a, Storable a) => Data a -> Data a -> Data a-optXor x y = case (dataToExpr x, dataToExpr y) of-               (Value 0, _) -> y-               (_, Value 0) -> x-               (Value x, _) | allOnes x -> complement y-               (_, Value y) | allOnes y -> complement x-               _            -> function2 "xor" (\_ _ -> universal) B.xor x y--allOnes :: (Prelude.Eq a, B.Bits a) => a -> Bool-allOnes x = x Prelude.== B.complement 0--optZero :: (a -> Data Int -> a) -> a -> Data Int -> a-optZero f x y = case dataToExpr y of-                  Value 0 -> x-                  _       -> f x y--scanLeft :: B.Bits b => b -> Int-scanLeft b =-   if B.isSigned b-   then scanLoop b (B.testBit b (B.bitSize b - 1)) (B.bitSize b - 2) 0-         else scanLoop b False (B.bitSize b - 1) 0-  where-    scanLoop b bit i n | i Prelude.< 0                = n-    scanLoop b bit i n | B.testBit b i Prelude./= bit = n-    scanLoop b bit i n | otherwise                    = scanLoop b bit (i-1) (n+1)---countBits :: B.Bits b => b -> Int-countBits b = loop b (B.bitSize b - 1) 0-  where-    loop b i n | i Prelude.< 0 = n-    loop b i n | B.testBit b i = loop b (i-1) (n+1)-    loop b i n | otherwise     = loop b (i-1) n--revBits :: B.Bits b => b -> b-revBits b = revLoop b 0 (0 `asTypeOf` b)-  where-    bitSize = B.bitSize b-    revLoop b i n | i Prelude.>= bitSize  = n-    revLoop b i n | B.testBit b i = revLoop b (i+1) (B.setBit n (bitSize - i - 1))-    revLoop b i n | otherwise     = revLoop b (i+1) n--instance Bits Int--instance Bits Unsigned32--instance Bits Signed32--instance Bits Unsigned16--instance Bits Signed16--instance Bits Unsigned8+import Prelude () -instance Bits Signed8+import Feldspar.Core.Functions.Logic+import Feldspar.Core.Functions.Eq+import Feldspar.Core.Functions.Ord+import Feldspar.Core.Functions.Num+import Feldspar.Core.Functions.Bits+import Feldspar.Core.Functions.Integral+import Feldspar.Core.Functions.Fractional+import Feldspar.Core.Functions.Floating+import Feldspar.Core.Functions.Complex+import Feldspar.Core.Functions.Tuple+import Feldspar.Core.Functions.Array+import Feldspar.Core.Functions.Conversion+import Feldspar.Core.Functions.Trace 
+ Feldspar/Core/Functions/Array.hs view
@@ -0,0 +1,88 @@+-- | Core language array operations++module Feldspar.Core.Functions.Array+    ( arrayLen+    , getIx+    , setIx+    , getLength+    , RandomAccess (..)+    ) where++++import Data.List++import Feldspar.Set+import Feldspar.Range+import Feldspar.Core.Types+import Feldspar.Core.Representation+import Feldspar.Core.Constructs+import Feldspar.Core.Functions.Num ()++import Feldspar.DSL.Expression+import Feldspar.DSL.Lambda+import Feldspar.DSL.Network++-- | Constructs an array of the given length and initialization.+arrayLen :: Type a => Data Length -> [a] -> Data [a]+arrayLen len = array (dataSize len :> universal)+  -- TODO This function is a temporary solution.++evalGetIx :: Range Length -> [a] -> Index -> a+evalGetIx l as i+    | not (i `inRange` r) = error "getIx: index out of bounds"+    | i >= la             = error "getIx: reading garbage"+    | otherwise           = genericIndex as i+  where+    la = genericLength as+    r  = rangeByRange 0 (l-1)++-- | Look up an index in an array (see also '!')+getIx :: Type a => Data [a] -> Data Index -> Data a+getIx arr = function2 "(!)" sizeProp (evalGetIx l) arr+  where+    sizeProp (_:>aSize) _ = aSize+    l:>_ = dataSize arr++-- | Array update+setIx+    :: Type a+    => Data [a]    -- ^ Source array+    -> Data Index  -- ^ Index to replace+    -> Data a      -- ^ New value+    -> Data [a]+setIx arr i a =+        nodeData (dataSize arr)+     $  Inject (Node SetIx)+    :$: toEdge i+    :$: toEdge a+    :$: toEdge arr++-- | Array length+getLength :: Type a => Data [a] -> Data Length+getLength arr = case undoEdge (unData arr) of+    Inject (Node Parallel) :$: len :$: _ :$: arr' -> Data len + getLength (Data arr')+    Inject (Node SetLength) :$: len :$: _ -> Data len+    Inject (Node SetIx) :$: _ :$: _ :$: arr' -> getLength (Data arr')+    _ -> case dataSize arr of+        (Range l b :> _)+            | l == b    -> value l+        otherwise       -> function1 "length" sizeProp genericLength arr+  where+    sizeProp (lSize:>_) = lSize++infixl 9 !++class RandomAccess a+  where+    -- | The type of elements in a random access structure+    type Element a++    -- | Index lookup in a random access structure+    (!) :: a -> Data Index -> Element a++instance Type a => RandomAccess (Data [a])+  where+    type Element (Data [a]) = Data a+    (!) = getIx+
+ Feldspar/Core/Functions/Bits.hs view
@@ -0,0 +1,202 @@+-- | Bit manipulation++module Feldspar.Core.Functions.Bits where++import qualified Data.Bits as B+import Data.Int+import Data.Word++import Feldspar.Range+import Feldspar.Core.Types+import Feldspar.Core.Representation+import Feldspar.Core.Constructs++infixl 5 <<,>>+infixl 4 ⊕++-- | Redefinition of the standard 'B.Bits' class for Feldspar+class (B.Bits a, Type a, FullProp (Size a)) => Bits a+  where+  -- Logical operations+  (.&.)         :: Data a -> Data a -> Data a+  (.&.)         =  optAnd fullProp+  (.|.)         :: Data a -> Data a -> Data a+  (.|.)         =  optOr fullProp+  xor           :: Data a -> Data a -> Data a+  xor           =  optXor fullProp+  complement    :: Data a -> Data a+  complement    =  function1 "complement" fullProp B.complement++  -- Operations on individual bits+  bit           :: Data Index -> Data a+  bit           =  function1 "bit" fullProp (B.bit . fromIntegral)+  setBit        :: Data a -> Data Index -> Data a+  setBit        =  function2 "setBit" fullProp (liftIntWord B.setBit)+  clearBit      :: Data a -> Data Index -> Data a+  clearBit      =  function2 "clearBit" fullProp (liftIntWord B.clearBit)+  complementBit :: Data a -> Data Index -> Data a+  complementBit =  function2 "complementBit" fullProp (liftIntWord B.complementBit)+  testBit       :: Data a -> Data Index -> Data Bool+  testBit       =  function2 "testBit" fullProp (liftIntWord B.testBit)++  -- Moving bits around+  shiftLU       :: Data a -> Data Index -> Data a+  shiftLU       =  optZero $ function2 "shiftL" fullProp (liftIntWord B.shiftL)+  shiftRU       :: Data a -> Data Index -> Data a+  shiftRU       =  optZero $ function2 "shiftR" fullProp cShiftRU+  shiftL        :: Data a -> Data DefaultInt -> Data a+  shiftL        =  optZero $ function2 "shiftL" fullProp (liftInt B.shiftL)+  shiftR        :: Data a -> Data DefaultInt -> Data a+  shiftR        =  optZero $ function2 "shiftR" fullProp (liftInt B.shiftR)+  rotateLU      :: Data a -> Data Index -> Data a+  rotateLU      =  optZero $ function2 "rotateL" fullProp (liftIntWord B.rotateL )+  rotateRU      :: Data a -> Data Index -> Data a+  rotateRU      =  optZero $ function2 "rotateR" fullProp (liftIntWord B.rotateR )+  rotateL       :: Data a -> Data DefaultInt -> Data a+  rotateL       =  optZero $ function2 "rotateL" fullProp (liftInt B.rotateL)+  rotateR       :: Data a -> Data DefaultInt -> Data a+  rotateR       =  optZero $ function2 "rotateR" fullProp (liftInt B.rotateR)+  reverseBits   :: Data a -> Data a+  reverseBits   =  function1 "reverseBits" fullProp evalReverseBits++  -- Bulk bit operations+  -- | Returns the number of leading zeroes for unsigned types.+  -- For signed types it returns the number of unnecessary sign bits+  bitScan       :: Data a -> Data Index+  bitScan       =  function1 "bitScan" fullProp (fromIntegral . evalBitScan)+  bitCount      :: Data a -> Data Index+  bitCount      =  function1 "bitCount" fullProp (fromIntegral . evalBitCount)++  -- Queries about the type+  bitSize       :: Data a -> Data Index+  bitSize       =  function1 "bitSize" (\_ -> naturalRange) (fromIntegral . B.bitSize)+  isSigned      :: Data a -> Data Bool+  isSigned      =  function1 "isSigned" fullProp B.isSigned++-- TODO Some range propagation could be improved.+--      bitSize could have (range 0 32) instead of naturalRange.++liftIntWord :: (a -> Int -> b) -> (a -> DefaultWord -> b)+liftIntWord f x = f x . fromIntegral++liftInt :: (a -> Int -> b) -> (a -> DefaultInt -> b)+liftInt f x = f x . fromIntegral++(⊕)  :: Bits a => Data a -> Data a -> Data a+(⊕)  =  xor+(<<) :: Bits a => Data a -> Data Index -> Data a+(<<) =  shiftLU+(>>) :: Bits a => Data a -> Data Index -> Data a+(>>) =  shiftRU++optAnd :: (Bits a) =>+          (Size a -> Size a -> Size a)+       -> Data a -> Data a -> Data a+optAnd rangeProp x y =+    case (viewLiteral x, viewLiteral y) of+      (Just 0, _) -> value 0+      (_, Just 0) -> value 0+      (Just x, _) | isAllOnes x -> y+      (_, Just y) | isAllOnes y -> x+      _ -> function2 "(.&.)" rangeProp (B..&.) x y++optOr :: (Bits a) =>+         (Size a -> Size a -> Size a)+      -> Data a -> Data a -> Data a+optOr rangeProp x y =+    case (viewLiteral x, viewLiteral y) of+      (Just 0, _) -> y+      (_, Just 0) -> x+      (Just x, _) | isAllOnes x -> value allOnes+      (_, Just y) | isAllOnes y -> value allOnes+      _ -> function2 "(.|.)" rangeProp (B..|.) x y++optXor :: (Bits a) =>+          (Size a -> Size a -> Size a)+       -> Data a -> Data a -> Data a+optXor rangeProp x y =+    case (viewLiteral x, viewLiteral y) of+      (Just 0, _) -> y+      (_, Just 0) -> x+      (Just x, _) | isAllOnes x -> complement y+      (_, Just y) | isAllOnes y -> complement x+      _ -> function2 "xor" rangeProp B.xor x y++isAllOnes :: B.Bits a => a -> Bool+isAllOnes x = x Prelude.== B.complement 0++allOnes :: B.Bits a => a+allOnes = B.complement 0++optZero :: (Type n, Num n) => (a -> Data n -> a) -> a -> Data n -> a+optZero f x y = case viewLiteral y of+                  Just 0 -> x+                  _      -> f x y++evalBitScan :: B.Bits b => b -> Word+evalBitScan b =+   if B.isSigned b+   then scanLoop b (B.testBit b (B.bitSize b - 1)) (B.bitSize b - 2) 0+         else scanLoop b False (B.bitSize b - 1) 0+  where+    scanLoop b bit i n | i Prelude.< 0                = n+    scanLoop b bit i n | B.testBit b i Prelude./= bit = n+    scanLoop b bit i n | otherwise                    = scanLoop b bit (i-1) (n+1)++evalBitCount :: B.Bits b => b -> Word+evalBitCount b = loop b (B.bitSize b - 1) 0+  where+    loop b i n | i Prelude.< 0 = n+    loop b i n | B.testBit b i = loop b (i-1) (n+1)+    loop b i n | otherwise     = loop b (i-1) n++evalReverseBits :: B.Bits b => b -> b+evalReverseBits b = revLoop b 0 (0 `asTypeOf` b)+  where+    bitSize = B.bitSize b+    revLoop b i n | i Prelude.>= bitSize  = n+    revLoop b i n | B.testBit b i = revLoop b (i+1) (B.setBit n (bitSize - i - 1))+    revLoop b i n | otherwise     = revLoop b (i+1) n++{- TODO+   This is a hack until we have proper size information for DefaultWord.+   We do not want the Range module to have to know about DefaultWord so+   we patch the types for this range propagation function here.+-}+propRangeShiftLU r1 r2+    = rangeShiftLU r1 (mapMonotonic (\ (DefaultWord a) -> a) r2)+propRangeShiftRU r1 r2+    = rangeShiftRU r1 (mapMonotonic (\ (DefaultWord a) -> a) r2)+cShiftRU v (DefaultWord i) = correctShiftRU v i++{- TODO+   The reason we have to provide the range propagation functions+   in these instances is that if we would try to do it in the default+   methods of the class we would get a superclass constraint 'Size a ~ Range a'.+   GHC 6.12 doesn't support this.+-}+instance Bits Word8 where+  xor     = optXor rangeXor+  shiftLU = optZero $ function2 "shiftL" propRangeShiftLU (liftIntWord B.shiftL)+  shiftRU = optZero $ function2 "shiftR" propRangeShiftRU cShiftRU+instance Bits Int8 where+  xor = optXor rangeXor+instance Bits Word16 where+  xor = optXor rangeXor+  shiftLU = optZero $ function2 "shiftL" propRangeShiftLU (liftIntWord B.shiftL)+  shiftRU = optZero $ function2 "shiftR" propRangeShiftRU cShiftRU+instance Bits Int16 where+  xor = optXor rangeXor+instance Bits Word32 where+  xor = optXor rangeXor+  shiftLU = optZero $ function2 "shiftL" propRangeShiftLU (liftIntWord B.shiftL)+  shiftRU = optZero $ function2 "shiftR" propRangeShiftRU cShiftRU+instance Bits Int32 where+  xor = optXor rangeXor+instance Bits DefaultWord where+  xor = optXor rangeXor+  shiftLU = optZero $ function2 "shiftL" propRangeShiftLU (liftIntWord B.shiftL)+  shiftRU = optZero $ function2 "shiftR" propRangeShiftRU cShiftRU+instance Bits DefaultInt where+  xor = optXor rangeXor+
+ Feldspar/Core/Functions/Complex.hs view
@@ -0,0 +1,51 @@+-- | Complex numbers++module Feldspar.Core.Functions.Complex where++++import Data.Complex (Complex (..))+import qualified Data.Complex as C++import Feldspar.Core.Types+import Feldspar.Core.Representation+import Feldspar.Core.Constructs+import Feldspar.Core.Functions.Num++++complex :: (Numeric a, RealFloat a) => Data a -> Data a -> Data (Complex a)+complex = function2 "complex" fullProp (:+)++realPart :: (Numeric a, RealFloat a) => Data (Complex a) -> Data a+realPart = function1 "creal" fullProp C.realPart++imagPart :: (Numeric a, RealFloat a) => Data (Complex a) -> Data a+imagPart = function1 "cimag" fullProp C.imagPart++conjugate :: (Numeric a, RealFloat a) => Data (Complex a) -> Data (Complex a)+conjugate = function1 "conjugate" fullProp C.conjugate++mkPolar :: (Numeric a, RealFloat a) => Data a -> Data a -> Data (Complex a)+mkPolar = function2 "mkPolar" fullProp C.mkPolar++cis :: (Numeric a, RealFloat a) => Data a -> Data (Complex a)+cis = function1 "cis" fullProp C.cis++magnitude :: (Numeric a, RealFloat a) => Data (Complex a) -> Data a+magnitude = function1 "magnitude" fullProp C.magnitude++phase :: (Numeric a, RealFloat a) => Data (Complex a) -> Data a+phase = function1 "phase" fullProp C.phase++polar :: (Numeric a, RealFloat a) => Data (Complex a) -> (Data a, Data a)+polar c = (magnitude c, phase c)++infixl 6 +.++(+.) :: (Numeric a, RealFloat a) => Data a -> Data a -> Data (Complex a)+(+.) = complex++iunit :: (Numeric a, RealFloat a) => Data (Complex a)+iunit = 0 +. 1+
+ Feldspar/Core/Functions/Conversion.hs view
@@ -0,0 +1,46 @@+-- | Type conversion operations++module Feldspar.Core.Functions.Conversion where++import qualified Prelude++import Data.Tagged++import Feldspar.Range+import Feldspar.Prelude+import Feldspar.Core.Types+import Feldspar.Core.Representation+import Feldspar.Core.Constructs+import Feldspar.Core.Functions.Num+import Feldspar.Core.Functions.Integral++++i2f :: (Integral a, Size a ~ Range a) => Data a -> Data Float+i2f = i2n++f2i :: Integral a => Data Float -> Data a+f2i = function1 "f2i" fullProp (Prelude.truncate)++i2n :: forall a b . (Integral a, Numeric b, Size a ~ Range a) =>+       Data a -> Data b+i2n = function1 "i2n" (unTag . prop) (fromInteger.toInteger)+  where prop r = rangeToSize (mapMonotonic toInteger r)+        unTag :: Tagged b (Size b) -> Size b+        unTag (Tagged sz) = sz++b2i :: Integral a => Data Bool -> Data a+b2i = function1 "b2i" fullProp (\b -> if b then 1 else 0)+++truncate :: Integral a => Data Float -> Data a+truncate = f2i++round :: Integral a => Data Float -> Data a+round = function1 "round" fullProp (Prelude.round)++ceiling :: Integral a => Data Float -> Data a+ceiling = function1 "ceiling" fullProp (Prelude.ceiling)++floor :: Integral a => Data Float -> Data a+floor = function1 "floor" fullProp (Prelude.floor)
+ Feldspar/Core/Functions/Eq.hs view
@@ -0,0 +1,98 @@+-- | Equality operations++module Feldspar.Core.Functions.Eq where++import qualified Prelude+import Data.Complex+import Data.Int+import Data.Word++import Feldspar.Prelude+import Feldspar.Range+import Feldspar.Core.Types+import Feldspar.Core.Representation+import Feldspar.Core.Constructs++infix 4 ==+infix 4 /=++-- | Redefinition of the standard 'Prelude.Eq' class for Feldspar+class Type a => Eq a+  where+    (==) :: Data a -> Data a -> Data Bool+    (==) = defaultEq+    (/=) :: Data a -> Data a -> Data Bool+    (/=) = defaultNeq++defaultEq :: Eq a => Data a -> Data a -> Data Bool+defaultEq a b+    | a Prelude.== b = true+    | otherwise      = function2 "(==)" fullProp (Prelude.==) a b++defaultNeq :: Eq a => Data a -> Data a -> Data Bool+defaultNeq a b+    | a Prelude.== b = false+    | otherwise      = function2 "(/=)" fullProp (Prelude./=) a b++optEq :: (Eq a, BoundedInt b, Size a ~ Range b) =>+    Data a -> Data a -> Data Bool+optEq a b+    | sa `disjoint` sb = false+    | otherwise        = defaultEq a b+  where+    sa = dataSize a+    sb = dataSize b++optNeq :: (Eq a, BoundedInt b, Size a ~ Range b) =>+    Data a -> Data a -> Data Bool+optNeq a b+    | sa `disjoint` sb = true+    | otherwise        = defaultNeq a b+   where+     sa = dataSize a+     sb = dataSize b++instance Eq ()+instance Eq Bool+instance Eq Float++instance Eq Word8 where+  (==) = optEq+  (/=) = optNeq++instance Eq Int8 where+  (==) = optEq+  (/=) = optNeq++instance Eq Word16 where+  (==) = optEq+  (/=) = optNeq++instance Eq Int16 where+  (==) = optEq+  (/=) = optNeq++instance Eq Word32 where+  (==) = optEq+  (/=) = optNeq++instance Eq Int32 where+  (==) = optEq+  (/=) = optNeq++instance Eq DefaultWord where+  (==) = optEq+  (/=) = optNeq++instance Eq DefaultInt where+  (==) = optEq+  (/=) = optNeq++instance (Eq a, RealFloat a) => Eq (Complex a)++instance Eq a => Eq [a]++instance (Eq a, Eq b)             => Eq (a,b)+instance (Eq a, Eq b, Eq c)       => Eq (a,b,c)+instance (Eq a, Eq b, Eq c, Eq d) => Eq (a,b,c,d)+
+ Feldspar/Core/Functions/Floating.hs view
@@ -0,0 +1,31 @@+-- | This module provides+--+-- @instance (`Fractional'` a, `Floating` a) => `Floating` (`Data` a)@++module Feldspar.Core.Functions.Floating where++import Feldspar.Core.Types+import Feldspar.Core.Representation+import Feldspar.Core.Constructs+import Feldspar.Core.Functions.Fractional++instance (Fractional' a, Floating a) => Floating (Data a) where+  pi        = value Prelude.pi+  exp       = function1 "exp"     fullProp Prelude.exp+  sqrt      = function1 "sqrt"    fullProp Prelude.sqrt+  log       = function1 "log"     fullProp Prelude.log+  (**)      = function2 "(**)"    fullProp (Prelude.**)+  logBase   = function2 "logBase" fullProp Prelude.logBase+  sin       = function1 "sin"     fullProp Prelude.sin+  tan       = function1 "tan"     fullProp Prelude.tan+  cos       = function1 "cos"     fullProp Prelude.cos+  asin      = function1 "asin"    fullProp Prelude.asin+  atan      = function1 "atan"    fullProp Prelude.atan+  acos      = function1 "acos"    fullProp Prelude.acos+  sinh      = function1 "sinh"    fullProp Prelude.sinh+  tanh      = function1 "tanh"    fullProp Prelude.tanh+  cosh      = function1 "cosh"    fullProp Prelude.cosh+  asinh     = function1 "asinh"   fullProp Prelude.asinh+  atanh     = function1 "atanh"   fullProp Prelude.atanh+  acosh     = function1 "acosh"   fullProp Prelude.acosh+
+ Feldspar/Core/Functions/Fractional.hs view
@@ -0,0 +1,29 @@+module Feldspar.Core.Functions.Fractional where++import Data.Complex++import Feldspar.Core.Types+import Feldspar.Core.Representation+import Feldspar.Core.Constructs+import Feldspar.Core.Functions.Num++-- | Fractional types. The relation to the standard 'Fractional' class is+--+-- @instance `Frational'` a => `Fractional` (`Data` a)@+class (Fractional a, Numeric a) => Fractional' a+  where+    fromRationalFrac :: Rational -> Data a+    fromRationalFrac = value . fromRational++    divFrac :: Data a -> Data a -> Data a+    divFrac = function2 "(/)" fullProp (/)++instance Fractional' Float++instance (Fractional' a, RealFloat a) => Fractional' (Complex a)++instance Fractional' a => Fractional (Data a)+  where+    fromRational = fromRationalFrac+    (/)          = divFrac+
+ Feldspar/Core/Functions/Integral.hs view
@@ -0,0 +1,133 @@+module Feldspar.Core.Functions.Integral where++import qualified Prelude+import Data.Int+import Data.Word++import Feldspar.Prelude+import Feldspar.Range+import Feldspar.Core.Types+import Feldspar.Core.Representation+import Feldspar.Core.Constructs+import Feldspar.Core.Functions.Logic+import Feldspar.Core.Functions.Eq+import Feldspar.Core.Functions.Ord+import Feldspar.Core.Functions.Num+import Feldspar.Core.Functions.Bits++-- | Redefinition of the standard 'Prelude.Integral' class for Feldspar+class (Numeric a, BoundedInt a, Bits a, Ord a) => Integral a where+  quot :: Data a -> Data a -> Data a+  quot =  defaultQuot+  rem  :: Data a -> Data a -> Data a+  div  :: Data a -> Data a -> Data a+  div  =  defaultDiv+  mod  :: Data a -> Data a -> Data a+  mod  =  defaultMod+  (^)  :: Data a -> Data a -> Data a+  (^)  =  optExp fullProp++-- TODO Should (^) really be in this class? The standard function has type+--+--     (Num a, Integral b) => a -> b -> a++defaultQuot :: Integral a => Data a -> Data a -> Data a+defaultQuot = function2 "quot" fullProp Prelude.quot++optQuot :: (Integral a, BoundedInt a, Size a ~ Range a) =>+          Data a -> Data a -> Data a+optQuot x y = function2 "quot" rangeQuot Prelude.quot x y++defaultDiv :: Integral a => Data a -> Data a -> Data a+defaultDiv x y = rem x y /= 0 && (x > 0 && y < 0 || x < 0 && y > 0) ?+                   (quotxy - 1, quotxy)+  where+    quotxy = quot x y++defaultMod :: Integral a => Data a -> Data a -> Data a+defaultMod x y = remxy /= 0 && (x > 0 && y < 0 || x < 0 && y > 0) ?+                   (remxy + y, remxy)+  where+    remxy = rem x y++optRem :: (Integral a, BoundedInt a, Size a ~ Range a) =>+          Data a -> Data a -> Data a+optRem x y+    -- -- | abs rx `rangeLess` abs ry = x+        -- This optimization is invalid if x == (-128) and 'a' is Int8+    | otherwise                 = function2 "rem" rangeRem Prelude.rem x y+    where rx = dataSize x+          ry = dataSize y+  -- TODO Use as default implementation of 'rem', when equality is allowed as+  --      super class constraint (i.e. Size a ~ Range a).++optMod :: (Integral a, BoundedInt b, Size a ~ Range b) =>+          Data a -> Data a -> Data a+optMod x y = cap (rangeMod rx ry) $+             remxy /= 0 && (x > 0 && y < 0 || x < 0 && y > 0) ?+             (remxy + y, remxy)+  where remxy = rem x y+        rx    = dataSize x+        ry    = dataSize y++optExp :: Integral a =>+          (Size a -> Size a -> Size a)+       -> Data a -> Data a -> Data a+optExp prop m e = case (viewLiteral m, viewLiteral e) of+               (Just 1,_) -> value 1+               (_,Just 1) -> m+               (_,Just 0) -> value 1+               _          -> function2 "(^)" prop (Prelude.^) m e++optSignedExp :: (Integral a, Signed a, BoundedInt b, Size a ~ Range b) =>+                Data a -> Data a -> Data a+optSignedExp m e = case viewLiteral m of+                   -- From Bit Twiddling Hacks+                   -- "Conditionally negate a value without branching"+                   -- Here we negate the value 1 if isOdd is true i.e. when e is+                   -- and odd number+                     Just (-1) -> cap (range (-1) 1) $+                                    let isOdd = e .&. 1+                                    in (1 `xor` (negate isOdd)) + isOdd+                     _ -> optExp rangeExp m e++instance Integral Word8 where+  div = optQuot+  rem = optRem+  mod = rem++instance Integral Int8 where+  rem = optRem+  mod = optMod+  (^) = optSignedExp++instance Integral Word16 where+  div = optQuot+  rem = optRem+  mod = rem++instance Integral Int16 where+  rem = optRem+  mod = optMod+  (^) = optSignedExp++instance Integral Word32 where+  div = optQuot+  rem = optRem+  mod = rem++instance Integral Int32 where+  rem = optRem+  mod = optMod+  (^) = optSignedExp++instance Integral DefaultWord where+  div = optQuot+  rem = optRem+  mod = rem++instance Integral DefaultInt where+  rem = optRem+  mod = optMod+  (^) = optSignedExp+
+ Feldspar/Core/Functions/Logic.hs view
@@ -0,0 +1,38 @@+module Feldspar.Core.Functions.Logic where++import Feldspar.Core.Types+import Feldspar.Core.Representation+import Feldspar.Core.Constructs++infixr 3 &&+infixr 3 &&*+infixr 2 ||+infixr 2 ||*++not :: Data Bool -> Data Bool+not = function1 "not" fullProp Prelude.not++(&&) :: Data Bool -> Data Bool -> Data Bool+x && y = case (viewLiteral x, viewLiteral y) of+           (Just True, _) -> y+           (Just False,_) -> false+           (_, Just True) -> x+           (_,Just False) -> false+           _              -> function2 "(&&)" fullProp (Prelude.&&) x y++(||) :: Data Bool -> Data Bool -> Data Bool+x || y = case (viewLiteral x, viewLiteral y) of+           (Just True, _) -> true+           (Just False,_) -> y+           (_, Just True) -> true+           (_,Just False) -> x+           _              -> function2 "(||)" fullProp (Prelude.||) x y++-- | Lazy conjunction, second argument only evaluated if necessary+(&&*) :: Data Bool -> Data Bool -> Data Bool+a &&* b = condition a b false++-- | Lazy disjunction, second argument only evaluated if necessary+(||*) :: Data Bool -> Data Bool -> Data Bool+a ||* b = condition a true b+
+ Feldspar/Core/Functions/Num.hs view
@@ -0,0 +1,179 @@+-- | Numeric operations++module Feldspar.Core.Functions.Num where++import Data.Complex+import Data.Int+import Data.Word++import Data.Tagged++import Feldspar.Range+import Feldspar.Core.Types+import Feldspar.Core.Representation+import Feldspar.Core.Constructs++-- | Numeric types. The relation to the standard 'Num' class is+--+-- @instance `Numeric` a => `Num` (`Data` a)@+class (Type a, Num a, FullProp (Size a)) => Numeric a+  where+    fromIntegerNum :: Integer -> Data a+    fromIntegerNum = value . fromInteger++    absNum    :: Data a -> Data a+    absNum    =  defaultAbs fullProp+    signumNum :: Data a -> Data a+    signumNum =  defaultSignum fullProp+    addNum    :: Data a -> Data a -> Data a+    addNum    =  defaultAdd fullProp+    subNum    :: Data a -> Data a -> Data a+    subNum    =  defaultSub fullProp+    mulNum    :: Data a -> Data a -> Data a+    mulNum    =  defaultMul fullProp++    rangeToSize :: Range Integer -> Tagged a (Size a)+    rangeToSize _ = Tagged fullProp++defaultAbs :: Numeric a => (Size a -> Size a) -> Data a -> Data a+defaultAbs szProp = function1 "abs" szProp abs++defaultSignum :: Numeric a => (Size a -> Size a) -> Data a -> Data a+defaultSignum szProp = function1 "signum" szProp signum++defaultAdd :: Numeric a =>+    (Size a -> Size a -> Size a) -> Data a -> Data a -> Data a+defaultAdd szProp = function2 "(+)" szProp (+)++defaultSub :: Numeric a =>+    (Size a -> Size a -> Size a) -> Data a -> Data a -> Data a+defaultSub szProp = function2 "(-)" szProp (-)++defaultMul :: Numeric a =>+    (Size a -> Size a -> Size a) -> Data a -> Data a -> Data a+defaultMul szProp = function2 "(*)" szProp (*)++optAbs :: (Numeric a, BoundedInt b, Size a ~ Range b) => Data a -> Data a+optAbs x | isNatural rx = x+         | otherwise    = defaultAbs abs x+  where rx = dataSize x++optSignum :: (Numeric a, BoundedInt b, Size a ~ Range b) => Data a -> Data a+optSignum x | 0  `rangeLess` rx =  1+            | rx `rangeLess` 0  = -1+            | rx Prelude.==  0  =  0+            | otherwise         = defaultSignum signum x+  where rx = dataSize x++optAdd :: (Numeric a, Num (Size a)) => Data a -> Data a -> Data a+optAdd x y = case (viewLiteral x, viewLiteral y) of+               (Just 0, _) -> y+               (_, Just 0) -> x+               _           -> defaultAdd (+) x y++optSub  :: (Numeric a, Num (Size a)) => Data a -> Data a -> Data a+optSub x y = case viewLiteral y of+               Just 0 -> x+               _      -> defaultSub (-) x y++optMul :: (Numeric a, Num (Size a)) => Data a -> Data a -> Data a+optMul x y = case (viewLiteral x, viewLiteral y) of+               (Just 0,_) -> value 0+               (_,Just 0) -> value 0+               (Just 1,_) -> y+               (_,Just 1) -> x+               _          -> defaultMul (*) x y++rangeProp :: forall a . (Bounded a, Integral a, Size a ~ Range a) =>+             Range Integer -> Tagged a (Size a)+rangeProp (Range l u)+    | withinBounds l && withinBounds u+        = Tagged $ range (fromIntegral l) (fromIntegral u)+    | otherwise = Tagged (range minBound maxBound)+  where withinBounds i = toInteger (minBound :: a) <= i &&+                         i <= toInteger (maxBound :: a)++instance Numeric Word8+  where+    absNum      = optAbs+    signumNum   = optSignum+    addNum      = optAdd+    subNum      = optSub+    mulNum      = optMul+    rangeToSize = rangeProp++instance Numeric Int8+  where+    absNum      = optAbs+    signumNum   = optSignum+    addNum      = optAdd+    subNum      = optSub+    mulNum      = optMul+    rangeToSize = rangeProp++instance Numeric Word16+  where+    absNum      = optAbs+    signumNum   = optSignum+    addNum      = optAdd+    subNum      = optSub+    mulNum      = optMul+    rangeToSize = rangeProp++instance Numeric Int16+  where+    absNum      = optAbs+    signumNum   = optSignum+    addNum      = optAdd+    subNum      = optSub+    mulNum      = optMul+    rangeToSize = rangeProp++instance Numeric Word32+  where+    absNum      = optAbs+    signumNum   = optSignum+    addNum      = optAdd+    subNum      = optSub+    mulNum      = optMul+    rangeToSize = rangeProp++instance Numeric Int32+  where+    absNum      = optAbs+    signumNum   = optSignum+    addNum      = optAdd+    subNum      = optSub+    mulNum      = optMul+    rangeToSize = rangeProp++instance Numeric DefaultWord+  where+    absNum      = optAbs+    signumNum   = optSignum+    addNum      = optAdd+    subNum      = optSub+    mulNum      = optMul+    rangeToSize = rangeProp++instance Numeric DefaultInt+  where+    absNum      = optAbs+    signumNum   = optSignum+    addNum      = optAdd+    subNum      = optSub+    mulNum      = optMul+    rangeToSize = rangeProp++instance Numeric Float+instance (Type a, RealFloat a) => Numeric (Complex a)++instance Numeric a => Num (Data a)+  where+    fromInteger = fromIntegerNum+    abs         = absNum+    signum      = signumNum+    (+)         = addNum+    (-)         = subNum+    (*)         = mulNum+
+ Feldspar/Core/Functions/Ord.hs view
@@ -0,0 +1,185 @@+module Feldspar.Core.Functions.Ord where++import qualified Prelude+import Data.Int+import Data.Word++import Feldspar.Prelude+import Feldspar.Range+import Feldspar.Core.Types+import Feldspar.Core.Representation+import Feldspar.Core.Constructs+import Feldspar.Core.Functions.Eq++infix 4 <+infix 4 >+infix 4 <=+infix 4 >=++-- | Redefinition of the standard 'Prelude.Ord' class for Feldspar+class (Eq a, Prelude.Ord a) => Ord a where+  (<)  :: Data a -> Data a -> Data Bool+  (<)  =  defaultLT+  (>)  :: Data a -> Data a -> Data Bool+  (>)  =  defaultGT++  (<=) :: Data a -> Data a -> Data Bool+  (<=) =  defaultLTE+  (>=) :: Data a -> Data a -> Data Bool+  (>=) =  defaultGTE++  min :: Data a -> Data a -> Data a+  min a b = a<b ? (a,b)+  max :: Data a -> Data a -> Data a+  max a b = a>b ? (a,b)++defaultLT a b+    | a Prelude.== b = false+    | otherwise      = function2 "(<)" fullProp (Prelude.<) a b++defaultGT a b+    | a Prelude.== b = false+    | otherwise      = function2 "(>)" fullProp (Prelude.>) a b++defaultLTE a b+    | a Prelude.== b = true+    | otherwise      = function2 "(<=)" fullProp (Prelude.<=) a b++defaultGTE a b+    | a Prelude.== b = true+    | otherwise      = function2 "(>=)" fullProp (Prelude.>=) a b++optLT :: (Ord a, BoundedInt b, Size a ~ Range b) =>+         Data a -> Data a -> Data Bool+optLT a b+    | a Prelude.== b      = false+    | sa `rangeLess`   sb = true+    | sb `rangeLessEq` sa = false+    | otherwise           = defaultLT a b+    where+      sa = dataSize a+      sb = dataSize b++optGT :: (Ord a, BoundedInt b, Size a ~ Range b) =>+         Data a -> Data a -> Data Bool+optGT a b+    | a Prelude.== b      = false+    | sb `rangeLess`   sa = true+    | sa `rangeLessEq` sb = false+    | otherwise           = defaultGT a b+    where+      sa = dataSize a+      sb = dataSize b++optLTE :: (Ord a, BoundedInt b, Size a ~ Range b) =>+          Data a -> Data a -> Data Bool+optLTE a b+    | a Prelude.== b      = true+    | sa `rangeLessEq` sb = true+    | sb `rangeLess`   sa = false+    | otherwise           = defaultLTE a b+    where+      sa = dataSize a+      sb = dataSize b++optGTE :: (Ord a, BoundedInt b, Size a ~ Range b) =>+          Data a -> Data a -> Data Bool+optGTE a b+    | a Prelude.== b      = true+    | sb `rangeLessEq` sa = true+    | sa `rangeLess`   sb = false+    | otherwise           = defaultGTE a b+    where+      sa = dataSize a+      sb = dataSize b++optMin :: (Ord a, BoundedInt b, Size a ~ Range b) => Data a -> Data a -> Data a+optMin a b = cap (rangeMin ra rb) $+    case viewLiteral cond1 of+      Just _ -> cond1 ? (a,b)+      _      -> cond2 ? (b,a)+  where+    cond1 = a<b+    cond2 = b<a+    ra    = dataSize a+    rb    = dataSize b++optMax :: (Ord a, BoundedInt b, Size a ~ Range b) => Data a -> Data a -> Data a+optMax a b = cap (rangeMax ra rb) $+    case viewLiteral cond1 of+      Just _ -> cond1 ? (a,b)+      _      -> cond2 ? (b,a)+  where+    cond1 = a>b+    cond2 = b>a+    ra    = dataSize a+    rb    = dataSize b++instance Ord ()+instance Ord Bool+instance Ord Float++instance Ord Word8 where+  (<)  = optLT+  (>)  = optGT+  (<=) = optLTE+  (>=) = optGTE+  min  = optMin+  max  = optMax++instance Ord Int8 where+  (<)  = optLT+  (>)  = optGT+  (<=) = optLTE+  (>=) = optGTE+  min  = optMin+  max  = optMax++instance Ord Word16 where+  (<)  = optLT+  (>)  = optGT+  (<=) = optLTE+  (>=) = optGTE+  min  = optMin+  max  = optMax++instance Ord Int16 where+  (<)  = optLT+  (>)  = optGT+  (<=) = optLTE+  (>=) = optGTE+  min  = optMin+  max  = optMax++instance Ord Word32 where+  (<)  = optLT+  (>)  = optGT+  (<=) = optLTE+  (>=) = optGTE+  min  = optMin+  max  = optMax++instance Ord Int32 where+  (<)  = optLT+  (>)  = optGT+  (<=) = optLTE+  (>=) = optGTE+  min  = optMin+  max  = optMax++instance Ord DefaultWord where+  (<)  = optLT+  (>)  = optGT+  (<=) = optLTE+  (>=) = optGTE+  min  = optMin+  max  = optMax++instance Ord DefaultInt where+  (<)  = optLT+  (>)  = optGT+  (<=) = optLTE+  (>=) = optGTE+  min  = optMin+  max  = optMax+
+ Feldspar/Core/Functions/Trace.hs view
@@ -0,0 +1,21 @@+-- | Tracing execution of Feldspar expressions++module Feldspar.Core.Functions.Trace where++++import Feldspar.Core.Types+import Feldspar.Core.Representation+import Feldspar.Core.Constructs+import Feldspar.Core.Functions.Num++++-- | Tracing execution of an expression. Semantically, this is the identity+-- function, but a back end may treat this function specially, for example write+-- its arguments to a log.+trace :: Numeric a => Int -> Data a -> Data a+trace label = function2 "trace" (const id) (const id) label'+  where+    label' = fromIntegral label :: Data DefaultInt+
+ Feldspar/Core/Functions/Tuple.hs view
@@ -0,0 +1,39 @@+-- | Tuple construction/destruction++module Feldspar.Core.Functions.Tuple where++++import Feldspar.DSL.Expression+import Feldspar.DSL.Lambda+import Feldspar.DSL.Network+import Feldspar.Core.Types+import Feldspar.Core.Representation+import Feldspar.Core.Constructs++++pair :: (Type a, Type b) => Data a -> Data b -> Data (a,b)+pair (Data a) (Data b) = case (undoEdge a, undoEdge b) of+             (  Inject (Node (Function "getFst" _)) :$: a'+              , Inject (Node (Function "getSnd" _)) :$: b'+              ) | exprEq a' b', Just ab <- exprCast b' -> Data ab+             _ -> nodeData (edgeSize $ edgeInfo a, edgeSize $ edgeInfo b) $ Inject (Node Pair) :$: a :$: b++getFst :: (Type a, Type b) => Data (a,b) -> Data a+getFst (Data ab) = case undoEdge ab of+    Inject (Node Pair) :$: a :$: _ -> Data a+    _ -> function1 "getFst" fst fst (Data ab)++getSnd :: (Type a, Type b) => Data (a,b) -> Data b+getSnd (Data ab) = case undoEdge ab of+    Inject (Node Pair) :$: _ :$: b -> Data b+    _ -> function1 "getSnd" snd snd (Data ab)++-- | Convenient together with view patterns:+--+-- > f :: Data (a,b) -> ...+-- > f (matchPair -> (a,b)) = ...+matchPair :: (Type a, Type b) => Data (a,b) -> (Data a, Data b)+matchPair ab = (getFst ab, getSnd ab)+
− Feldspar/Core/Graph.hs
@@ -1,555 +0,0 @@------ Copyright (c) 2009-2010, ERICSSON AB All rights reserved.--- --- Redistribution and use in source and binary forms, with or without--- modification, are permitted provided that the following conditions are met:--- ---     * Redistributions of source code must retain the above copyright notice,---       this list of conditions and the following disclaimer.---     * 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 name of the ERICSSON AB nor the names of its contributors---       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 AND CONTRIBUTORS "AS IS"--- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE--- IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE--- ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS--- BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,--- OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF--- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS--- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN--- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)--- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF--- THE POSSIBILITY OF SUCH DAMAGE.------- | A graph representation of core programs. A graph is a flat structure that--- can be viewed as a program with a global scope. For example, the Haskell--- program------ > main x = f 1--- >   where--- >     f y = g 2--- >       where--- >         g z = x + z------ might be represented by the following flat graph:------ > graph = Graph--- >   { graphNodes =--- >       [ Node--- >           { nodeId     = 0--- >           , function   = Input--- >           , input      = Tup []--- >           , inputType  = Tup []--- >           , outputType = intType--- >           }--- >       , Node--- >           { nodeId     = 1--- >           , function   = Input--- >           , input      = Tup []--- >           , inputType  = Tup []--- >           , outputType = intType--- >           }--- >       , Node--- >           { nodeId     = 2--- >           , function   = Input--- >           , input      = Tup []--- >           , inputType  = Tup []--- >           , outputType = intType--- >           }--- >       , Node--- >           { nodeId     = 3--- >           , function   = Function "(+)"--- >           , input      = Tup [One (Variable (0,[])), One (Variable (2,[]))]--- >           , inputType  = intPairType--- >           , outputType = intType--- >           }--- >       , Node--- >           { nodeId     = 4--- >           , function   = NoInline "f" (Interface 1 (One (Variable (5,[]))) intType intType)--- >           , input      = One (Constant (IntData 1))--- >           , inputType  = intType--- >           , outputType = intType--- >           }--- >       , Node--- >           { nodeId     = 5--- >           , function   = NoInline "g" (Interface 2 (One (Variable (3,[]))) intType intType)--- >           , input      = One (Constant (IntData 2))--- >           , inputType  = intType--- >           , outputType = intType--- >           }--- >       ]--- >--- >   , graphInterface = Interface--- >       { interfaceInput      = 0--- >       , interfaceOutput     = One (Variable (4,[]))--- >       , interfaceInputType  = intType--- >       , interfaceOutputType = intType--- >       }--- >   }--- >   where--- >     intType     = result (typeOf :: Res [[[Int]]] (Tuple StorableType))--- >     intPairType = result (typeOf :: Res (Int,Int) (Tuple StorableType))------ XXX Check above code again------ which corresponds to the following flat program------ > main v0 = v4--- > f v1    = v5--- > g v2    = v3--- > v3      = v0 + v2--- > v4      = f 1--- > v5      = g 2------ There are a few assumptions on graphs:------ * All nodes have unique identifiers.------ * There are no cycles.------ * The 'input' and 'inputType' tuples of each node should have the same shape.------ * Each 'interfaceInput' (including the top-level one) refers to an 'Input'--- node not referred to by any other interface.------ * All 'Variable' references are valid (i.e. refer only to those variables--- implicitly defined by each node).------ * There should not be any cycles in the constraints introduced by--- 'findLocalities'. (XXX Is this even possible?)------ * Sub-function interfaces should be \"consistent\" with the input/output type--- of the node. For example, the body of a while loop should have the same type--- as the whole loop.------ In the original program, @g@ was defined locally to @f@, and the addition was--- done locally in @g@. But in the flat program, this hierarchy (called--- /definition hierarchy/) is not represented. The flat program is of course not--- valid Haskell (@v0@ and @v2@ are used outside of their scopes). The function--- 'makeHierarchical' turns a flat graph into a hierarchical one that--- corresponds to syntactically valid Haskell.------ 'makeHierarchical' requires some explanation. First a few definitions:------ * Nodes that have associated interfaces ('NoInline', 'IfThenElse', 'While'--- and 'Parallel') are said to contain /sub-functions/. These nodes are called--- /super nodes/. In the above program, the super node @v4@ contains the--- sub-function @f@, and @v5@ contains the sub-function @g@.------ * A definition @d@ is /local/ to a definition @e@ iff. @d@ is placed--- somewhere within the definition of @e@ (i.e. inside an arbitrarily deeply--- nested @where@ clause).------ * A definition @d@ is /owned/ by a definition @e@ iff. @d@ is placed--- immediately under the top-most @where@ clause of @e@. A definition may have--- at most one owner.------ The definition hierarchy thus specifies ownership between the definitions in--- the program. There are two types of ownership:------ * A super node is always the owner of its sub-functions.------ * A sub-function may be the owner of some node definitions.------ Assigning nodes to sub-functions in a useful way takes some work. It is done--- by first finding out for each node which sub-functions it must be local to.--- Each locality constraint gives an upper bound on where in the definition--- hierarchy the node may be placed. There is one principle for introducing a--- locality constraint:------ * If node @v@ depends on the input of sub-function @f@, then @v@ must be--- local to @f@.------ The locality constraints for a graph can thus be found be tracing each--- sub-function input in order to find the nodes that depend on it (see function--- 'findLocalities'). In the above program, we have the sub-functions @f@ and--- @g@ with the inputs @v1@ and @v2@ respectively. We can see immediately that--- no node depends on @v1@, so we get no locality constraints for @f@. The only--- node that depends on @v2@ is @v3@, so the program has a single locality--- constraint: @v3@ is local to @g@. Nodes without constraints are simply taken--- to be local to @main@. With this information, we can now rewrite the flat--- program as------ > main v0 = v4--- >   where--- >     v4 = f 1--- >       where--- >         f v1 = v5--- >     v5 = g 2--- >       where--- >         g v2 = v3--- >           where--- >             v3 = v0 + v2------ which is syntactically valid Haskell. Note that this program is slightly--- different from the original which defined @g@ locally to @f@. However, in--- general, we want definitions to be as \"global\" as possible in order to--- maximize sharing. For example, we don't want to put definitions in the body--- of a while loop unless they really depend on the loop state, because then--- they will (probably, depending on implementation) be recomputed in every--- iteration. Also note that in this program, it is not strictly necessary to--- have the sub-functions owned by their super nodes -- @f@ and @g@ could have--- been owned by @main@ instead. However, this would cause clashes if two--- sub-functions have the same name. Having sub-functions owned by their super--- nodes is also a way of keeping related definitions together in the program.------ There is one caveat with the above method. Consider the following flat--- program:------ > main v0 = v4--- > f v1    = v5--- > g v2    = v3--- > v3      = v1 + 2--- > v4      = f 0--- > v5      = g 1------ Here, we get the locality constraint: @v3@ is local to @f@. However, to get a--- valid definition hierarchy, we also need @v5@ to be local to @f@. This is--- because @v5@ is the owner of @g@, and the output of @g@ is local to @f@. So--- when looking for dependencies, we should let each super node depend on its--- sub-function output, /except/ for the owner of the very sub-function that is--- being traced (a function cannot be owned by itself).--module Feldspar.Core.Graph where----import qualified Data.Foldable as Fold-import Data.Function-import Data.List-import Data.Map (Map)-import qualified Data.Map as Map--import Feldspar.Utils-import Feldspar.Core.Types------ | Node identifier-type NodeId = Int---- | Variable represented by a node id and a tuple path. For example, in a--- definition (given in Haskell syntax)------ > ((a,b),c) = f x------ the variable @b@ would be represented as @(i,[0,1])@ (where @i@ is the id of--- the @f@ node).-type Variable = (NodeId, [Int])---- | The source of a value is either constant data or a variable.-data Source-  = Constant PrimitiveData-  | Variable Variable-    deriving (Eq, Show)---- | A node in the program graph. The input is given as a 'Source' tuple. The--- output is implicitly defined by the 'nodeId' and the 'outputType'. For--- example, a node with id @i@ and output type------ > Tup [One ..., One ...]------ has the implicit output------ > Tup [One (i,[0]), One (i,[1])]-data Node = Node-  { nodeId     :: NodeId-  , function   :: Function-  , input      :: Tuple Source-  , inputType  :: Tuple StorableType-  , outputType :: Tuple StorableType-  }-    deriving (Eq, Show)---- | The interface of a (sub-)graph. The input is conceptually a--- @Tuple Variable@, but all these variables refer to the same 'Input' node, so--- it is sufficient to track the node id (the tuple shape can be inferred from--- the 'interfaceInputType').-data Interface = Interface-  { interfaceInput      :: NodeId-  , interfaceOutput     :: Tuple Source-  , interfaceInputType  :: Tuple StorableType-  , interfaceOutputType :: Tuple StorableType-  }-    deriving (Eq, Show)---- | Node functionality-data Function-  =-    -- | Primary input-    Input-    -- | Constant array-  | Array StorableData-    -- | Primitive function-  | Function String-    -- | Non-inlined function-  | NoInline String Interface-    -- | Conditional-  | IfThenElse Interface Interface-    -- | While-loop-  | While Interface Interface-    -- | Parallel tiling-  | Parallel Interface-    deriving (Eq, Show)---- | A graph is a list of unique nodes with an interface.-data Graph = Graph-  { graphNodes     :: [Node]-  , graphInterface :: Interface-  }--instance Eq Graph-  where-    Graph ns1 iface1 == Graph ns2 iface2-         = ns1'  == ns2'-        && iface1  == iface2-      where-        ns1' = sortBy (compare `on` nodeId) ns1-        ns2' = sortBy (compare `on` nodeId) ns2-      -- Comparison ignores order of nodes.---- | A definition hierarchy. A hierarchy consists of number of top-level nodes,--- each one associated with its sub-functions, represented as hierarchies. The--- nodes owned by a sub-function appear as the top-level nodes in the--- corresponding hierarchy.-data Hierarchy = Hierarchy [(Node, [Hierarchy])]---- | A graph with a hierarchical ordering of the nodes. If the hierarchy is--- flattened it should result in a valid 'Graph'.-data HierarchicalGraph = HierGraph-  { graphHierarchy     :: Hierarchy-  , hierGraphInterface :: Interface-  }---- | A node that contains a sub-function-type SuperNode = NodeId---- | The branch is used to distinguish between different sub-functions of the--- same super node. For example, the continue condition of a while-loop has--- branch number 0, and the body has number 1 (see 'subFunctions').-data SubFunction = SubFunction-       { sfSuper  :: SuperNode-       , sfBranch :: Int-       , sfInput  :: NodeId-       , sfOutput :: [NodeId]-       }-    deriving (Eq, Show)--instance Ord SubFunction-  where-    compare (SubFunction o1 b1 _ _) (SubFunction o2 b2 _ _) =-        compare (o1,b1) (o2,b2)-      -- Ignores inputs/outputs since these should be equal anyway if the super-      -- and branch fields are equal.---- | Locality constraint-data Local = Local SubFunction NodeId-    deriving (Eq, Show)------ | Returns the nodes in a source tuple.-sourceNodes :: Tuple Source -> [NodeId]-sourceNodes tup = [i | Variable (i,_) <- Fold.toList tup]---- | The fanout of each node in a graph. Nodes that are not in the map are--- assumed to have no fanout.-fanout :: Graph -> Map NodeId [NodeId]-fanout graph = Map.fromListWith (++)-    [ (inp, [nodeId node])-      | node <- graphNodes graph-      , inp  <- sourceNodes (input node)-    ]---- | Look up a node in the graph-nodeMap :: Graph -> (NodeId -> Node)-nodeMap graph = (m Map.!)-  where-    m = Map.fromList [(nodeId node, node) | node <- graphNodes graph]------ | Lists all sub-functions in the graph.-subFunctions :: Graph -> [SubFunction]-subFunctions graph =-    concat [subFun i fun | Node i fun _ _ _ <- graphNodes graph]-  where-    sub i branch (Interface inp outp _ _) =-      SubFunction i branch inp (sourceNodes outp)--    subFun i (NoInline _ f)    = [sub i 0 f]-    subFun i (IfThenElse t e)  = [sub i 0 t, sub i 1 e]-    subFun i (While cont body) = [sub i 0 cont, sub i 1 body]-    subFun i (Parallel ixf)    = [sub i 0 ixf]-    subFun _ _                 = []------ | Lists all locality constraints of the graph.-findLocalities :: Graph -> [Local]-findLocalities graph = concatMap traceSub sfs-  where-    fo  = fanout graph-    sfs = subFunctions graph--    superLink = Map.fromListWith (++)-      [(outp,[super]) | SubFunction super _ _ outps <- sfs, outp <- outps]-      -- Fanout map with edges from sub-function output to super node--    traceSub sf@(SubFunction _ _ inp outps) = trace inp-      where-        trace a = Local sf a : concatMap trace bs-          where-            as = if a `elem` outps then [] else superLink !!! a-            bs = (fo !!! a) ++ as-      -- Computes locality constraints by tracing the dependencies of-      -- sub-function inputs.------ | Returns a total ordering between all super nodes in a graph, such that if--- node @v@ is local to sub-function @f@, then @v@ maps to a lower number than--- the owner of @f@. The converse is not necessarily true. The second argument--- gives the locality constraints for each node in the graph (top-level nodes--- may be left undefined).-orderSuperNodes :: Graph -> Map NodeId [SubFunction] -> Map SuperNode Int-orderSuperNodes graph locals = Map.fromList $ zip (topSort sfOrder) [0..]-  where-    sfOrder = Map.fromListWith (++)-        [ (i, map sfSuper (locals !!! i))-          | SubFunction i _ _ _ <- subFunctions graph-        ]-      -- A partial ordering between all sub-functions. An edge from `f` to `g`-      -- means that `f` is local to `g`. This is a representation of the actual-      -- sub-function ordering which is the transitive closure of `sfOrder`.-      -- `sfOrder` is a dag.---- | Returns the minimal sub-function according to the given owner ordering.-minimalSubFun :: Map SuperNode Int -> [SubFunction] -> SubFunction-minimalSubFun ownOrd = head . sortBy (compare `on` ((ownOrd Map.!) . sfSuper))---- | Sorts the nodes by their id.-sortNodes :: [Node] -> [Node]-sortNodes = sortBy (compare `on` nodeId)------ | Makes a hierarchical graph from a flat one. The node lists in the hierarchy--- are always sorted according to node id.-makeHierarchical :: Graph -> HierarchicalGraph-makeHierarchical graph@(Graph nodes iface) =-    HierGraph (mkHierarchy topLevel) iface-  where-    locs = findLocalities graph--    locals :: Map NodeId [SubFunction]-    locals = Map.fromListWith (++) [(i,[sf]) | Local sf i <- locs]-      -- The locality constraints for each node. Nodes that are not in the map-      -- have no constraints.--    owner :: Map NodeId SubFunction-    owner = fmap (minimalSubFun $ orderSuperNodes graph locals) locals-      -- The owner of each node. Nodes that are not in the map have no owner.--    nodeLookup :: NodeId -> Node-    nodeLookup = nodeMap graph--    mkHierarchy :: [Node] -> Hierarchy-    mkHierarchy nodes = Hierarchy (nodes `zip` map subHierarchies nodes)--    subFunHier :: SuperNode -> Int -> Hierarchy-    subFunHier i branch = mkHierarchy nodes-      where-        ownedBy = fmap (sortNodes . map nodeLookup) $ invertMap owner-        sf      = SubFunction i branch undefined undefined-        nodes   = ownedBy Map.! sf-          -- Defined for every sub-function, because each sub-function contains-          -- at least one node (the input).--    subHierarchies :: Node -> [Hierarchy]-    subHierarchies (Node i (NoInline _ _) _ _ _)   = map (subFunHier i) [0]-    subHierarchies (Node i (IfThenElse _ _) _ _ _) = map (subFunHier i) [0,1]-    subHierarchies (Node i (While _ _) _ _ _)      = map (subFunHier i) [0,1]-    subHierarchies (Node i (Parallel _) _ _ _)     = map (subFunHier i) [0]-    subHierarchies _ = []--    topLevel :: [Node]-    topLevel = sortNodes-        [ nodeLookup i-          | node <- nodes-          , let i = nodeId node-          , Nothing <- [Map.lookup i owner]-        ]-      -- The nodes that don't have any owner---------------------- --- show function --------------------- --instance Show Graph where -  show gr = prP 0 gr --instance Show HierarchicalGraph where -  show hgr = prP 0 hgr ---class PrP a where -    prP :: Int -> a -> String --tab sc = replicate sc ' ' --listprint :: (a->String) -> String -> [a] -> String -listprint _ _ [] = "" -listprint f _ [x] = f x -listprint f s (x:y:xs) = f x ++ s ++ listprint f s (y:xs) --instance PrP Graph where -  prP sc gr = tab sc ++ "Graph {\n" ++ tab (sc + 1) ++ "graphNodes = [\n" ++ prP (sc+2) (graphNodes gr)  -                 ++ "],\n" ++ tab (sc + 1) ++ "graphInterface = \n" ++ tab (sc + 3) ++ show (graphInterface gr) ++ "\n}" --instance PrP [Node] where -  prP sc ns = (listprint (\n -> (tab sc ++ prP sc n)) ",\n" ns) ---  prP sc [] = "" ---  prP sc [node] = tab sc ++ prP sc node ++ "\n" ---  prP sc (node:ns) = tab sc ++ prP sc node ++ ",\n" ++ prP sc ns  --instance PrP Node where -  prP sc node = "Node {nodeId = " ++ show (nodeId node) ++ ",\n"  -                   ++ tab (sc + 6) ++ "function = " ++ prP (sc+8) (function node) ++ ",\n"    -                    ++ tab (sc + 6) ++ "input = " ++ show (input node) ++ ",\n" -                     ++ tab (sc + 6) ++ "inputType = " ++ show (inputType node) ++ ",\n" -                      ++ tab (sc + 6) ++ "outputType = " ++ show (outputType node) ++ "}" --instance PrP Function where -  prP sc (IfThenElse if1 if2) = "\n" ++ tab (sc+1) ++ "IfThenElse\n" ++ tab (sc+2) ++ show if1 ++ "\n" -                                   ++ tab (sc+2) ++ show if2 -  prP sc (Parallel if1) = "\n" ++ tab (sc+1) ++"Parallel " ++ "\n" ++ tab (sc+2) ++ show if1 -  prP sc (While if1 if2) = "\n" ++ tab (sc+1) ++ "While\n" ++ tab (sc+2) ++ show if1 ++ "\n" -                                   ++ tab (sc+2) ++ show if2  -  prP sc (NoInline str if1) = "\n" ++ tab (sc+1) ++ "NoInline \"" ++ str ++"\" \n" ++ tab (sc+2) ++ show if1 -  prP sc x = show x  --instance PrP HierarchicalGraph where -  prP sc hgr = "HierGraph {\n" ++ tab (sc+1) ++ "graphHierarchy =\n" ++ tab (sc+2) ++ prP (sc+2) (graphHierarchy hgr) -                   ++ ",\n" ++ tab (sc+1) ++ "hierGraphInterface =\n" ++  tab (sc+2) ++ show (hierGraphInterface hgr) ++ "\n}" --instance PrP Hierarchy where -  prP sc (Hierarchy ndhrs) = "Hierarchy [\n" ++ prP (sc+1) ndhrs ++ "\n" ++ tab sc ++ "]"  --instance PrP [(Node, [Hierarchy])] where -  prP sc nhrs = (listprint (prP sc) ",\n" nhrs) --- prP sc [] = "" ---  prP sc [(node,hrs)] = tab sc ++ "(" ++ prP (sc+1) node ++ ",\n" ++ prP (sc+1) hrs ++ ")"  ---  prP sc ((node,hrs):ns) = tab sc ++ "(" ++ prP (sc+1) node ++ ",\n" ++ prP (sc+1) hrs ++ "),\n" ++ prP (sc+1) ns --instance PrP (Node, [Hierarchy]) where -  prP sc (node,hrs) = tab sc ++ "(" ++ prP (sc+1) node ++ ",\n" ++ tab sc ++ "[" ++ prP (sc+1) hrs ++ "])" ---instance PrP [Hierarchy] where -  prP sc nhrs = (listprint (prP sc) (",\n" ++ tab sc) nhrs) 
− Feldspar/Core/Ref.hs
@@ -1,98 +0,0 @@------ Copyright (c) 2009-2010, ERICSSON AB All rights reserved.--- --- Redistribution and use in source and binary forms, with or without--- modification, are permitted provided that the following conditions are met:--- ---     * Redistributions of source code must retain the above copyright notice,---       this list of conditions and the following disclaimer.---     * 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 name of the ERICSSON AB nor the names of its contributors---       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 AND CONTRIBUTORS "AS IS"--- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE--- IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE--- ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS--- BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,--- OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF--- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS--- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN--- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)--- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF--- THE POSSIBILITY OF SUCH DAMAGE.------- Copyright (c) 2009 Koen Claessen--- All rights reserved.------ Redistribution and use in source and binary forms, with or without--- modification, are permitted provided that the following conditions are met:------     * Redistributions of source code must retain the above copyright notice,---       this list of conditions and the following disclaimer.---     * 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 name of the Koen Claessen nor the names of its contributors---       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 AND CONTRIBUTORS "AS IS"--- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE--- IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE--- DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE--- FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL--- DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR--- SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER--- CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,--- OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE--- OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.--{-# OPTIONS_GHC -O0 #-}---- |--- A simple implementation of \"observable sharing\". See------ * Koen Claessen, David Sands,--- \"/Observable sharing for functional circuit description/\",--- Asian Computing Science Conference, 1999.------ for more details.--module Feldspar.Core.Ref-  ( Ref-  , refId-  , deref-  , ref-  ) where----import Data.Function-import Data.Unique-import System.IO.Unsafe----data Ref a = Ref-  { refId :: Unique-  , deref :: a-  }--instance Eq (Ref a) where-  (==) = (==) `on` refId--instance Ord (Ref a) where-  compare = compare `on` refId----ref :: a -> Ref a-ref x = unsafePerformIO $ do-     u <- newUnique-     return (Ref u x)-
− Feldspar/Core/Reify.hs
@@ -1,315 +0,0 @@------ Copyright (c) 2009-2010, ERICSSON AB All rights reserved.--- --- Redistribution and use in source and binary forms, with or without--- modification, are permitted provided that the following conditions are met:--- ---     * Redistributions of source code must retain the above copyright notice,---       this list of conditions and the following disclaimer.---     * 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 name of the ERICSSON AB nor the names of its contributors---       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 AND CONTRIBUTORS "AS IS"--- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE--- IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE--- ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS--- BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,--- OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF--- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS--- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN--- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)--- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF--- THE POSSIBILITY OF SUCH DAMAGE.-----{-# LANGUAGE OverlappingInstances, UndecidableInstances #-}---- | Functions for reifying expressions ('Data' / 'Expr') to graphs ('Graph')--- and to textual format.--module Feldspar.Core.Reify-  ( Program (..)-  , showCore-  , showCoreWithSize-  , printCore-  , printCoreWithSize-  , runGraph-  , buildSubFun-  , startInfo-  ) where----import Control.Monad.State-import Control.Monad.Writer-import Data.Map (Map)-import qualified Data.Map as Map-import Data.Maybe-import Data.Unique--import Feldspar.Core.Types-import Feldspar.Core.Ref-import Feldspar.Core.Expr-import Feldspar.Core.Graph hiding (function, Function (..), Variable)-import qualified Feldspar.Core.Graph as Graph-import Feldspar.Core.Show----data Info = Info-  { -- | Next id-    index :: NodeId-    -- | Visited references mapped to their id-  , visited :: Map Unique NodeId-  }---- | Monad for making graph building easier-type Reify a = WriterT [Node] (State Info) a--startInfo :: Info-startInfo = Info 0 Map.empty--runGraph :: Reify a -> Info -> (a, ([Node], Info))-runGraph graph info = (a, (nodes, info'))-  where-    ((a,nodes),info') = runState (runWriterT graph) info--newIndex :: Reify NodeId-newIndex = do-    info <- get-    put (info {index = succ (index info)})-    return (index info)--remember :: Data a -> NodeId -> Reify ()-remember a i = modify $ \info ->-    info {visited = Map.insert (dataId a) i (visited info)}--checkNode :: Data a -> Reify (Maybe NodeId)-checkNode a = gets ((Map.lookup (dataId a)) . visited)------ | Declare a node-node ::-    Data a -> Graph.Function -> Tuple Source -> Tuple StorableType -> Reify ()--node a@(Data _ _) fun inTup inType = do-    i <- newIndex-    remember a i-    tell [Node i fun inTup inType (dataType a)]------ | Declare a source node (one with no inputs)-sourceNode :: Data a -> Graph.Function -> Reify ()-sourceNode a fun = node a fun (Tup []) (Tup [])--isPrimitive :: Data a -> Bool-isPrimitive a@(Data _ _) = case dataType a of-    One (StorableType [] _) -> True-    _ -> False---- Creates a source. The node must have been visited.-source :: [Int] -> Data a -> Reify Source-source path a = case dataToExpr a of--    Application (Function ('g':'e':'t':'T':'u':'p':_:n:_) _) tup ->-      source ((read [n] - 1) : path) tup-        -- XXX This is a bit fragile...--    Value b | isPrimitive a ->-      let PrimitiveData b' = storableData b-       in return $ Constant b'--    _ -> do-      Just i <- checkNode a-      return $ Graph.Variable (i,path)----traceTuple :: Data a -> Reify (Tuple Source)-traceTuple a = case dataToExpr a of--    Application (Application (Function "tup2" _) b) c -> do-      b' <- traceTuple b-      c' <- traceTuple c-      return (Tup [b',c'])--    Application (Application (Application (Function "tup3" _) b) c) d -> do-      b' <- traceTuple b-      c' <- traceTuple c-      d' <- traceTuple d-      return (Tup [b',c',d'])--    Application (Application (Application (Application-                                            (Function "tup4" _) b) c) d) e -> do-      b' <- traceTuple b-      c' <- traceTuple c-      d' <- traceTuple d-      e' <- traceTuple e-      return (Tup [b',c',d',e'])--    _ -> liftM One (source [] a)----buildGraph :: forall a . Data a -> Reify ()-buildGraph a@(Data _ _) = do-    ia <- checkNode a-    unless (isJust ia) $ list (dataToExpr a)-  where-    funcNode fun inp = do-      buildGraph inp-      inTup <- traceTuple inp-      node a fun inTup (dataType inp)--    list :: Expr a -> Reify ()--    list Variable = sourceNode a Graph.Input--    list (Value b)-      | isPrimitive a = return ()-      | otherwise     = sourceNode a $ Graph.Array $ storableData b--    list (Application (Application (Function fun _) b) c)-      | fun == "tup2" = buildGraph b >> buildGraph c--    list (Application (Application (Application (Function "tup3" _) b) c) d) =-      buildGraph b >> buildGraph c >> buildGraph d--    list (Application (Application (Application (Application-                                               (Function "tup4" _) b) c) d) e) =-      buildGraph b >> buildGraph c >> buildGraph d >> buildGraph e--    list (Application (Function fun _) b)-      | take 6 fun == "getTup" = buildGraph b-      | otherwise              = funcNode (Graph.Function fun) b--      -- XXX Assumes that no other kinds of function application exist.--    list (NoInline fun f b@(Data _ _)) = do-      iface <- buildSubFun (deref f)-      funcNode (Graph.NoInline fun iface) b-      -- XXX Sub-graph is not shared at the moment.--    list (IfThenElse c t e b@(Data _ _)) = do-      ifaceThen <- buildSubFun t-      ifaceElse <- buildSubFun e-      funcNode (Graph.IfThenElse ifaceThen ifaceElse) (tup2 c b)--    list (While cont body b@(Data _ _)) = do-      ifaceCont <- buildSubFun cont-      ifaceBody <- buildSubFun body-      funcNode (Graph.While ifaceCont ifaceBody) b--    list (Parallel l ixf) = do-      iface <- buildSubFun ixf-      funcNode (Graph.Parallel iface) l----buildSubFun :: forall a b . (Typeable a, Typeable b) =>-    (a :-> b) -> Reify Interface--buildSubFun (Lambda _ inp outp) = do-    let inType  = typeOf (dataSize inp) (T::T a)-        outType = typeOf (dataSize outp) (T::T b)-    buildGraph inp  -- Needed in case input is not used-    buildGraph outp-    outTup <- traceTuple outp-    info   <- get-    let inId = visited info Map.! dataId inp-    return (Interface inId outTup inType outType)----reifyD :: (Typeable a, Typeable b) => (Data a -> Data b) -> Graph-reifyD f = Graph nodes iface-  where-    subFun            = lambda universal f-    (iface,(nodes,_)) = runGraph (buildSubFun subFun) startInfo------ | Types that represent core language programs-class Program a-  where-    -- | Converts a program to a Graph-    reify :: a -> Graph--    -- | Returns whether or not the program has an argument. This is needed-    -- because the 'Graph' type always assumes the existence of an input. So-    -- for programs without input, the 'Graph' representation will have a-    -- \"dummy\" input, which is indistinguishable from a real input.-    numArgs :: T a -> Int--instance Computable a => Program a-  where-    reify     = reify_computable-    numArgs _ = 0--instance (Computable a, Computable b) => Program (a,b)-  where-    reify     = reify_computable-    numArgs _ = 0--instance (Computable a, Computable b, Computable c) => Program (a,b,c)-  where-    reify     = reify_computable-    numArgs _ = 0--instance (Computable a, Computable b, Computable c, Computable d) => Program (a,b,c,d)-  where-    reify     = reify_computable-    numArgs _ = 0--instance (Computable a, Computable b) => Program (a -> b)-  where-    reify   = reifyD . lowerFun-    numArgs = const 1--instance (Computable a, Computable b, Computable c) => Program (a -> b -> c)-  where-    reify f = reifyD $ lowerFun $ \(a,b) -> f a b-    numArgs = const 2--instance (Computable a, Computable b, Computable c, Computable d) => Program (a -> b -> c -> d)-  where-    reify f = reifyD $ lowerFun $ \(a,b,c) -> f a b c-    numArgs = const 3--instance (Computable a, Computable b, Computable c, Computable d, Computable e) => Program (a -> b -> c -> d -> e)-  where-    reify f = reifyD $ lowerFun $ \(a,b,c,d) -> f a b c d-    numArgs = const 4----reify_computable :: forall a . Computable a => a -> Graph-reify_computable a =-    reifyD (const (internalize a) :: Data () -> Data (Internal a))------ | Shows the core code generated by the program.-showCore :: forall a . Program a => a -> String-showCore = showGraph False "program" (numArgs (T::T a) > 0) . reify---- | Shows the core code with size information as comments.-showCoreWithSize :: forall a . Program a => a -> String-showCoreWithSize = showGraph True "program" (numArgs (T::T a) > 0) . reify---- | @printCore = putStrLn . showCore@-printCore :: Program a => a -> IO ()-printCore = putStrLn . showCore---- | @printCoreWithSize = putStrLn . showCoreWithSize@-printCoreWithSize :: Program a => a -> IO ()-printCoreWithSize = putStrLn . showCoreWithSize--instance Storable a => Show (Data a) where-  show = showCore
+ Feldspar/Core/Representation.hs view
@@ -0,0 +1,323 @@+module Feldspar.Core.Representation where++++import Data.List+import Data.Typeable hiding (TypeRep)++import Data.Tagged+import Data.Proxy++import Feldspar.DSL.Expression hiding (Eval)+import qualified Feldspar.DSL.Expression as E+import Feldspar.DSL.Lambda+import Feldspar.DSL.Sharing+import Feldspar.DSL.Network+import Feldspar.Set+import Feldspar.Core.Types++++--------------------------------------------------------------------------------+-- * Feldspar expressions+--------------------------------------------------------------------------------++-- | Feldspar-specific expressions+data Feldspar role a+  where+    Literal :: (Type a, MetaType () a) => a -> Feldspar (Out ()) a++    Function :: (Typeable (a -> b), MetaType () b) =>+      String -> (a -> b) -> Feldspar (In ra -> Out ()) (a -> b)++    Pair :: (Type a, Type b, MetaType () (a,b)) => Feldspar (In () -> In () -> Out ()) (a -> b -> (a,b))++    Condition :: MetaType ra a => Feldspar+      (In () -> In ra -> In ra -> Out ra)+      (Bool  -> a     -> a     -> a)++    Parallel :: (Type a, MetaType () [a]) => Feldspar+      (In ()  -> (Out () -> In ()) -> In () -> Out ())+      (Length -> (Index  -> a)     -> [a]   -> [a])++    Sequential :: (Type a, MetaType () [a], MetaType rst st) => Feldspar+      (In ()  -> In rst -> (Out () -> Out rst -> In ((),rst)) -> (Out rst -> In ()) -> Out ())+      (Length -> st     -> (Index  -> st      -> (a,st))      -> (st      -> [a])   -> [a])++    ForLoop :: MetaType rst st => Feldspar+      (In ()  -> In rst -> (Out () -> Out rst -> In rst) -> Out rst)+      (Length -> st     -> (Index  -> st      -> st)     -> st)++    NoInline :: MetaType rb b =>+      String -> Feldspar ((Out ra -> In rb) -> (In ra -> Out rb)) ((a -> b) -> (a -> b))++    SetLength :: Type a =>+      Feldspar (In () -> In () -> Out ()) (Length -> [a] -> [a])++    SetIx :: (Type a) => Feldspar+      (In () -> In () -> In () -> Out ())+      (Index -> a     -> [a]   -> [a])++-- TODO Missing support for writing to several indices at once in 'Parallel' and+--      'Sequential'.++++instance ExprEq Feldspar+  where+    exprEq (Literal a)      (Literal b)      = eqLiteral a b+    exprEq (Function n1 f1) (Function n2 f2) = n1==n2 && sameType f1 f2+    exprEq Pair             Pair             = True+    exprEq Condition        Condition        = True+    exprEq Parallel         Parallel         = True+    exprEq Sequential       Sequential       = True+    exprEq ForLoop          ForLoop          = True+    exprEq (NoInline n1)    (NoInline n2)    = n1 == n2+    exprEq SetLength        SetLength        = True+    exprEq SetIx            SetIx            = True+    exprEq _ _                               = False+      -- Note that functions are only compared by name.++eqLiteral :: (Typeable a, Typeable b, Eq b) => a -> b -> Bool+eqLiteral a b = case cast a of+    Just a' -> a'==b+    _       -> False++sameType :: forall a b . (Typeable a, Typeable b) => a -> b -> Bool+sameType a b = case cast a :: Maybe b of+    Nothing -> False+    _       -> True++instance E.Eval Feldspar+  where+    eval (Literal a)    = a+    eval (Function _ f) = f+    eval Pair           = (,)+    eval Condition      = \cond t e -> if cond then t else e+    eval Parallel       = evalParallel+    eval Sequential     = evalSequential+    eval ForLoop        = evalForLoop+    eval (NoInline _)   = id+    eval SetLength      = evalSetLength+    eval SetIx          = evalSetIx+    +evalParallel :: Length -> (Index -> a) -> [a] -> [a]+evalParallel 0 _ cont   = cont+evalParallel l ixf cont = map ixf [0 .. l-1] ++ cont+  -- Need a special case for l==0 because 0-1 is a huge number++evalSequential :: Length -> st -> (Index -> st -> (a,st)) -> (st -> [a]) -> [a]+evalSequential l init step cont = start ++ cont st'+  where+    (st',start)   = mapAccumL evalStep init [0 .. l-1]+    evalStep st i = (st',a) where (a,st') = step i st++evalForLoop :: Length -> st -> (Index -> st -> st) -> st+evalForLoop 0 init body = init+evalForLoop l init body = foldl (flip body) init [0 .. l-1]+  -- Need a special case for l==0 because 0-1 is a huge number++evalSetLength :: Length -> [a] -> [a]+evalSetLength 0 as     = []+evalSetLength l (a:as) = a : evalSetLength (l-1) as+evalSetLength _ _      = error "setLength: reading past the end of an array"++evalSetIx :: Index -> a -> [a] -> [a]+evalSetIx i v as | i < len   = genericTake i as ++ [v] ++ genericDrop (i+1) as+                 | otherwise = error $ "setIx: assigning index (" ++ show i +++                                       ") past the end of an array of length " +++                                       show len+  where len = genericLength as++instance ExprShow Feldspar+  where+    exprShow (Literal a)      = show a+    exprShow (Function fun _) = fun+    exprShow Pair             = "pair"+    exprShow Condition        = "condition"+    exprShow Parallel         = "parallel"+    exprShow Sequential       = "sequential"+    exprShow ForLoop          = "forLoop"+    exprShow (NoInline n)     = "noinline " ++ show n+    exprShow SetLength        = "setLength"+    exprShow SetIx            = "setIx"+++--------------------------------------------------------------------------------+-- * Feldspar networks+--------------------------------------------------------------------------------++-- | A wrapper around 'Size' to make it look like an expression. The 'Type'+-- constraint ensures that edges in a 'FeldNetwork' always have supported types.+data EdgeSize role a = (Type a, Eq (Size a), Show (Size a)) =>+    EdgeSize { edgeSize :: Size a }++instance ExprShow EdgeSize+  where+    exprShow (EdgeSize a) = show a++instance Eq (Size a) => Eq (EdgeSize role a) where+  EdgeSize sz1 == EdgeSize sz2 = sz1 == sz2++instance Type a => Set (EdgeSize role a)+  where+    empty                        = EdgeSize empty+    universal                    = EdgeSize universal+    EdgeSize sz1 \/ EdgeSize sz2 = EdgeSize (sz1 \/ sz2)+    EdgeSize sz1 /\ EdgeSize sz2 = EdgeSize (sz1 /\ sz2)++-- | 'Network' of 'Feldspar' expressions+type FeldNetwork = Network EdgeSize Feldspar++-- | A Feldspar program computing a value of type @a@+newtype Data a = Data { unData :: FeldNetwork (In ()) a }+  deriving (Eq)++instance Show (Data a)+  where+    show = show . unData++instance EdgeInfo (Data a)+  where+    type Info (Data a) = EdgeSize () a+    edgeInfo           = edgeInfo . unData++instance Type a => MultiEdge (Data a) Feldspar EdgeSize+  where+    type Role     (Data a) = ()+    type Internal (Data a) = a+    toEdge                 = toEdge . unData+    fromInEdge             = Data . fromInEdge+    fromOutEdge info       = Data . fromOutEdge info++++-- | 'Syntactic' is a specialization of the 'MultiEdge' class for 'Feldspar'+-- programs.+class+    ( MultiEdge a Feldspar EdgeSize+    , Set (Info a)+    , Type (Internal a)+    , MetaType (Role a) (Internal a)+    ) => Syntactic a++-- TODO There is something strange with the constraint Type (Internal a). It is+--      really only needed when Role a ~ (), but it accidentally works to have+--      this constraint for all Syntactic types.++instance Type a => Syntactic (Data a)+instance (Syntactic a, Syntactic b) => Syntactic (a,b)+instance (Syntactic a, Syntactic b, Syntactic c) => Syntactic (a,b,c)+instance (Syntactic a, Syntactic b, Syntactic c, Syntactic d) => Syntactic (a,b,c,d)++++edgeType :: forall a . EdgeSize () a -> TypeRep+edgeType (EdgeSize sz) = typeRep (Tagged sz :: Tagged a (Size a))++dataSize :: Type a => Data a -> Size a+dataSize = edgeSize . edgeInfo . unData++dataNode :: Data a -> FeldNetwork (Out ()) a+dataNode = undoEdge . unData++nodeData :: Type a => Size a -> FeldNetwork (Out ()) a -> Data a+nodeData sz = fromOutEdge (EdgeSize sz)++getInfo :: Syntactic a => a -> Info a+getInfo = edgeInfo++resizeData :: Type a => Size a -> Data a -> Data a+resizeData sz = nodeData sz . dataNode++variable :: Syntactic a => Info a -> Ident -> a+variable info = fromOutEdge info . Variable++lambda :: (Syntactic a, Syntactic b)+    => Info a+    -> (a -> b)+    -> FeldNetwork (Out (Role a) -> In (Role b)) (Internal a -> Internal b)+lambda info f = Lambda (toEdge . f . fromOutEdge info)++-- | Forcing computation+force :: Syntactic a => a -> a+force = edgeCast++-- | Evaluation of Feldspar programs+eval :: Syntactic a => a -> Internal a+eval = E.eval . toEdge++-- | Yield the value of a constant program. If the value is not known+-- statically, the result is 'Nothing'.+viewLiteral :: Syntactic a => a -> Maybe (Internal a)+viewLiteral = mapEdge (\_ a -> lit (undoEdge a)) . toEdge+  where+    lit :: FeldNetwork (Out ()) a -> Maybe a+    lit (Inject (Node (Literal a))) = Just a+    lit _                           = Nothing++metaTypes :: forall a ra expr .+    MetaType ra a => expr (Out ra) a -> [([Int], TypeRep)]+metaTypes _ = listTypes [] (Proxy :: Proxy ra) (Proxy :: Proxy a)++-- | List the types of the results produced by a 'Feldspar' expression+resTypes :: FeldNetwork ra a -> [([Int], TypeRep)]  -- TODO Should use (Out ra)+resTypes a = case a of+    Inject (Node (Literal _))                        -> metaTypes a+    Inject (Node (Function _ _)) :$: _               -> metaTypes a+    Inject (Node Pair) :$: _ :$: _                   -> metaTypes a+    Inject (Node Condition) :$: _ :$: _ :$: _        -> metaTypes a+    Inject (Node Parallel) :$: _ :$: _ :$: _         -> metaTypes a+    Inject (Node Sequential) :$: _ :$: _ :$: _ :$: _ -> metaTypes a+    Inject (Node ForLoop) :$: _ :$: _ :$: _          -> metaTypes a+    Inject (Node (NoInline n)) :$: _ :$: _           -> metaTypes a+    Inject (Node SetLength) :$: _ :$: _              -> metaTypes a+    Inject (Node SetIx) :$: _ :$: _ :$: _            -> metaTypes a+    Let _ :$: _ :$: (Lambda f)                       -> resTypes (f ph)+    _                                                -> error $ "Representation.resTypes: " ++ show a++isMulti :: FeldNetwork ra a -> Bool+isMulti a = isNode a && (length (resTypes a) > 1)++isElem :: FeldNetwork ra a -> Bool+isElem (Inject (Node (Function "(!)" _)) :$: _) = True+isElem _ = False++isSelector :: FeldNetwork ra a -> Bool+isSelector (Inject (Node (Function fun _)) :$: _) =+    fun `elem` ["getFst","getSnd"]+isSelector _ = False++isArrayLit :: FeldNetwork ra a -> Bool+isArrayLit (Inject (Node (Literal a)))+    | ArrayData as <- dataRep a = True+isArrayLit _ = False++isEmpty :: FeldNetwork ra a -> Bool+isEmpty (Inject (Node (Literal a)))+    | ArrayData as <- dataRep a = length as == 0+isEmpty _ = False++feldSharing :: (Typeable ra, Typeable a) => FeldNetwork ra a -> FeldNetwork ra a+feldSharing = sharing Params+    { necessary    = \(SomeLam a) -> isNode a && not (isFunction a || isVar a || isElem a || isSelector a)+    , sufficient   = \(SomeLam a) -> isMulti a+    , sharingPoint = \(SomeLam a) -> not (isFunction a)+        -- To avoid introducing 'Let' in the middle of a nested lambda (e.g. the+        -- body of a 'ForLoop')+    }++showExprTree :: Syntactic a => a -> String+showExprTree = showLamTree . feldSharing . toEdge++showExprTree2 :: (Syntactic a, Syntactic b) => (a -> b) -> String+showExprTree2 = showLamTree . feldSharing . lambda universal+  -- TODO Only temporary...++drawExpr :: Syntactic a => a -> IO ()+drawExpr = drawLambda . feldSharing . toEdge++drawExpr2 :: (Syntactic a, Syntactic b) => (a -> b) -> IO ()+drawExpr2 = drawLambda . feldSharing . lambda universal+  -- TODO Only temporary...+
− Feldspar/Core/Show.hs
@@ -1,207 +0,0 @@------ Copyright (c) 2009-2010, ERICSSON AB All rights reserved.--- --- Redistribution and use in source and binary forms, with or without--- modification, are permitted provided that the following conditions are met:--- ---     * Redistributions of source code must retain the above copyright notice,---       this list of conditions and the following disclaimer.---     * 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 name of the ERICSSON AB nor the names of its contributors---       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 AND CONTRIBUTORS "AS IS"--- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE--- IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE--- ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS--- BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,--- OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF--- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS--- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN--- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)--- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF--- THE POSSIBILITY OF SUCH DAMAGE.------- | Defines a function 'showGraph' for showing core language graphs as Haskell--- code.--module Feldspar.Core.Show where----import Control.Monad-import Data.List--import Feldspar.Utils-import Feldspar.Haskell-import Feldspar.Core.Types-import Feldspar.Core.Graph----instance HaskellValue Variable-  where-    haskellValue (i,path) = "v" ++ intercalate "_" (map show (i:path))--instance HaskellValue Source-  where-    haskellValue (Constant a) = haskellValue a-    haskellValue (Variable v) = haskellValue v---- | Creates a tuple pattern of the given type, for the output of the given--- node.-tupPatt :: Tuple StorableType -> NodeId -> Tuple Variable-tupPatt tup i = fmap (\path -> (i,path)) (tuplePath tup)---- | Matches the string against @\"(...)\"@, and returns @Just ...@ if possible,--- otherwise @Nothing@.-viewBinOp :: String -> Maybe String-viewBinOp "" = Nothing-viewBinOp op-    | length op < 2                        = Nothing-    | (head op == '(') && (last op == ')') = Just $ tail $ init op-    | otherwise                            = Nothing----sizeComment :: Tuple StorableType -> String-sizeComment typ = case size of-    "" -> ""-    _  -> "  -- Size: " ++ size-  where-    size = showTuple (fmap showStorableSize typ)------ | Shows a single node.-showNode :: Bool -> Node -> [Hierarchy] -> String--showNode _ (Node i Input inp inType outType) subHiers = ""--showNode showSize (Node i fun inp inType outType) subHiers-    | showSize  = appendFirstLine (sizeComment outType) (showNd fun)-    | otherwise = showNd fun-  where-    outp = tupPatt outType i--    showSF' = showSF showSize--    showNd Input     = ""-    showNd (Array a) = ((i,[])::Variable) -=- a--    showNd (Function fun)-        | Just op <- viewBinOp fun = outp -=- opApp op a b-      where-        Tup [a,b] = inp--    showNd (Function fun) = outp -=- fun -$- inp--    showNd (NoInline fun iface) =-        outp -=- fun -$- inp-          `local`-        showSF' (head subHiers) fun subInp subOutp-      where-        subInp  = tupPatt inType $ interfaceInput iface-        subOutp = interfaceOutput iface--    showNd (IfThenElse ifaceThen ifaceElse) =-        outp -=- ifExpr-          `local`-        (thenBranch ++ newline ++ elseBranch)-      where-        Tup [One cond, a]   = inp-        Tup [_, aType]      = inType-        [thenHier,elseHier] = subHiers--        ifExpr = ifThenElse cond-          ("thenBranch" -$- a)-          ("elseBranch" -$- a)--        subInpThen  = tupPatt aType $ interfaceInput ifaceThen-        subInpElse  = tupPatt aType $ interfaceInput ifaceElse-        subOutpThen = interfaceOutput ifaceThen-        subOutpElse = interfaceOutput ifaceElse--        thenBranch = showSF' thenHier "thenBranch" subInpThen subOutpThen-        elseBranch = showSF' elseHier "elseBranch" subInpElse subOutpElse--    showNd (While ifaceCont ifaceBody) =-        outp -=- "while" -$- "cont" -$- "body" -$- inp-          `local`-        (contBranch ++ newline ++ bodyBranch)-      where-        [contHier,bodyHier] = subHiers--        subInpCont  = tupPatt inType $ interfaceInput ifaceCont-        subInpBody  = tupPatt inType $ interfaceInput ifaceBody-        subOutpCont = interfaceOutput ifaceCont-        subOutpBody = interfaceOutput ifaceBody--        contBranch = showSF' contHier "cont" subInpCont subOutpCont-        bodyBranch = showSF' bodyHier "body" subInpBody subOutpBody--    showNd (Parallel iface) =-        outp -=- "parallel" -$- inp -$- "ixf"-          `local`-        showSF' (head subHiers) "ixf" subInp subOutp-      where-        subInp  = tupPatt inType $ interfaceInput iface-        subOutp = interfaceOutput iface------ | @showSubFun showSize hier name inp outp@:------ Shows a sub-function named @name@ represented by the hierarchy @hier@. If--- @inp@ is @Nothing@, it will be shown as a definition without an argument.--- @showSize@ decides whether or not to show size comments.-showSubFun-    :: (HaskellValue inp, HaskellValue outp)-    => Bool-    -> Hierarchy-    -> String-    -> Maybe inp-    -> outp-    -> String--showSubFun showSize (Hierarchy nodes) name inp outp =-    funHead inp -=- outp-      `local`-    unlinesNoTrail (filter (not.null) $ map (uncurry (showNode showSize)) nodes)-  where-    funHead Nothing    = name-    funHead (Just inp) = name -$- inp------ | @showSF showSize hier name inp = showSubFun showSize hier name (Just inp)@-showSF-    :: (HaskellValue inp, HaskellValue outp)-    => Bool-    -> Hierarchy-    -> String-    -> inp-    -> outp-    -> String--showSF showSize hier name inp = showSubFun showSize hier name (Just inp)------ | Shows a graph. The given string is the name of the top-level function. The--- Boolean tells whether the graph has a real or a dummy argument. A graphs with--- that has a dummy argument will be shown as a definition without an argument.--- Of course, this assumes that a dummy argument is not used within the graph.-showGraph :: Bool -> String -> Bool -> Graph -> String-showGraph showSize name hasArg graph@(Graph nodes iface) =-    showSubFun showSize hier name inp' outp-  where-    hier = graphHierarchy $ makeHierarchical graph-    inp  = tupPatt (interfaceInputType iface) (interfaceInput iface)-    inp' = guard hasArg >> Just inp-    outp = interfaceOutput iface-
− Feldspar/Core/Trace.hs
@@ -1,38 +0,0 @@------ Copyright (c) 2009-2010, ERICSSON AB All rights reserved.--- --- Redistribution and use in source and binary forms, with or without--- modification, are permitted provided that the following conditions are met:--- ---     * Redistributions of source code must retain the above copyright notice,---       this list of conditions and the following disclaimer.---     * 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 name of the ERICSSON AB nor the names of its contributors---       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 AND CONTRIBUTORS "AS IS"--- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE--- IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE--- ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS--- BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,--- OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF--- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS--- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN--- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)--- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF--- THE POSSIBILITY OF SUCH DAMAGE.-----module Feldspar.Core.Trace where---import Feldspar.Core.Expr-import Feldspar.Core.Types----trace :: (Storable a) => Int -> Data a -> Data a-trace label = function2 "trace" (const id) (const id) $ value label
Feldspar/Core/Types.hs view
@@ -1,456 +1,314 @@------ Copyright (c) 2009-2010, ERICSSON AB All rights reserved.--- --- Redistribution and use in source and binary forms, with or without--- modification, are permitted provided that the following conditions are met:--- ---     * Redistributions of source code must retain the above copyright notice,---       this list of conditions and the following disclaimer.---     * 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 name of the ERICSSON AB nor the names of its contributors---       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 AND CONTRIBUTORS "AS IS"--- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE--- IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE--- ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS--- BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,--- OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF--- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS--- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN--- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)--- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF--- THE POSSIBILITY OF SUCH DAMAGE.-----{-# LANGUAGE UndecidableInstances #-}---- | Defines types and classes for the data computed by "Feldspar" programs.- module Feldspar.Core.Types where   -import Control.Applicative-import Data.Char-import Data.Foldable (Foldable)-import qualified Data.Foldable as Fold-import Data.Monoid-import Data.Traversable (Traversable, traverse)-+import Data.Bits+import Data.Complex import Data.Int+import Data.List+import Data.Tagged+import Data.Proxy+import Data.Typeable (Typeable) import Data.Word-import Data.Bits -import Feldspar.Utils-import Feldspar.Haskell+import Feldspar.Set import Feldspar.Range   --- * Misc.---- | Used to pass a type to a function without using 'undefined'.-data T a = T--mkT :: a -> T a-mkT _ = T--+--------------------------------------------------------------------------------+-- * Heterogenous lists+--------------------------------------------------------------------------------  -- | Heterogeneous list data a :> b = a :> b-    deriving (Eq, Ord, Show)+  deriving (Eq, Ord, Show)  infixr 5 :> -instance (Monoid a, Monoid b) => Monoid (a :> b)-  where-    mempty = mempty :> mempty--    (a1:>b1) `mappend` (a2:>b2) = (a1 `mappend` a2) :> (b1 `mappend` b2)----class Set a-  where-    universal :: a--instance Set ()-  where-    universal     = ()--instance Ord a => Set (Range a)-  where-    universal = fullRange- instance (Set a, Set b) => Set (a :> b)   where+    empty     = empty :> empty     universal = universal :> universal--instance (Set a, Set b) => Set (a,b)-  where-    universal = (universal,universal)--instance (Set a, Set b, Set c) => Set (a,b,c)-  where-    universal = (universal,universal,universal)--instance (Set a, Set b, Set c, Set d) => Set (a,b,c,d)-  where-    universal = (universal,universal,universal,universal)+    (a1:>a2) \/ (b1:>b2) = (a1 \/ b1) :> (a2 \/ b2)+    (a1:>a2) /\ (b1:>b2) = (a1 /\ b1) :> (a2 /\ b2)   -type Length = Int-+--------------------------------------------------------------------------------+-- * Integers+-------------------------------------------------------------------------------- +-- | Platform-independent unsigned integers+newtype DefaultWord = DefaultWord Word32+  deriving (Eq, Ord, Num, Enum, Real, Integral, Bits, Bounded, Typeable)+  -- TODO Find better name --- * Tuples+-- | Platform-independent signed integers+newtype DefaultInt = DefaultInt Int32+  deriving (Eq, Ord, Num, Enum, Real, Integral, Bits, Bounded, Typeable)+  -- TODO Find better name --- | Untyped representation of nested tuples-data Tuple a-       = One a-       | Tup [Tuple a]-     deriving (Eq, Show)+-- TODO Should really be defined as:+--+--     data DefaultWord+--         = DefWord32 Word32+--         | DefWord16 Word16+--+--     data DefaultInt+--         = DefInt32 Int32+--         | DefInt16 Int16 -instance Functor Tuple-  where-    fmap f (One a)  = One (f a)-    fmap f (Tup as) = Tup $ map (fmap f) as-  -- XXX Can be derived in GHC 6.12+type Length = DefaultWord+type Index  = DefaultWord -instance Foldable Tuple+instance Show DefaultWord   where-    foldr f x (One a)  = f a x-    foldr f x (Tup as) = Fold.foldr (flip $ Fold.foldr f) x as-  -- XXX Can be derived in GHC 6.12+    show (DefaultWord a) = show a -instance Traversable Tuple+instance Show DefaultInt   where-    traverse f (One a)  = pure One <*> f a-    traverse f (Tup as) = pure Tup <*> traverse (traverse f) as-  -- XXX Can be derived in GHC 6.12+    show (DefaultInt a) = show a -instance HaskellType a => HaskellType (Tuple a)-  where-    haskellType = showTuple . fmap haskellType+-- | The set of signed integer types+class Signed a -instance HaskellValue a => HaskellValue (Tuple a)-  where-    haskellValue = showTuple . fmap haskellValue+instance Signed Int8+instance Signed Int16+instance Signed Int32+instance Signed DefaultInt   --- | Shows a nested tuple in Haskell's tuple syntax (e.g @\"(a,(b,c))\"@).-showTuple :: Tuple String -> String-showTuple (One a)  = a-showTuple (Tup as) = showSeq "(" (map showTuple as) ")"---- | Replaces each element by its path in the tuple tree. For example:------ > tuplePath (Tup [One 'a',Tup [One 'b', One 'c']])--- >   ==--- > Tup [One [0],Tup [One [1,0],One [1,1]]]-tuplePath :: Tuple a -> Tuple [Int]-tuplePath tup = path [] tup-  where-    path pth (One _)  = One pth-    path pth (Tup as) = Tup [path (pth++[n]) a | (a,n) <- as `zip` [0..]]--+--------------------------------------------------------------------------------+-- * Type/data representation+-------------------------------------------------------------------------------- --- * Data+-- | Representation of types+data TypeRep+  = BoolType+  | forall a . (BoundedInt a, Typeable a) => IntType { intRange :: Range a }+  | FloatType+  | UserType String+  | ComplexType TypeRep+  | ArrayType (Range Length) TypeRep+  | StructType [TypeRep] --- | Untyped representation of primitive data-data PrimitiveData-  = UnitData  ()-  | BoolData  Bool-  | IntData   Integer+-- | Representation of data+data DataRep+  = BoolData Bool+  | IntData Integer   | FloatData Float-    deriving (Eq, Show)---- | Untyped representation of storable data (arrays of primitive data)-data StorableData-  = PrimitiveData PrimitiveData-  | StorableData [StorableData]-    deriving (Eq, Show)--instance HaskellValue PrimitiveData-  where-    haskellValue (UnitData  a) = show a-    haskellValue (BoolData  a) = map toLower (show a)-    haskellValue (IntData   a) = show a-    haskellValue (FloatData a) = show a+  | ComplexData DataRep DataRep+  | ArrayData [DataRep]+  | StructData [DataRep]+  deriving (Eq, Show) -instance HaskellValue StorableData+class (Eq a, Show a, Typeable a, Eq (Size a), Show (Size a), Set (Size a)) => Type a   where-    haskellValue (PrimitiveData a) = haskellValue a-    haskellValue (StorableData as) = showSeq "[" (map haskellValue as) "]"------ * Types+    type Size a -type Unsigned32 = Word32-type Signed32   = Int32-type Unsigned16 = Word16-type Signed16   = Int16-type Unsigned8  = Word8-type Signed8    = Int8+    dataRep :: a -> DataRep --- | Representation of primitive types-data PrimitiveType-  = UnitType-  | BoolType-  | IntType { signed :: Bool, bitSize :: Int, valueSet :: (Range Integer) }-  | FloatType (Range Float)-  | UserType String-    deriving (Eq, Show)+    -- | Gives the type representation of a storable value.+    typeRep :: Tagged a (Size a) -> TypeRep --- | Representation of storable types (arrays of primitive types). Array size is--- given as a list of ranged lengths, starting with outermost array level.--- Primitive types are treated as zero-dimensional arrays.-data StorableType = StorableType [Range Length] PrimitiveType-    deriving (Eq, Show)+    -- | Gives the size of a storable value.+    sizeOf :: a -> Size a -instance HaskellType PrimitiveType+instance Type ()   where-    haskellType UnitType             = "()"-    haskellType BoolType             = "Bool"-    haskellType (IntType True  32 _) = "Int32"-    haskellType (IntType False 32 _) = "Word32"-    haskellType (IntType True  16 _) = "Int16"-    haskellType (IntType False 16 _) = "Word16"-    haskellType (IntType True   8 _) = "Int8"-    haskellType (IntType False  8 _) = "Word8"-    haskellType (FloatType _)        = "Float"-    haskellType (UserType t)         = t+    type Size () = ()+    dataRep _    = BoolData False+    typeRep _    = BoolType+    sizeOf _     = () -instance HaskellType StorableType+instance Type Bool   where-    haskellType (StorableType ls t) = arrType-      where-        d       = length ls-        arrType = replicate d '[' ++ haskellType t ++ replicate d ']'--showPrimitiveRange :: PrimitiveType -> String-showPrimitiveRange (IntType _ _ r) = showRange r-showPrimitiveRange (FloatType r)   = showRange r-showPrimitiveRange _               = ""---- | Shows the size of a storable type.-showStorableSize :: StorableType -> String-showStorableSize (StorableType ls t) =-    showSeq "" (map (showBound . upperBound) ls) "" ++ showPrimitiveRange t----{-# DEPRECATED Primitive "The class Primitive will be removed. Use Storable instead." #-}--- | Primitive types-class    Storable a => Primitive a-instance Storable a => Primitive a+    type Size Bool = ()+    dataRep        = BoolData+    typeRep _      = BoolType+    sizeOf _       = () --- | Storable types (zero- or higher-level arrays of primitive data).-class Typeable a => Storable a+instance Type Word8   where-    -- | Converts a storable value to its untyped representation.-    storableData :: a -> StorableData--    -- | Gives the type representation of a storable value.-    storableType :: Size a -> T a -> StorableType--    -- | Gives the size of a storable value.-    storableSize :: a -> Size a--    listSize :: T a -> Size a -> [Range Length]-      -- XXX Could be put in a separate class without the (T a).+    type Size Word8 = Range Word8+    dataRep         = IntData . toInteger+    typeRep         = IntType . untag+    sizeOf a        = singletonRange a -instance Storable ()+instance Type Int8   where-    storableData    = PrimitiveData . UnitData-    storableType _ _= StorableType [] UnitType-    storableSize _  = ()-    listSize _ _    = []+    type Size Int8 = Range Int8+    dataRep        = IntData . toInteger+    typeRep        = IntType . untag+    sizeOf a       = singletonRange a -instance Storable Bool+instance Type Word16   where-    storableData     = PrimitiveData . BoolData-    storableType _ _ = StorableType [] BoolType-    storableSize _   = ()-    listSize _ _     = []+    type Size Word16 = Range Word16+    dataRep          = IntData . toInteger+    typeRep          = IntType . untag+    sizeOf a         = singletonRange a --- XXX Assumes 32 bits which is not necessarily correct-instance Storable Int+instance Type Int16   where-    storableData     = PrimitiveData . IntData . toInteger-    storableType s _ = StorableType [] $ IntType True 32 s-    storableSize a   = singletonRange $ toInteger a-    listSize _ _     = []+    type Size Int16 = Range Int16+    dataRep         = IntData . toInteger+    typeRep         = IntType . untag+    sizeOf a        = singletonRange a -instance Storable Unsigned32+instance Type Word32   where-    storableData     = PrimitiveData . IntData . toInteger-    storableType s _ = StorableType [] $ IntType False 32 s-    storableSize a   = singletonRange $ toInteger a-    listSize _ _     = []+    type Size Word32 = Range Word32+    dataRep          = IntData . toInteger+    typeRep          = IntType . untag+    sizeOf a         = singletonRange a -instance Storable Signed32+instance Type Int32   where-    storableData     = PrimitiveData . IntData . toInteger-    storableType s _ = StorableType [] $ IntType True 32 s-    storableSize a   = singletonRange $ toInteger a-    listSize _ _     = []+    type Size Int32 = Range Int32+    dataRep         = IntData . toInteger+    typeRep         = IntType . untag+    sizeOf a        = singletonRange a -instance Storable Unsigned16+instance Type DefaultWord   where-    storableData     = PrimitiveData . IntData . toInteger-    storableType s _ = StorableType [] $ IntType False 16 s-    storableSize a   = singletonRange $ toInteger a-    listSize _ _     = []+    type Size DefaultWord = Range DefaultWord+    dataRep               = IntData . toInteger+    typeRep               = IntType . untag+    sizeOf a              = singletonRange a -instance Storable Signed16+instance Type DefaultInt   where-    storableData     = PrimitiveData . IntData . toInteger-    storableType s _ = StorableType [] $ IntType True 16 s-    storableSize a   = singletonRange $ toInteger a-    listSize _ _     = []+    type Size DefaultInt = Range DefaultInt+    dataRep              = IntData . toInteger+    typeRep              = IntType . untag+    sizeOf a             = singletonRange a -instance Storable Unsigned8+instance Type Float   where-    storableData     = PrimitiveData . IntData . toInteger-    storableType s _ = StorableType [] $ IntType False 8 s-    storableSize a   = singletonRange $ toInteger a-    listSize _ _     = []+    type Size Float = ()+    dataRep         = FloatData+    typeRep _       = FloatType+    sizeOf _        = () -instance Storable Signed8+instance (Type a, RealFloat a) => Type (Complex a)+  -- 'RealFloat' comes from the constraint on the 'Complex' data type. It+  -- implies 'Floating'   where-    storableData     = PrimitiveData . IntData . toInteger-    storableType s _ = StorableType [] $ IntType True 8 s-    storableSize a   = singletonRange $ toInteger a-    listSize _ _     = []+    type Size (Complex a) = ()+    dataRep (r :+ i) = ComplexData (dataRep r) (dataRep i)+    typeRep sz = ComplexType $ typeRep (Tagged universal :: Tagged a (Size a))+    sizeOf  _  = () -instance Storable Float+instance Type a => Type [a]   where-    storableData     = PrimitiveData . FloatData-    storableType s _ = StorableType [] $ FloatType s-    storableSize a   = singletonRange a-    listSize _ _     = []+    type Size [a]            = Range Length :> Size a+    dataRep as               = ArrayData (map dataRep as)+    typeRep (Tagged (l:>sz)) = ArrayType l (typeRep sz')+      where+        sz' = Tagged sz :: Tagged a (Size a)+    sizeOf as = singletonRange (genericLength as) :> unions (map sizeOf as) -instance Storable a => Storable [a]+instance (Type a, Type b) => Type (a,b)   where-    storableData = StorableData . map storableData--    storableType (l:>ls) _ = StorableType (l:ls') t+    type Size (a,b)            = (Size a, Size b)+    dataRep (a,b)              = StructData [dataRep a, dataRep b]+    typeRep (Tagged (sza,szb)) = StructType [typeRep sza', typeRep szb']       where-        StorableType ls' t = storableType ls (T::T a)--    storableSize as =-        singletonRange (length as) :> mconcat (map storableSize as)--    listSize _ (l:>ls) = l : listSize (T::T a) ls--+        sza' = Tagged sza :: Tagged a (Size a)+        szb' = Tagged szb :: Tagged b (Size b)+    sizeOf (a,b) = (sizeOf a, sizeOf b) -class (Eq a, Monoid (Size a), Set (Size a)) => Typeable a+instance (Type a, Type b, Type c) => Type (a,b,c)   where-    -- | This type provides the necessary extra information to compute a type-    -- representation @`Tuple` `StorableType`@ from a type @a@. This is needed-    -- because the type @a@ is missing information about sizes of arrays and-    -- primitive values.-    type Size a--    -- | Gives the type representation of a storable value.-    typeOf :: Size a -> T a -> Tuple StorableType+    type Size (a,b,c) = (Size a, Size b, Size c)+    dataRep (a,b,c)   = StructData [dataRep a, dataRep b, dataRep c]+    typeRep (Tagged (sza,szb,szc)) = StructType [typeRep sza', typeRep szb', typeRep szc']+      where+        sza' = Tagged sza :: Tagged a (Size a)+        szb' = Tagged szb :: Tagged b (Size b)+        szc' = Tagged szc :: Tagged c (Size c)+    sizeOf (a,b,c) = (sizeOf a, sizeOf b, sizeOf c) -instance Typeable ()+instance (Type a, Type b, Type c, Type d) => Type (a,b,c,d)   where-    type Size () = ()-    typeOf       = typeOfStorable+    type Size (a,b,c,d) = (Size a, Size b, Size c, Size d)+    dataRep (a,b,c,d)   = StructData [dataRep a, dataRep b, dataRep c, dataRep d]+    typeRep (Tagged (sza,szb,szc,szd)) = StructType [typeRep sza', typeRep szb', typeRep szc', typeRep szd']+      where+        sza' = Tagged sza :: Tagged a (Size a)+        szb' = Tagged szb :: Tagged b (Size b)+        szc' = Tagged szc :: Tagged c (Size c)+        szd' = Tagged szd :: Tagged d (Size d)+    sizeOf (a,b,c,d) = (sizeOf a, sizeOf b, sizeOf c, sizeOf d) -instance Typeable Bool+-- TODO Document+class MetaType role a   where-    type Size Bool = ()-    typeOf         = typeOfStorable+    listTypes :: [Int] -> Proxy role -> Proxy a -> [([Int], TypeRep)] -instance Typeable Int+instance Type a => MetaType () a   where-    type Size Int = Range Integer-    typeOf        = typeOfStorable+    listTypes path _ _ =+        [(path, typeRep (Tagged universal :: Tagged a (Size a)))] -instance Typeable Unsigned32+instance (MetaType ra a, MetaType rb b) => MetaType (ra,rb) (a,b)   where-    type Size Unsigned32 = Range Integer-    typeOf               = typeOfStorable+    listTypes path _ _+        =  listTypes (1:path) (Proxy :: Proxy ra) (Proxy :: Proxy a)+        ++ listTypes (2:path) (Proxy :: Proxy rb) (Proxy :: Proxy b) -instance Typeable Signed32+instance (MetaType ra a, MetaType rb b, MetaType rc c) =>+    MetaType (ra,rb,rc) (a,b,c)   where-    type Size Signed32 = Range Integer-    typeOf             = typeOfStorable+    listTypes path _ _+        =  listTypes (1:path) (Proxy :: Proxy ra) (Proxy :: Proxy a)+        ++ listTypes (2:path) (Proxy :: Proxy rb) (Proxy :: Proxy b)+        ++ listTypes (3:path) (Proxy :: Proxy rc) (Proxy :: Proxy c) -instance Typeable Unsigned16+instance (MetaType ra a, MetaType rb b, MetaType rc c, MetaType rd d) =>+    MetaType (ra,rb,rc,rd) (a,b,c,d)   where-    type Size Unsigned16 = Range Integer-    typeOf               = typeOfStorable+    listTypes path _ _+        =  listTypes (1:path) (Proxy :: Proxy ra) (Proxy :: Proxy a)+        ++ listTypes (2:path) (Proxy :: Proxy rb) (Proxy :: Proxy b)+        ++ listTypes (3:path) (Proxy :: Proxy rc) (Proxy :: Proxy c)+        ++ listTypes (4:path) (Proxy :: Proxy rd) (Proxy :: Proxy d) -instance Typeable Signed16-  where-    type Size Signed16 = Range Integer-    typeOf             = typeOfStorable -instance Typeable Unsigned8-  where-    type Size Unsigned8 = Range Integer-    typeOf              = typeOfStorable -instance Typeable Signed8-  where-    type Size Signed8 = Range Integer-    typeOf            = typeOfStorable+-- | A version of 'typeRep' that gets the 'Size' implicitly from the argument.+typeRep' :: forall a . Type a => a -> TypeRep+typeRep' a = typeRep (Tagged (sizeOf a) :: Tagged a (Size a)) -instance Typeable Float-  where-    type Size Float = Range Float-    typeOf          = typeOfStorable+isNil :: Type a => a -> Bool+isNil a = case dataRep a of+    ArrayData [] -> True+    _            -> False -instance Storable a => Typeable [a]-  where-    type Size [a] = Range Length :> Size a-    typeOf        = typeOfStorable -instance (Typeable a, Typeable b) => Typeable (a,b)-  where-    type Size (a,b) = (Size a, Size b) -    typeOf (sa,sb) _ = Tup [typeOf sa (T::T a), typeOf sb (T::T b)]+--------------------------------------------------------------------------------+-- * Size propagation+-------------------------------------------------------------------------------- -instance (Typeable a, Typeable b, Typeable c) => Typeable (a,b,c)+class FullProp a   where-    type Size (a,b,c) = (Size a, Size b, Size c)--    typeOf (sa,sb,sc) _ = Tup-        [ typeOf sa (T::T a)-        , typeOf sb (T::T b)-        , typeOf sc (T::T c)-        ]+    -- | Size propagation function that maps any number of arguments to+    -- 'universal'.+    fullProp :: a -instance (Typeable a, Typeable b, Typeable c, Typeable d) => Typeable (a,b,c,d)+instance FullProp ()   where-    type Size (a,b,c,d) = (Size a, Size b, Size c, Size d)--    typeOf (sa,sb,sc,sd) _ = Tup-        [ typeOf sa (T::T a)-        , typeOf sb (T::T b)-        , typeOf sc (T::T c)-        , typeOf sd (T::T d)-        ]-+    fullProp = universal +instance BoundedInt a => FullProp (Range a)+  where+    fullProp = universal --- | Default implementation of 'typeOf' for 'Storable' types.-typeOfStorable :: Storable a => Size a -> T a -> Tuple StorableType-typeOfStorable sz = One . storableType sz+instance FullProp b => FullProp (a -> b)+  where+    fullProp = const fullProp 
+ Feldspar/Core/Wrap.hs view
@@ -0,0 +1,47 @@+-- | Module "Data.TypeLevel.Num.Aliases" is re-exported because+-- wrappers use type level numbers frequently+module Feldspar.Core.Wrap ( Wrap(..), Data'(..), module Data.TypeLevel.Num.Aliases, D0, D1, D2, D3, D4, D5, D6, D7, D8, D9) where+++import Feldspar.DSL.Network+import Feldspar.Core.Types+import Feldspar.Core.Representation++import Data.TypeLevel.Num.Aliases+import Data.TypeLevel.Num.Reps (D0, D1, D2, D3, D4, D5, D6, D7, D8, D9 )+++-- | Wrapping Feldspar functions+class Wrap t w where+    wrap :: t -> w++-- | Basic instances to handle @Data a@ input and output.+-- Other instances are located in the concerned libraries.+instance Wrap (Data a) (Data a) where+    wrap = id++instance (Wrap t u) => Wrap (Data a -> t) (Data a -> u) where+    wrap f = \x -> wrap $ f x++-- | Extended 'Data' to be used in wrappers+data Data' s a =+    Data'+    { unData'   :: Data a+    }++-- Syntactic instance for 'Data''+instance EdgeInfo (Data' s a)+  where+    type Info (Data' s a)   = EdgeSize () a+    edgeInfo                = edgeInfo . unData . unData'++instance Type a => MultiEdge (Data' s a) Feldspar EdgeSize+  where+    type Role     (Data' s a)   = ()+    type Internal (Data' s a)   = a+    toEdge                      = toEdge . unData . unData'+    fromInEdge                  = Data' . Data . fromInEdge+    fromOutEdge info            = Data' . Data . fromOutEdge info++instance (Type a) => Syntactic (Data' s a)+
+ Feldspar/DSL/Expression.hs view
@@ -0,0 +1,74 @@+-- | This module defines the concept of expressions and expression transformers.+--+-- An expression is a type constructor of kind+--+-- > * -> * -> *+--+-- where the first argument denotes the \"role\" of the expression, and the+-- second argument is the type of the value computed by the expression.+--+-- An expression transformer is a type constructor of kind+--+-- > (* -> * -> *) -> (* -> * -> *)+--+-- i.e. a expression parameterized by an expression.++module Feldspar.DSL.Expression where++++import Data.Typeable+import Unsafe.Coerce++++-- | Expression type with no constructors. Can be used to turn an expression+-- transformer to an expression.+data Empty role a++-- | Equality for expressions. The difference between 'Eq' and 'ExprEq' is that+-- 'ExprEq' allows comparison of expressions with different role and value type.+-- It is assumed that when the types differ, the expressions also differ. The+-- reason for allowing comparison of different types is that this is convenient+-- when the types are existentially quantified.+class ExprEq expr+  where+    exprEq :: expr ra a -> expr rb b -> Bool++instance ExprEq Empty+  where+    exprEq _ _ = undefined++instance Eq (Empty role a)+  where+    (==) = exprEq++-- | Evaluation of expressions+class Eval expr+  where+    eval :: expr role a -> a++instance Eval Empty+  where+    eval _ = undefined++class ExprShow expr+  where+    exprShow :: expr role a -> String++instance ExprShow Empty+  where+    exprShow _ = undefined++printExpr :: ExprShow expr => expr role a -> IO ()+printExpr = putStrLn . exprShow++-- | Type-safe cast for expressions+exprCast :: forall expr ra a rb b+    .  (Typeable ra, Typeable a, Typeable rb, Typeable b)+    => expr ra a -> Maybe (expr rb b)+exprCast e = do+    cast (undefined :: ra) :: Maybe rb  -- Check that ra and rb are the same+    cast (undefined :: a)  :: Maybe b   -- Check that a and b are the same+    return (unsafeCoerce e)+
+ Feldspar/DSL/Lambda.hs view
@@ -0,0 +1,197 @@+-- | A module for lambda expressions++module Feldspar.DSL.Lambda where++++import Control.Monad.State+import Data.Tree+import Data.Typeable++import Feldspar.DSL.Expression++++-- | Unique identifier+type Ident = String++-- | Extensible lambda expressions+data Lam expr role a+  where+    Variable :: Ident -> Lam expr role a++    Value :: a -> Lam expr role a++    Lambda+        :: (Typeable rb, Typeable b)+        => (Lam expr ra a -> Lam expr rb b) -> Lam expr (ra -> rb) (a -> b)++    (:$:)+        :: (Typeable ra, Typeable a)+        => Lam expr (ra -> rb) (a -> b) -> Lam expr ra a -> Lam expr rb b+      -- Application. Using an infix operator makes it *a lot* easier to work+      -- with the library.++    Let :: String -> Lam expr (ra -> (ra -> rb) -> rb) (a -> (a -> b) -> b)++    Inject :: expr role a -> Lam expr role a++      -- Note: Using an infix operator for application makes it *a lot* easier+      -- to work with the library.++      -- TODO 'Value' is used for evaluating 'Lambda' expressions. It should not+      --      be exported to the user. This is only a temporary solution.++      -- TODO 'Lambda' should have a base name field instead of 'Let'.++++-- | Let binding+let_ :: (Typeable ra, Typeable a, Typeable rb, Typeable b)+    => String  -- ^ Preferred base name+    -> Lam expr ra a -> (Lam expr ra a -> Lam expr rb b) -> Lam expr rb b+let_ base a f = Let base :$: a :$: Lambda f++instance ExprEq expr => ExprEq (Lam expr)+  where+    exprEq a b = evalState (exprEqLam a b) 0++instance ExprEq expr => Eq (Lam expr role a)+  where+    (==) = exprEq++freshVar+    :: String  -- ^ Base name+    -> State Integer (Lam expr role a)+freshVar base = do+    v <- get+    put (v+1)+    return $ Variable (base ++ show v)++exprEqLam :: ExprEq expr => Lam expr ra a -> Lam expr rb b -> State Integer Bool+exprEqLam (Variable i1) (Variable i2) = return (i1 == i2)+exprEqLam (Lambda f1) (Lambda f2) = do+    i <- get+    v1 <- freshVar ""+    put i+    v2 <- freshVar ""+    exprEqLam (f1 v1) (f2 v2)+exprEqLam (f1 :$: a1) (f2 :$: a2) = do+    aCond <- exprEqLam f1 f2+    if aCond+      then exprEqLam a1 a2+      else return False+exprEqLam (Inject a) (Inject b) = return (exprEq a b)+exprEqLam (Let _)    (Let _)    = return True+exprEqLam _ _ = return False+  -- This case includes 'Value', which is only supposed to be used during+  -- evaluation.++instance Eval expr => Eval (Lam expr)+  where+    eval (Variable ident) = error $ "Evaluating variable " ++ show ident+    eval (Value a)        = a+    eval (Lambda f)       = eval . f . Value+    eval (f :$: a)        = eval f $ eval a+    eval (Inject a)       = eval a+    eval (Let _)          = flip ($)++instance ExprShow expr => ExprShow (Lam expr)+  where+    exprShow = flip evalState 0 . exprShowLam++instance ExprShow (Lam expr) => Show (Lam expr role a)+  where+    show = exprShow++-- | Shallow application. Function argument must be a 'Lambda'.+shallowApply :: Lam expr (ra -> rb) (a -> b) -> Lam expr ra a -> Lam expr rb b+shallowApply (Lambda f) = f++infixr 0 $$+($$) = shallowApply++isVar :: Lam expr role a -> Bool+isVar (Variable _) = True+isVar _            = False++isLet :: Lam expr role a -> Bool+isLet (Let _ :$: _ :$: _) = True+isLet _                   = False++-- | Parser for infix operators of the form @"(op)"@+viewInfix :: String -> Maybe String+viewInfix ('(':op)+    | (')':op') <- reverse op = Just op'+viewInfix _ = Nothing++-- | Shows a partially applied expression+exprShowApp :: ExprShow expr+    => [String]              -- ^ Missing arguments+    -> Lam expr role a       -- ^ Partially applied expression+    -> State Integer String+exprShowApp args (f :$: a) = do+    aStr <- exprShowLam a+    exprShowApp (aStr:args) f+exprShowApp args f = do+    fStr <- exprShowLam f+    return $ case (viewInfix fStr, args) of+        (Just op, [a,b]) -> "(" ++ unwords [a,op,b] ++ ")"+        _                -> "(" ++ unwords (fStr : args) ++ ")"++exprShowLam :: ExprShow expr => Lam expr role a -> State Integer String+exprShowLam (Variable ident) = return ident+exprShowLam (Value _)        = error "exprShowLam: illegal use of Value"+exprShowLam (Lambda f) = do+    v@(Variable ident) <- freshVar "v"+    body <- exprShowLam (f v)+    return $ "(\\" ++ ident ++ " -> "  ++ body ++ ")"+exprShowLam (Let base :$: a :$: Lambda f) = do+    v@(Variable ident) <- freshVar base+    aStr <- exprShowLam a+    body <- exprShowLam (f v)+    return $ "(let " ++ ident ++ " = " ++ aStr ++ " in "  ++ body ++ ")"+exprShowLam (f :$: a) = do+    aStr <- exprShowLam a+    exprShowApp [aStr] f+exprShowLam (Inject a) = return (exprShow a)++-- | Converts a partially applied expression to a tree+lamToTreeApp :: ExprShow expr+    => Forest String                -- ^ Missing arguments+    -> Lam expr role a              -- ^ Partially applied expression+    -> State Integer (Tree String)+lamToTreeApp args (f :$: a) = do+    aTree <- lamToTree a+    lamToTreeApp (aTree : args) f+lamToTreeApp args f = do+    fTree <- lamToTree f+    return $ Node "Apply" (fTree : args)++-- | Converts a lambda expression to a tree+lamToTree :: ExprShow expr => Lam expr role a -> State Integer (Tree String)+lamToTree (Variable ident) = return $ Node ("Variable " ++ ident) []+lamToTree (Value a)        = return $ Node "Value ..." []+lamToTree (Lambda f) = do+    v@(Variable ident) <- freshVar "v"+    body <- lamToTree (f v)+    return $ Node ("Lambda " ++ ident) [body]+lamToTree (Let base :$: a :$: Lambda f) = do+    v@(Variable ident) <- freshVar base+    aTree <- lamToTree a+    body  <- lamToTree (f v)+    return $ Node ("Let " ++ ident) [aTree,body]+lamToTree (f :$: a) = do+    aTree <- lamToTree a+    lamToTreeApp [aTree] f+lamToTree (Let base) = return $ Node ("Let " ++ base) []+lamToTree (Inject a) = return $ Node (exprShow a) []++-- | Show a lambda expression as a tree+showLamTree :: ExprShow expr => Lam expr role a -> String+showLamTree = drawTree . flip evalState 0 . lamToTree++-- | Print a lambda expression as a tree+drawLambda :: ExprShow expr => Lam expr role a -> IO ()+drawLambda = putStrLn . showLamTree+
+ Feldspar/DSL/Network.hs view
@@ -0,0 +1,389 @@+{-# LANGUAGE UndecidableInstances #-}++-- | This module defines computational networks.++module Feldspar.DSL.Network where++++import Control.Applicative+import Data.Typeable++import Feldspar.DSL.Expression+import Feldspar.DSL.Lambda++++-- | Empty type denoting an \"out\" role+data Out role deriving Typeable++-- | Empty type denoting an \"in\" role+data In role deriving Typeable++++-- | Expression transformer for representing network connections.+data Connection edge node role a+  where+    Node :: node role a -> Connection edge node role a+      -- Turning a @node@ expression into a network node.++    Edge :: edge () a -> Connection edge node (Out () -> In ()) (a -> a)+      -- A network edge: semantically an identity function, but decorated with+      -- some @edge@ information++    Group2 :: Connection e n (In ra -> In rb -> In (ra,rb))                         (a -> b -> (a,b))+    Group3 :: Connection e n (In ra -> In rb -> In rc -> In (ra,rb,rc))             (a -> b -> c -> (a,b,c))+    Group4 :: Connection e n (In ra -> In rb -> In rc -> In rd -> In (ra,rb,rc,rd)) (a -> b -> c -> d -> (a,b,c,d))++    Match21 :: Connection e n (Out (ra,rb) -> Out ra)       ((a,b) -> a)+    Match22 :: Connection e n (Out (ra,rb) -> Out rb)       ((a,b) -> b)+    Match31 :: Connection e n (Out (ra,rb,rc) -> Out ra)    ((a,b,c) -> a)+    Match32 :: Connection e n (Out (ra,rb,rc) -> Out rb)    ((a,b,c) -> b)+    Match33 :: Connection e n (Out (ra,rb,rc) -> Out rc)    ((a,b,c) -> c)+    Match41 :: Connection e n (Out (ra,rb,rc,rd) -> Out ra) ((a,b,c,d) -> a)+    Match42 :: Connection e n (Out (ra,rb,rc,rd) -> Out rb) ((a,b,c,d) -> b)+    Match43 :: Connection e n (Out (ra,rb,rc,rd) -> Out rc) ((a,b,c,d) -> c)+    Match44 :: Connection e n (Out (ra,rb,rc,rd) -> Out rd) ((a,b,c,d) -> d)++++-- | A computational network+--+-- A value of type @(Network edge node (In role) a)@ is called a in-edge, and a+-- value of type @(Network edge node (Out role) a)@ is called a out-edge.+--+-- It is assumed that the @node@ type is designed such that it is impossible to+-- construct a in-edge that is an (nested) application of a 'Node'. This means+-- that a value of type @(Network edge node (In ()) a)@ can only be constructed+-- by+--+-- @`Inject` (`Edge` ...) `:$:` ...@+--+-- It also means that values of type @(Network edge node (In role) a)@ are+-- always (nested) applications of 'Edge', 'Group2', 'Group3' or 'Group4'.+--+-- This ensures that all functions in this module are total.+--+-- Note that the @edge@ information will be ignored when comparing two networks+-- using 'exprEq'.+type Network edge node = Lam (Connection edge node)+  -- TODO The above is not correct anymore: 'Variable' and 'Let' can construct+  --      expressions of any type.++++instance ExprEq node => ExprEq (Connection edge node)+  where+    exprEq (Node a) (Node b)  = exprEq a b+    exprEq (Edge _) (Edge _)  = True  -- Edge information ignored+    exprEq Group2   Group2    = True+    exprEq Group3   Group3    = True+    exprEq Group4   Group4    = True+    exprEq Match21  Match21   = True+    exprEq Match22  Match22   = True+    exprEq Match31  Match31   = True+    exprEq Match32  Match32   = True+    exprEq Match33  Match33   = True+    exprEq Match41  Match41   = True+    exprEq Match42  Match42   = True+    exprEq Match43  Match43   = True+    exprEq Match44  Match44   = True+    exprEq _ _                = False++instance (ExprEq edge, ExprEq node) => Eq (Connection edge node role a)+  where+    (==) = exprEq++instance Eval node => Eval (Connection edge node)+  where+    eval (Node a) = eval a+    eval (Edge _) = id+    eval Group2   = (,)+    eval Group3   = (,,)+    eval Group4   = (,,,)+    eval Match21  = fst+    eval Match22  = snd+    eval Match31  = \(a,b,c) -> a+    eval Match32  = \(a,b,c) -> b+    eval Match33  = \(a,b,c) -> c+    eval Match41  = \(a,b,c,d) -> a+    eval Match42  = \(a,b,c,d) -> b+    eval Match43  = \(a,b,c,d) -> c+    eval Match44  = \(a,b,c,d) -> d++instance (ExprShow edge, ExprShow node) => ExprShow (Connection edge node)+  where+    exprShow (Node a) = exprShow a+    exprShow (Edge e) = "(edge " ++ exprShow e ++ ")"+    exprShow Group2   = "group2"+    exprShow Group3   = "group3"+    exprShow Group4   = "group4"+    exprShow Match21  = "match21"+    exprShow Match22  = "match22"+    exprShow Match31  = "match21"+    exprShow Match32  = "match22"+    exprShow Match33  = "match23"+    exprShow Match41  = "match41"+    exprShow Match42  = "match42"+    exprShow Match43  = "match43"+    exprShow Match44  = "match44"++++-- | This class should be thought of as roughly equivalent to 'MultiEdge'.+-- The difference is that 'EdgeInfo' has fewer constraints.+class EdgeInfo a+  where+    type Info a+    edgeInfo :: a -> Info a+  -- This class could be baked into 'MultiEdge', but that leads to unnecessary+  -- constraints for 'edgeInfo'.++-- | Types that can be converted to/from network edges. Instances must fulfill+-- 'prop_edge1' and 'prop_edge2'.+class (Typeable (Role a), Typeable (Internal a), EdgeInfo a) =>+    MultiEdge a node edge | a -> node edge+  where+    type Role     a+    type Internal a++    toEdge      :: a -> Network edge node (In (Role a)) (Internal a)+    fromInEdge  :: Network edge node (In (Role a)) (Internal a) -> a+    fromOutEdge :: Info a -> Network edge node (Out (Role a)) (Internal a) -> a++-- TODO Make node and edge associated types instead. The reason for not doing+--      this now is that it is currently not possible to make a class alias+--      fixing an associated type. But in the future (GHC 7.0, I think) this+--      will be possible.++prop_edge1 :: forall a node edge+    .  (Eval node, MultiEdge a node edge, Eq (Internal a))+    => Network edge node (In (Role a)) (Internal a)+    -> Bool+prop_edge1 a = eval a == eval (toEdge $ id' $ fromInEdge a)+  where+    id' = id :: a -> a++prop_edge2 :: forall a node edge+    .  (Eval node, MultiEdge a node edge, Eq (Internal a))+    => Info a+    -> Network edge node (Out (Role a)) (Internal a)+    -> Bool+prop_edge2 info a = eval a == eval (toEdge $ id' $ fromOutEdge info a)+  where+    id' = id :: a -> a++instance EdgeInfo (Network edge node (In ()) a)+  where+    type Info (Network edge node (In ()) a) = edge () a+    edgeInfo (Inject (Edge edge) :$: _)     = edge++instance Typeable a => MultiEdge (Network edge node (In ()) a) node edge+  where+    type Role     (Network edge node (In ()) a) = ()+    type Internal (Network edge node (In ()) a) = a++    toEdge           = id+    fromInEdge       = id+    fromOutEdge edge = (Inject (Edge edge) :$:)++instance (EdgeInfo a, EdgeInfo b) => EdgeInfo (a,b)+  where+    type Info (a,b) = (Info a, Info b)+    edgeInfo (a,b)  = (edgeInfo a, edgeInfo b)++instance+    ( MultiEdge a node edge+    , MultiEdge b node edge+    ) => MultiEdge (a,b) node edge+  where+    type Role     (a,b) = (Role a, Role b)+    type Internal (a,b) = (Internal a, Internal b)++    toEdge (a,b) = Inject Group2 :$: toEdge a :$: toEdge b++    fromInEdge (Inject Group2 :$: a :$: b) = (fromInEdge a, fromInEdge b)++    fromOutEdge (ia,ib) a =+        ( fromOutEdge ia $ Inject Match21 :$: a+        , fromOutEdge ib $ Inject Match22 :$: a+        )++instance (EdgeInfo a, EdgeInfo b, EdgeInfo c) => EdgeInfo (a,b,c)+  where+    type Info (a,b,c) = (Info a, Info b, Info c)+    edgeInfo (a,b,c)  = (edgeInfo a, edgeInfo b, edgeInfo c)++instance+    ( MultiEdge a node edge+    , MultiEdge b node edge+    , MultiEdge c node edge+    ) => MultiEdge (a,b,c) node edge+  where+    type Role     (a,b,c) = (Role a, Role b, Role c)+    type Internal (a,b,c) = (Internal a, Internal b, Internal c)++    toEdge (a,b,c) = Inject Group3 :$: toEdge a :$: toEdge b :$: toEdge c++    fromInEdge (Inject Group3 :$: a :$: b :$: c) =+        (fromInEdge a, fromInEdge b, fromInEdge c)++    fromOutEdge (ia,ib,ic) a =+        ( fromOutEdge ia $ Inject Match31 :$: a+        , fromOutEdge ib $ Inject Match32 :$: a+        , fromOutEdge ic $ Inject Match33 :$: a+        )++instance (EdgeInfo a, EdgeInfo b, EdgeInfo c, EdgeInfo d) => EdgeInfo (a,b,c,d)+  where+    type Info (a,b,c,d) = (Info a, Info b, Info c, Info d)+    edgeInfo (a,b,c,d)  = (edgeInfo a, edgeInfo b, edgeInfo c, edgeInfo d)++instance+    ( MultiEdge a node edge+    , MultiEdge b node edge+    , MultiEdge c node edge+    , MultiEdge d node edge+    ) => MultiEdge (a,b,c,d) node edge+  where+    type Role     (a,b,c,d) = (Role a, Role b, Role c, Role d)+    type Internal (a,b,c,d) = (Internal a, Internal b, Internal c, Internal d)++    toEdge (a,b,c,d)+        =   Inject Group4+        :$: toEdge a+        :$: toEdge b+        :$: toEdge c+        :$: toEdge d++    fromInEdge (Inject Group4 :$: a :$: b :$: c :$: d) =+        (fromInEdge a, fromInEdge b, fromInEdge c, fromInEdge d)++    fromOutEdge (ia,ib,ic,id) a =+        ( fromOutEdge ia $ Inject Match41 :$: a+        , fromOutEdge ib $ Inject Match42 :$: a+        , fromOutEdge ic $ Inject Match43 :$: a+        , fromOutEdge id $ Inject Match44 :$: a+        )++++-- | Remove an 'Edge' application+undoEdge :: Network edge node (In ()) a -> Network edge node (Out ()) a+undoEdge (Inject (Edge _) :$: a) = a++-- | Cast between two 'MultiEdge' types that have the same internal+-- representation.+edgeCast ::+    ( MultiEdge a node edge+    , MultiEdge b node edge+    , Internal a ~ Internal b+    , Role a     ~ Role b+    ) => a -> b+edgeCast = fromInEdge . toEdge++-- | Applies a function to each 'Edge' in an in-edge, and collects the result in+-- an applicative functor. The applied function receives the path of the edge as+-- an argument.+mapEdge :: forall app edge node ra a . Applicative app+    => (forall b . [Int] -> Network edge node (In ()) b -> app b)+    -> Network edge node (In ra) a -> app a+mapEdge f a = mapE [] a+  where+    mapE :: [Int] -> Network edge node (In rc) c -> app c+    mapE path a@(Inject (Edge _) :$: _) = f (reverse path) a+    mapE path (Inject Group2 :$: a :$: b)+        =   pure (,)+        <*> mapE (1:path) a+        <*> mapE (2:path) b+    mapE path (Inject Group3 :$: a :$: b :$: c)+        =   pure (,,)+        <*> mapE (1:path) a+        <*> mapE (2:path) b+        <*> mapE (3:path) c+    mapE path (Inject Group4 :$: a :$: b :$: c :$: d)+        =   pure (,,,)+        <*> mapE (1:path) a+        <*> mapE (2:path) b+        <*> mapE (3:path) c+        <*> mapE (4:path) d++-- | Applies a function to each 'Edge' in an in-edge, and collects the results+-- in a list. The applied function receives the path of the edge as an argument.+listEdge :: forall edge node ra a b+    .  (forall c . [Int] -> Network edge node (In ()) c -> b)+    -> Network edge node (In ra) a -> [b]+listEdge f a = listE [] a+  where+    listE :: [Int] -> Network edge node (In rd) d -> [b]+    listE path a@(Inject (Edge _) :$: _) = [f (reverse path) a]+    listE path (Inject Group2 :$: a :$: b)+        =  listE (1:path) a+        ++ listE (2:path) b+    listE path (Inject Group3 :$: a :$: b :$: c)+        =  listE (1:path) a+        ++ listE (2:path) b+        ++ listE (3:path) c+    listE path (Inject Group4 :$: a :$: b :$: c :$: d)+        =  listE (1:path) a+        ++ listE (2:path) b+        ++ listE (3:path) c+        ++ listE (4:path) d++-- | Lists the match constructors of an out-edge+matchPath :: Network edge node (Out ()) a -> [Int]+matchPath = reverse . match+  where+    match :: Network edge node (Out role) a -> [Int]+    match (Inject Match21 :$: a) = 1:match a+    match (Inject Match22 :$: a) = 2:match a+    match (Inject Match31 :$: a) = 1:match a+    match (Inject Match32 :$: a) = 2:match a+    match (Inject Match33 :$: a) = 3:match a+    match (Inject Match41 :$: a) = 1:match a+    match (Inject Match42 :$: a) = 2:match a+    match (Inject Match43 :$: a) = 3:match a+    match (Inject Match44 :$: a) = 4:match a+    match _                      = []+      -- Using local function just to be able to give more restricted type to+      -- 'matchPath'.++-- | Count the number of \"single\" edges (i.e. edges with role @In ()@)+countEdges :: Network edge node (In role) a -> Int+countEdges = length . listEdge (\_ _ -> ())++isMatch :: Connection edge node (ra -> rb) (a -> b) -> Bool+isMatch Match21 = True+isMatch Match22 = True+isMatch Match31 = True+isMatch Match32 = True+isMatch Match33 = True+isMatch Match41 = True+isMatch Match42 = True+isMatch Match43 = True+isMatch Match44 = True+isMatch _       = False++traceVar :: Network edge node (Out ()) a -> Maybe Ident+traceVar = trace+  where+    trace :: Network edge node role a -> Maybe Ident+    trace (Variable v)                 = Just v+    trace (Inject f :$: a) | isMatch f = trace a+    trace _                            = Nothing+      -- Using local function just to be able to give more restricted type to+      -- 'matchPath'.++isNode :: Network edge node ra a -> Bool+isNode (Inject (Node _)) = True+isNode (a :$: _)         = isNode a+isNode _                 = False++isEdge :: Network edge node ra a -> Bool+isEdge (Inject (Edge _) :$: _)                 = True+isEdge (Inject Group2 :$: _ :$: _)             = True+isEdge (Inject Group3 :$: _ :$: _ :$: _)       = True+isEdge (Inject Group4 :$: _ :$: _ :$: _ :$: _) = True+isEdge _ = False+
+ Feldspar/DSL/Sharing.hs view
@@ -0,0 +1,164 @@+-- | Common sub-expression elimination and variable hoisting for 'Lam'+-- expressions.++module Feldspar.DSL.Sharing where++++import Control.Monad.State+import Data.Typeable++import Feldspar.DSL.Expression+import Feldspar.DSL.Lambda++++-- | Substituting a sub-expression+substitute :: (ExprEq expr, Typeable ra, Typeable a, Typeable rb, Typeable b)+    => Lam expr ra a  -- ^ Sub-expression to be replaced+    -> Lam expr ra a  -- ^ Replacing sub-expression+    -> Lam expr rb b  -- ^ Whole expression+    -> Lam expr rb b+substitute x y a | Just y' <- exprCast y, exprEq x a = y'+substitute x y (Lambda f) = Lambda $ \v -> substitute x y (f v)+substitute x y (f :$: a)  = substitute x y f :$: substitute x y a+substitute x y a          = a++-- | Count the number of occurrences of a sub-expression+count :: (ExprEq expr, Typeable ra, Typeable a, Typeable rb, Typeable b)+    => Lam expr ra a  -- ^ Sub-expression+    -> Lam expr rb b  -- ^ Whole expression+    -> Integer+count a b = evalState (countM a b) 0++countM :: (ExprEq expr, Typeable ra, Typeable a, Typeable rb, Typeable b)+    => Lam expr ra a+    -> Lam expr rb b+    -> State Integer Integer+countM a b = case exprCast b of+    Just b' -> do+        eq <- exprEqLam a (b' `asTypeOf` a)+        if eq then return 1 else countNonEq a b+    _ -> countNonEq a b++countNonEq :: (ExprEq expr, Typeable ra, Typeable a, Typeable rb, Typeable b)+    => Lam expr ra a+    -> Lam expr rb b+    -> State Integer Integer+countNonEq a (Lambda f) = do+    v <- freshVar ""+    countM a (f v)+countNonEq a (f :$: b) = liftM2 (+) (countM a f) (countM a b)+countNonEq _ _ = return 0++++data SomeLam expr = forall ra a .+    (Typeable ra, Typeable a) => SomeLam (Lam expr ra a)++-- | Custom parameters to sharing transformation. The 'necessary' predicate+-- gives a necessary condition for lifting an expression, and 'sufficient' gives+-- a sufficient condition. Note that 'necessary' takes precedence over+-- 'sufficient'.+--+-- The 'sharingPoint' field determines whether the expression is a valid point+-- for introducing a 'Let'.+data Params expr = Params+    { necessary    :: SomeLam expr -> Bool+    , sufficient   :: SomeLam expr -> Bool+    , sharingPoint :: SomeLam expr -> Bool+    }++data Env expr = Env+    { inLambda :: Bool  -- ^ Whether the current expression is inside a lambda+    , subExpr  :: Bool  -- ^ Whether the current expression is a sub-expression+    , counter  :: SomeLam expr -> Integer+        -- ^ Counting the number of occurrences of an expression in the+        -- environment+    }++simpleParams :: Params expr+simpleParams = Params+    { necessary    = const True+    , sufficient   = const False+    , sharingPoint = const True+    }++initEnv :: (ExprEq expr, Typeable ra, Typeable a)+    => Lam expr ra a+    -> Env expr+initEnv a = Env+    { inLambda = False+    , subExpr  = False+    , counter  = \(SomeLam b) -> count b a+    }++dummy = Variable ""+ph    = Variable "PLACEHOLDER"++-- | Checks whether an expression is compound+compound :: Lam expr ra a -> Bool+compound (Lambda _) = True+compound (_ :$: _)  = True+compound _          = False++-- | Checks if the expression does not contain any @"PLACEHOLDER"@ variables+independent :: Lam expr ra a -> Bool+independent (Variable ident) = ident /= "PLACEHOLDER"+independent (Lambda f)       = independent (f dummy)+independent (f :$: a)        = independent f && independent a+independent _                = True++-- | Checks whether a sub-expression in a given environment can be lifted out+liftable :: (Typeable ra, Typeable a)+    => Params expr+    -> Env expr+    -> Lam expr ra a -> Bool+liftable params env a+    =  independent a  -- Lifting dependent expressions is semantically incorrect+    && subExpr env    -- Otherwise infinite loop+    && necessary params (SomeLam a)+    && (heuristic || sufficient params (SomeLam a))+  where+    heuristic = compound a && (inLambda env || (counter env (SomeLam a) > 1))++-- | Chooses a sub-expression to lift out+choose :: (Typeable ra, Typeable a) =>+    Params expr -> Env expr -> Lam expr ra a -> Maybe (SomeLam expr)+choose par env a | liftable par env a = Just (SomeLam a)+choose par env (Lambda f) = choose par env' (f ph)+  where env' = env {inLambda = True, subExpr = True}+choose par env (f :$: a) = choose par env' f `mplus` choose par env' a+  where env' = env {subExpr = True}+choose _ _ _ = Nothing++-- | Perform common sub-expression elimination and variable hoisting+sharing :: forall expr ra a . (ExprEq expr, Typeable ra, Typeable a)+    => Params expr+    -> Lam expr ra a+    -> Lam expr ra a+sharing par a = case choose par (initEnv a) a of+    Just b | sharingPoint par (SomeLam a) -> share b+    _ -> descend par a+  where+    share :: SomeLam expr -> Lam expr ra a+    share (SomeLam b) = let_ "v" (sharing par b) f+      where f x = sharing par (substitute b x a)++descend :: (ExprEq expr, Typeable ra, Typeable a)+    => Params expr+    -> Lam expr ra a+    -> Lam expr ra a+descend params (Lambda f) = Lambda $ \v -> sharing params (f v)+descend params (f :$: a)  = sharing params f :$: sharing params a+descend _ a = a++simpleSharing :: (ExprEq expr, Typeable ra, Typeable a) =>+    Lam expr ra a -> Lam expr ra a+simpleSharing = sharing simpleParams++-- | Checks if the expression computes a function. Can be used in the parameters+-- passed to 'sharing'.+isFunction :: forall expr ra a . Typeable a => Lam expr ra a -> Bool+isFunction _ = show (typeRepTyCon $ typeOf (undefined :: a)) == "->"+
+ Feldspar/DSL/Val.hs view
@@ -0,0 +1,78 @@+-- | Simple example language built using 'Lam'.++module Feldspar.DSL.Val where++++import Data.Typeable++import Feldspar.DSL.Expression+import Feldspar.DSL.Lambda+import Feldspar.DSL.Sharing++++--------------------------------------------------------------------------------+-- * Library+--------------------------------------------------------------------------------++data Val role a = Val String a++instance ExprEq Val+  where+    exprEq (Val v1 _) (Val v2 _) = v1==v2++instance Eval Val+  where+    eval (Val _ a) = a++instance ExprShow Val+  where+    exprShow (Val val _) = val++simpleVal :: Show a => a -> Lam Val () a+simpleVal a = Inject $ Val (show a) a++function :: (Typeable ra, Typeable a) =>+    String -> (a -> b) -> (Lam Val ra a -> Lam Val rb b)+function name f a = Inject (Val name f) :$: a++function2 :: (Typeable ra, Typeable a, Typeable rb, Typeable b) =>+    String -> (a -> b -> c) -> (Lam Val ra a -> Lam Val rb b -> Lam Val rc c)+function2 name f a b = Inject (Val name f) :$: a :$: b++int :: Int -> Lam Val () Int+int = simpleVal++true  = simpleVal True+false = simpleVal False++instance (Num a, Typeable a) => Num (Lam Val () a)+  where+    fromInteger = simpleVal . fromInteger+    abs         = function "abs" abs+    signum      = function "signum" signum+    (+)         = function2 "(+)" (+)+    (-)         = function2 "(-)" (-)+    (*)         = function2 "(*)" (*)++++--------------------------------------------------------------------------------+-- * Examples+--------------------------------------------------------------------------------++expr1 :: Lam Val (() -> ()) (Int -> Int)+expr1 = Lambda $ \x -> x + (let_ "temp" (2 + 3 + x) $ \y -> y+x)++expr2 :: Lam Val (() -> ()) (Int -> Int)+expr2 = Lambda $ \x -> x + (let_ "temp" (2 + 3 + x) $ \y -> 2 + 3 + y+x)++test1 = drawLambda expr2+test2 = drawLambda $ simpleSharing expr2++problem = drawLambda $+    simpleSharing ((1+2+3) + (1+2+4) + (1+2+3+4) :: Lam Val () Int)+  -- TODO: 1+2 not shared+  --       Use fixpoint iteration?+
Feldspar/FixedPoint.hs view
@@ -1,577 +1,228 @@------ Copyright (c) 2009-2010, ERICSSON AB All rights reserved.--- --- Redistribution and use in source and binary forms, with or without--- modification, are permitted provided that the following conditions are met:--- ---     * Redistributions of source code must retain the above copyright notice,---       this list of conditions and the following disclaimer.---     * 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 name of the ERICSSON AB nor the names of its contributors---       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 AND CONTRIBUTORS "AS IS"--- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE--- IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE--- ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS--- BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,--- OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF--- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS--- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN--- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)--- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF--- THE POSSIBILITY OF SUCH DAMAGE.-----module Feldspar.FixedPoint where+{-# LANGUAGE UndecidableInstances #-}+module Feldspar.FixedPoint+    ( Fix(..), Fixable(..)+    , freezeFix, freezeFix', unfreezeFix, unfreezeFix'+    , (?!), fixFold+    )+where  import qualified Prelude-import Feldspar.Prelude-import Feldspar.Core.Types-import Feldspar.Core.Expr-import Feldspar.Core+import Feldspar+import Feldspar.DSL.Network hiding (In,Out)+import Feldspar.Core.Representation+import Feldspar.Vector import Data.Ratio -import System.IO.Unsafe-import Feldspar.Core.Functions--type Fix32  = (Int, Data Signed32)-type UFix32 = (Int, Data Unsigned32)-type Fix16  = (Int, Data Signed16)-type UFix16 = (Int, Data Unsigned16)-type Fix8  = (Int, Data Signed8)-type UFix8 = (Int, Data Unsigned8)-type Fix  = (Int,Data Int)--intToFix :: Int -> Data Int -> Fix-intToFix exp val = (exp, val)--intToFix32 :: Int -> Data Signed32 -> Fix32-intToFix32 exp val = (exp, val)--intToUFix32 :: Int -> Data Unsigned32 -> UFix32-intToUFix32 exp val = (exp, val)--intToFix16 :: Int -> Data Signed16 -> Fix16-intToFix16 exp val = (exp, val)--intToUFix16 :: Int -> Data Unsigned16 -> UFix16-intToUFix16 exp val = (exp, val)--intToFix8 :: Int -> Data Signed8 -> Fix8-intToFix8 exp val = (exp, val)--intToUFix8 :: Int -> Data Unsigned8 -> UFix8-intToUFix8 exp val = (exp, val)--fixToInt :: Int -> Fix -> Data Int-fixToInt exp' (exp,val) = val `leftShift` (exp-exp')--fix32ToInt :: Int -> Fix32 -> Data Signed32-fix32ToInt exp' (exp,val) = val `leftShift` (exp-exp')--uFix32ToInt :: Int -> UFix32 -> Data Unsigned32-uFix32ToInt exp' (exp,val) = val `leftShift` (exp-exp')--fix16ToInt :: Int -> Fix16 -> Data Signed16-fix16ToInt exp' (exp,val) = val `leftShift` (exp-exp')--uFix16ToInt :: Int -> UFix16 -> Data Unsigned16-uFix16ToInt exp' (exp,val) = val `leftShift` (exp-exp')--fix8ToInt :: Int -> Fix8 -> Data Signed8-fix8ToInt exp' (exp,val) = val `leftShift` (exp-exp')--uFix8ToInt :: Int -> UFix8 -> Data Unsigned8-uFix8ToInt exp' (exp,val) = val `leftShift` (exp-exp')--floatToFix :: Float -> Fix-floatToFix f = (0, value $ Prelude.round f)--floatToFix32 :: Float -> Fix32-floatToFix32 f = (0, value $ Prelude.round f)--floatToUFix32 :: Float -> UFix32-floatToUFix32 f = (0, value $ Prelude.round f)--floatToFix16 :: Float -> Fix16-floatToFix16 f = (0, value $ Prelude.round f)--floatToUFix16 :: Float -> UFix16-floatToUFix16 f = (0, value $ Prelude.round f)--floatToFix8 :: Float -> Fix8-floatToFix8 f = (0, value $ Prelude.round f)--floatToUFix8 :: Float -> UFix8-floatToUFix8 f = (0, value $ Prelude.round f)---floatToFix32' :: Int -> Float -> Fix32-floatToFix32' exp fl = (exp, value $ Prelude.round $-          (fl Prelude./ (2.0 Prelude.** (fromInteger(toInteger exp)))::Float))--floatToUFix32' :: Int -> Float -> UFix32-floatToUFix32' exp fl = (exp, value $ Prelude.round $-          (fl Prelude./ (2.0 Prelude.** (fromInteger(toInteger exp)))::Float))--floatToFix16' :: Int -> Float -> Fix16-floatToFix16' exp fl = (exp, value $ Prelude.round $-          (fl Prelude./ (2.0 Prelude.** (fromInteger(toInteger exp)))::Float))--floatToUFix16' :: Int -> Float -> UFix16-floatToUFix16' exp fl = (exp, value $ Prelude.round $-          (fl Prelude./ (2.0 Prelude.** (fromInteger(toInteger exp)))::Float))--floatToFix8' :: Int -> Float -> Fix8-floatToFix8' exp fl = (exp, value $ Prelude.round $-          (fl Prelude./ (2.0 Prelude.** (fromInteger(toInteger exp)))::Float))--floatToUFix8' :: Int -> Float -> UFix8-floatToUFix8' exp fl = (exp, value $ Prelude.round $-          (fl Prelude./ (2.0 Prelude.** (fromInteger(toInteger exp)))::Float))---toExp32 :: Int -> Fix32 -> Fix32-toExp32 exp (e,i) = (exp, i `leftShift` (e-exp))--toExpU32 :: Int -> UFix32 -> UFix32-toExpU32 exp (e,i) = (exp, i `leftShift` (e-exp))--toExp16 :: Int -> Fix16 -> Fix16-toExp16 exp (e,i) = (exp, i `leftShift` (e-exp))--toExpU16 :: Int -> UFix16 -> UFix16-toExpU16 exp (e,i) = (exp, i `leftShift` (e-exp))--toExp8 :: Int -> Fix8 -> Fix8-toExp8 exp (e,i) = (exp, i `leftShift` (e-exp))--toExpU8 :: Int -> UFix8 -> UFix8-toExpU8 exp (e,i) = (exp, i `leftShift` (e-exp))--fixToFloat :: (Integral a,Integral b) => ( a , Data b ) -> Float-fixToFloat fix =( 2.0 Prelude.** (fromInteger (toInteger(fst fix)))) Prelude.*-                 ( (fromInteger ( toInteger ( evalD (snd fix) )) )::Float )--fix32ToFloat :: Fix32-> Float-fix32ToFloat fix = fixToFloat fix--uFix32ToFloat :: UFix32-> Float-uFix32ToFloat fix = fixToFloat fix--fix16ToFloat :: Fix16-> Float-fix16ToFloat fix = fixToFloat fix--uFix16ToFloat :: UFix16-> Float-uFix16ToFloat fix = fixToFloat fix+-- | Abstract real number type with exponent and mantissa+data Fix a =+    Fix+    { exponent  :: Data DefaultInt+    , mantissa  :: Data a+    }+    deriving (Prelude.Eq,Prelude.Show) -fix8ToFloat :: Fix8-> Float-fix8ToFloat fix = fixToFloat fix+instance+    ( Bounded a+    , Numeric a+    , Bits a+    , Ord a+    , Range a ~ Size a+    , Prelude.Real a+    ) => Num (Fix a)+  where+    fromInteger n = Fix 0 (Prelude.fromInteger n)+    (+) = fixAddition+    (*) = fixMultiplication+    negate = fixNegate+    abs = fixAbsolute+    signum = fixSignum -uFix8ToFloat :: UFix8-> Float-uFix8ToFloat fix = fixToFloat fix+instance+    ( Bounded a+    , Numeric a+    , Bits a+    , Ord a+    , Range a ~ Size a+    , Prelude.Real a+    , Integral a+    ) => Fractional (Fix a)+  where+    (/) = fixDiv'+    recip = fixRecip'+    fromRational = fixfromRational -inBounds :: Bool -> Int -> Int -> Bool-inBounds s wbits i | s Prelude.&& (i Prelude.> sintmax)       = False-           | s Prelude.&& (i Prelude.< sintmin)               = False-           | (Prelude.not s) Prelude.&& (i Prelude.> uintmax) = False-           | (Prelude.not s) Prelude.&& (i Prelude.< uintmin) = False-           | otherwise  = True+fixAddition :: (Bounded a,Numeric a, Bits a, Ord a, Range a ~ Size a, Prelude.Real a) => Fix a -> Fix a -> Fix a+fixAddition f1@(Fix e1 m1) f2@(Fix e2 m2) = Fix e m    where-      (sintmax :: Int) = 2 Prelude.^ (wbits Prelude.- 1) - 1-      (sintmin :: Int) = -sintmax-      (uintmax :: Int) = 2 Prelude.^ wbits Prelude.- 1-      (uintmin :: Int) = 0--fl01toFix :: (Integral a,Integral b) => Bool ->Int-> Float-                                     -> (a,Data b) -> Bool -> (a,Data b)-fl01toFix s bts fl fix gt-  | (Prelude.not gt) Prelude.&& ( fl1 Prelude.> fl   ) =-        fl01toFix s bts fl ((fst fix) Prelude.- 1, snd fix  ) Prelude.False-  | (Prelude.not gt) Prelude.&& ( fl1 Prelude.< fl   ) =-        fl01toFix s bts fl ((fst fix) Prelude.- 1, snd fix  ) Prelude.True-  | (Prelude.not gt) Prelude.&& ( fl1 Prelude.== fl   ) =-        ((fst fix) Prelude.- 1, snd fix  )-  | gt Prelude.&& ( (inBounds s bts val') Prelude.&& ( fl2 Prelude.> fl )  ) =-      fl01toFix s bts fl ((fst fix) Prelude.- 1, 2 * (snd fix) ) Prelude.True-  | gt Prelude.&& ( (inBounds s bts val') Prelude.&& ( fl2 Prelude.< fl )  ) =-      fl01toFix s bts fl ((fst fix) Prelude.- 1,2 * ( snd fix) + 1) Prelude.True-  | gt Prelude.&& ( (inBounds s bts val') Prelude.&& ( fl2 Prelude.== fl )  ) =-      fl01toFix s bts fl ((fst fix) Prelude.- 1, 2 * (snd fix) +1 ) Prelude.True-  | otherwise = fix-    where-      fl2 = (2.0 Prelude.* (fromInteger val) Prelude.+ 1.0 ) Prelude.*-            (2.0 Prelude.** ( (fromInteger exp) Prelude.- 1.0 ))-      fl1 =( fromInteger val ) Prelude.*-           (2.0 Prelude.** ( (fromInteger exp) Prelude.- 1.0 ))-      val'= 2 Prelude.* (fromInteger val) Prelude.+ 1-      val = toInteger $ evalD $ snd fix-      exp = toInteger $ fst fix--fl01toFix' :: Float -> Fix -> Bool -> Fix-fl01toFix' = fl01toFix True 31--fl01toUFix32 :: Float -> UFix32 -> Bool -> UFix32-fl01toUFix32 = fl01toFix False 32--fl01toFix32  :: Float -> Fix32 -> Bool -> Fix32-fl01toFix32 = fl01toFix True 31--fl01toUFix16 :: Float -> UFix16 -> Bool -> UFix16-fl01toUFix16 = fl01toFix False 16--fl01toFix16  :: Float -> Fix16 -> Bool -> Fix16-fl01toFix16 = fl01toFix True 15--fl01toUFix8 :: Float -> UFix8 -> Bool -> UFix8-fl01toUFix8 = fl01toFix False 8--fl01toFix8  :: Float -> Fix8 -> Bool -> Fix8-fl01toFix8 = fl01toFix True 7--zeroOneToFix :: Float -> Fix-zeroOneToFix fl = fl01toFix' fl (1,1) Prelude.False--zeroOneToFix32 :: Float -> Fix32-zeroOneToFix32 fl = fl01toFix32 fl (1,1) Prelude.False--zeroOneToUFix32 :: Float -> UFix32-zeroOneToUFix32 fl = fl01toUFix32 fl (1,1) Prelude.False--zeroOneToFix16 :: Float -> Fix16-zeroOneToFix16 fl = fl01toFix16 fl (1,1) Prelude.False--zeroOneToUFix16 :: Float -> UFix16-zeroOneToUFix16 fl = fl01toUFix16 fl (1,1) Prelude.False--zeroOneToFix8 :: Float -> Fix8-zeroOneToFix8 fl = fl01toFix8 fl (1,1) Prelude.False--zeroOneToUFix8 :: Float -> UFix8-zeroOneToUFix8 fl = fl01toUFix8 fl (1,1) Prelude.False---addFix ::(Integral b,Bits b) =>-              Int -> (Int,Data b) -> (Int,Data b) -> (Int,Data b)-addFix e (e1,i1) (e2,i2) =-      (e, i1 `leftShift` (e1 Prelude.- e) + i2 `leftShift` (e2 Prelude.- e))--addFix'' :: Int -> Fix -> Fix -> Fix-addFix'' = addFix--addFix32 :: Int -> Fix32 -> Fix32 -> Fix32-addFix32 = addFix--addUFix32 :: Int -> UFix32 -> UFix32 -> UFix32-addUFix32 = addFix--addFix16 :: Int -> Fix16 -> Fix16 -> Fix16-addFix16 = addFix--addUFix16 :: Int -> UFix16 -> UFix16 -> UFix16-addUFix16 = addFix--addFix8 :: Int -> Fix8 -> Fix8 -> Fix8-addFix8 = addFix--addUFix8 :: Int -> UFix8 -> UFix8 -> UFix8-addUFix8 = addFix+     e    =  max e1 e2+     m    =  mantissa (fix e f1) + mantissa (fix e f2) -recipFix :: (Integral b,Bits b) =>-                Int -> (Int,Data b) -> (Int,Data b)-recipFix exp (e,i) = (e2,i2)+fixMultiplication :: (Bounded a,Numeric a, Bits a, Ord a, Range a ~ Size a, Prelude.Real a) => Fix a -> Fix a -> Fix a+fixMultiplication f1@(Fix e1 m1) f2@(Fix e2 m2) = Fix e m    where-      e2 = exp-      i2 = div sh i-      sh = 1 `rightShift` (exp Prelude.+ e)--recipFix' :: Int -> Fix -> Fix-recipFix' =  recipFix--recipFix32 :: Int -> Fix32 -> Fix32-recipFix32 =  recipFix--recipUFix32 :: Int -> UFix32 -> UFix32-recipUFix32 =  recipFix--recipFix16 :: Int -> Fix16 -> Fix16-recipFix16 =  recipFix--recipUFix16 :: Int -> UFix16 -> UFix16-recipUFix16 =  recipFix--recipFix8 :: Int -> Fix8 -> Fix8-recipFix8 =  recipFix--recipUFix8 :: Int -> UFix8 -> UFix8-recipUFix8 =  recipFix--divFix :: (Integral b,Bits b) =>-               Int -> (Int,Data b) -> (Int,Data b)-           -> (Int,Data b)-divFix exp (e1,i1) (e2,i2) = (e,i)+     e  =  e1 + e2+     m    =  m1 * m2+     +fixNegate :: (Bounded a,Numeric a, Bits a, Ord a, Range a ~ Size a, Prelude.Real a) => Fix a -> Fix a +fixNegate f1@(Fix e1 m1)  = Fix e1 m    where-      e = exp-      i = div sh i2-      val = e1 Prelude.- e2 Prelude.- exp-      sh = i1 `leftShift` val--divFix' :: Int -> Fix -> Fix -> Fix-divFix' = divFix--divFix32 :: Int -> Fix32 -> Fix32 -> Fix32-divFix32 = divFix--divUFix32 :: Int -> UFix32 -> UFix32 -> UFix32-divUFix32 = divFix--divFix16 :: Int -> Fix16 -> Fix16 -> Fix16-divFix16 = divFix--divUFix16 :: Int -> UFix16 -> UFix16 -> UFix16-divUFix16 = divFix--divFix8 :: Int -> Fix8 -> Fix8 -> Fix8-divFix8 = divFix--divUFix8 :: Int -> UFix8 -> UFix8 -> UFix8-divUFix8 = divFix+     m = negate m1 -addFix' ::(Integral b,Bits b) =>-              (Int,Data b) -> (Int,Data b) -> (Int,Data b)-addFix' (e1,i1) (e2,i2) =-      (  m, ( i1 `leftShift` (e1 Prelude.- m)) +-             ( i2 `leftShift` ( e2 Prelude.- m ) ) )+fixAbsolute :: (Bounded a,Numeric a, Bits a, Ord a, Range a ~ Size a, Prelude.Real a) => Fix a -> Fix a +fixAbsolute f1@(Fix e1 m1)  = Fix e1 m    where-      m = Prelude.max e1 e2--mulFix' ::(Integral b,Bits b) =>-              (Int,Data b) -> (Int,Data b) -> (Int,Data b)-mulFix' (e1,i1) (e2,i2)=(added ,(i1*i2 ) )-      where-        added = e1 Prelude.+ e2--negate' ::(Integral b,Bits b) =>-              (Int,Data b) -> (Int,Data b)-negate' (e,i) = (e, negate i )--abs' ::(Integral b,Bits b) =>-              (Int,Data b) -> (Int,Data b)-abs' (e,i) = (e,abs(i))--signum' ::(Integral b,Bits b) =>-              (Int,Data b) -> (Int,Data b)-signum' (e,i) = ( 0 , signum i )--fromInteger' ::(Integral b,Bits b) =>-                Integer -> (Int,Data b)-fromInteger' i = ( 0 , fromInteger i )--instance Num Fix where-    x + y = addFix' x y-    x * y=mulFix' x y-    negate = negate'-    abs = abs'-    signum = signum'-    fromInteger = fromInteger'--instance Num Fix32 where-    x + y = addFix' x y-    x * y=mulFix' x y-    negate = negate'-    abs = abs'-    signum = signum'-    fromInteger = fromInteger'--instance Num UFix32 where-    x + y = addFix' x y-    x * y=mulFix' x y-    negate = negate'-    abs = abs'-    signum = signum'-    fromInteger = fromInteger'--instance Num Fix16 where-    x + y = addFix' x y-    x * y=mulFix' x y-    negate = negate'-    abs = abs'-    signum = signum'-    fromInteger = fromInteger'--instance Num UFix16 where-    x + y = addFix' x y-    x * y=mulFix' x y-    negate = negate'-    abs = abs'-    signum = signum'-    fromInteger = fromInteger'---instance Num Fix8 where-    x + y = addFix' x y-    x * y=mulFix' x y-    negate = negate'-    abs = abs'-    signum = signum'-    fromInteger = fromInteger'--instance Num UFix8 where-    x + y = addFix' x y-    x * y=mulFix' x y-    negate = negate'-    abs = abs'-    signum = signum'-    fromInteger = fromInteger'--recip' ::(Integral b,Bits b) =>-              Int -> (Int,Data b) -> (Int,Data b)-recip' bts (e,i) = ( e2, i2 )-      where-        k   = bts - 2-        e2  = Prelude.negate $ e Prelude.+ k-        sh  = 1 `leftShift` k-        i2  = div sh i--fromRational' ::(Integral b,Bits b,Num (Int,Data b)) =>-                Bool -> Int->(Float->(Int,Data b))->(Integer->(Int,Data b))-                    -> Rational -> (Int,Data b)-fromRational' s bts zotf fi  rat = addFix e integ frac-      where-       e      = (fst frac) Prelude.+ toShift'-       toShift' | s = Prelude.min toShift-                    ((bts Prelude.- 1) Prelude.- bitsInteg)-                | (Prelude.not s) =-                    Prelude.min toShift (bts Prelude.- bitsInteg)-       toShift | s = Prelude.max 0-                   (bitsFrac Prelude.- (bts Prelude.- 1) Prelude.+ bitsInteg)-               | (Prelude.not s) =-                   Prelude.max 0 (bitsFrac Prelude.- bts Prelude.+ bitsInteg)-       bitsFrac  = Prelude.floor $-                     Prelude.logBase 2.0 (fromInteger (toInteger vfrac))-       bitsInteg = Prelude.floor $-                     Prelude.logBase 2.0 (fromInteger (toInteger vinteg))-       vinteg = evalD $ snd integ-       vfrac  = evalD $ snd frac-       frac   = zotf fl01-       integ  = (fi-                  ( Prelude.quot (numerator rat) (denominator rat)  ))-       fl01   = fl - ((Prelude.fromInteger (Prelude.floor fl))::Float)-       fl     = (Prelude.fromRational rat)::Float--instance Fractional Fix where-   recip = recip' 32-   fromRational = fromRational' True  32 zeroOneToFix fromInteger--instance Fractional Fix32 where-   recip = recip' 32-   fromRational = fromRational' True 32 zeroOneToFix32 fromInteger--instance Fractional UFix32 where-   recip = recip' 31-   fromRational = fromRational' False 31 zeroOneToUFix32 fromInteger--instance Fractional Fix16 where-   recip = recip' 16-   fromRational = fromRational' True 16 zeroOneToFix16 fromInteger+     m = abs m1 -instance Fractional UFix16 where-   recip = recip' 15-   fromRational = fromRational' False 15 zeroOneToUFix16 fromInteger+fixSignum :: (Bounded a,Numeric a, Bits a, Ord a, Range a ~ Size a, Prelude.Real a) => Fix a -> Fix a +fixSignum f1@(Fix e1 m1)  = Fix 0 m+   where+     m = signum m1 -instance Fractional Fix8 where-   recip = recip' 8-   fromRational = fromRational' True 8 zeroOneToFix8 fromInteger+fixFromInteger :: (Bounded a,Numeric a, Bits a, Ord a, Range a ~ Size a, Prelude.Real a) =>  Integer -> Fix a +fixFromInteger i  = Fix 0 m+   where+     m = fromInteger i -instance Fractional UFix8 where-   recip = recip' 7-   fromRational = fromRational' False 7 zeroOneToUFix8 fromInteger+fixDiv' :: (Bounded a,Numeric a, Bits a, Ord a, Range a ~ Size a, Prelude.Real a,Integral a) => Fix a -> Fix a -> Fix a+fixDiv' f1@(Fix e1 m1) f2@(Fix e2 m2) = Fix e m+   where+     e = e1-e2+     m  = div m1 m2 -class FixFloatLike a  where-   addFF   :: Int -> a -> a -> a-   recipFF :: Int -> a -> a-   divFF   :: Int -> a -> a -> a+fixRecip' :: forall a . (Bounded a,Numeric a, Bits a, Ord a, Range a ~ Size a, Prelude.Real a,Integral a) => Fix a -> Fix a+fixRecip' f@(Fix e m) = Fix (e + (value $ wordLength (T :: T a) - 1)) (div sh m)+   where+     sh  :: Data a+     sh  = (1::Data a) << (value $ fromInteger $ toInteger $ wordLength (T :: T a) - 1) -instance FixFloatLike (Data Float) where-   addFF _ x y = x + y-   recipFF _ x = 1/x-   divFF _ x y = x/y+fixfromRational :: forall a . (Range a ~ Size a, Numeric a, Integral a, Num a,Type a) =>+                   Prelude.Rational -> Fix a+fixfromRational inp = Fix exponent mantissa+   where+      inpAsFloat :: Float+      inpAsFloat =  fromRational inp+      intPart :: Float+      intPart =  fromRational $ toRational $ (Prelude.floor inpAsFloat)+      intPartWidth :: DefaultInt+      intPartWidth =  Prelude.ceiling  $ logBase 2 intPart+      fracPartWith :: DefaultInt+      fracPartWith =  (wordLength (T :: T a)) - intPartWidth - 2+      mantissa = value $ Prelude.floor $ inpAsFloat * 2.0 ** fromRational (toRational fracPartWith)+      exponent =  negate $ value fracPartWith +instance (Type a) => EdgeInfo (Fix a)+  where+    type Info (Fix a)   = EdgeSize () (DefaultInt, a)+    edgeInfo            = edgeInfo . toEdge -instance FixFloatLike Fix where-   addFF   = addFix''-   recipFF = recipFix'-   divFF   = divFix'+instance (Type a) => MultiEdge (Fix a) Feldspar EdgeSize+  where+    type Role     (Fix a)   = ()+    type Internal (Fix a)   = (DefaultInt, a)+    toEdge           = toEdge . freezeFix+    fromInEdge       = unfreezeFix . fromInEdge+    fromOutEdge info = unfreezeFix . fromOutEdge info -instance FixFloatLike Fix32 where-   addFF   = addFix32-   recipFF = recipFix32-   divFF   = divFix32+instance (Type a) => Syntactic (Fix a) -instance FixFloatLike UFix32 where-   addFF   = addUFix32-   recipFF = recipUFix32-   divFF   = divUFix32+-- | Convers an abstract real number to a pair of exponent and mantissa+freezeFix :: (Type a) => Fix a -> Data (DefaultInt,a)+freezeFix (Fix e m) = pair e m -instance FixFloatLike Fix16 where-   addFF   = addFix16-   recipFF = recipFix16-   divFF   = divFix16+-- | Convers an abstract real number to fixed point integer with given exponent+freezeFix' :: (Bits a) => DefaultInt -> Fix a -> Data a+freezeFix' e f = mantissa $ fix (value e) f -instance FixFloatLike UFix16 where-   addFF   = addUFix16-   recipFF = recipUFix16-   divFF   = divUFix16+-- | Converts a pair of exponent and mantissa to an abstract real number+unfreezeFix :: (Type a) => Data (DefaultInt,a) -> Fix a+unfreezeFix p = Fix (getFst p) (getSnd p) -instance FixFloatLike Fix8 where-   addFF   = addFix8-   recipFF = recipFix8-   divFF   = divFix8+-- | Converts a fixed point integer with given exponent to an abstract real number+unfreezeFix' :: DefaultInt -> Data a -> Fix a+unfreezeFix' e m = Fix (value e) m -instance FixFloatLike UFix8 where-   addFF   = addUFix8-   recipFF = recipUFix8-   divFF   = divUFix8+significantBits :: forall a . (Type a, Size a ~ Range a, Num a, Ord a, Prelude.Real a) => Data a -> DefaultInt+significantBits x = DefaultInt $ fromInteger $ toInteger $ (Prelude.floor mf)+1+  where+    r :: Range a+    r = dataSize x+    m :: a+    m = Prelude.max (Prelude.abs $ lowerBound r) (Prelude.abs $ upperBound r)+    mf :: Float+    mf = logBase 2 $ fromRational $ toRational m +setSignificantBits :: forall a . (Type a, Size a ~ Range a, Num a, Ord a, Prelude.Real a) => a -> Data a -> Data a+setSignificantBits sb x = resizeData r x+   where +     r :: Range a+     r =  Range 0 sb -class FromFloat t where-   float :: Float -> t+wordLength :: forall a . (Prelude.Bounded a,Type a,Size a ~ Range a,Num a,Ord a,Prelude.Real a) => T a -> DefaultInt+wordLength x = (Prelude.ceiling $ logBase 2 $ fromRational $ toRational (maxBound :: a)) + 1 -instance FromFloat (Data Float) where-   float = value+wordLength' :: forall a . (Prelude.Bounded a,Prelude.Real a) => a -> DefaultInt+wordLength' x = swl+   where+    b   :: a+    wl  :: DefaultInt+    swl :: DefaultInt+    b   = maxBound::a+    wl  = Prelude.ceiling $ logBase 2 $ fromRational $ toRational b+    swl = wl + 1  -instance FromFloat Fix where-   float = floatToFix+-- | Operations to get and set exponent+class (Splittable t) => Fixable t where+    fix :: Data DefaultInt -> t -> t+    getExp :: t -> Data DefaultInt -instance FromFloat Fix32 where-   float = floatToFix32+instance (Bits a) => Fixable (Fix a) where+    fix e' (Fix e m) = Fix e' $ e' > e ? (m >> i2n (e' - e), m << i2n (e - e'))+    getExp = Feldspar.FixedPoint.exponent -instance FromFloat UFix32 where-   float = floatToUFix32+instance Fixable (Data Float) where+    fix = const id+    getExp = const $ fromInteger $ toInteger $ Feldspar.exponent (0.0 :: Float) -instance FromFloat Fix16 where-   float = floatToFix16+data T a = T -instance FromFloat UFix16 where-   float = floatToUFix16+-- | Operations to split data into dynamic and static parts+class (Syntactic (Dynamic t)) => Splittable t where+    type Static t+    type Dynamic t+    store       :: t -> (Static t, Dynamic t)+    retrieve    :: (Static t, Dynamic t) -> t+    patch       :: Static t -> t -> t+    common      :: t -> t -> Static t -instance FromFloat Fix8 where-   float = floatToFix8+instance (Type a) => Splittable (Data a) where+    type Static (Data a) = ()+    type Dynamic (Data a) = Data a+    store x = ((),x)+    retrieve = snd+    patch = const id+    common _ _ = () -instance FromFloat UFix8 where-   float = floatToUFix8+instance (Type a, Bits a) => Splittable (Fix a) where+    type Static (Fix a) = Data DefaultInt+    type Dynamic (Fix a) = Data a+    store f = (Feldspar.FixedPoint.exponent f, mantissa f)+    retrieve = uncurry Fix+    patch = fix+    common f g = max (Feldspar.FixedPoint.exponent f) (Feldspar.FixedPoint.exponent g) --- Helper functions to generate shift with non-negative parameter-leftShift :: Bits a => Data a -> Int -> Data a-leftShift a b-    | b Prelude.>= 0    = a << value b-    | otherwise         = a >> value (Prelude.negate b)+-- | A version of vector fold for fixed point algorithms+fixFold :: forall a b . (Splittable a) => (a -> b -> a) -> a -> Vector b -> a+fixFold fun ini vec = retrieve (static, fold fun' ini' vec)+  where+    static = fst $ store ini+    ini' = snd $ store ini+    fun' st el = snd $ store $ patch static $ retrieve (static,st) `fun` el -rightShift :: Bits a => Data a -> Int -> Data a-rightShift a b-    | b Prelude.>= 0    = a >> value b-    | otherwise         = a << value (Prelude.negate b)+-- | A version of branching for fixed point algorithms+infix 1 ?!+(?!) :: forall a . (Syntactic a, Splittable a) => Data Bool -> (a,a) -> a+cond ?! (x,y) = retrieve (comm, cond ? (x',y'))+  where+    comm = common x y+    x' = snd $ store $ patch comm x+    y' = snd $ store $ patch comm y
− Feldspar/Haskell.hs
@@ -1,101 +0,0 @@------ Copyright (c) 2009-2010, ERICSSON AB All rights reserved.--- --- Redistribution and use in source and binary forms, with or without--- modification, are permitted provided that the following conditions are met:--- ---     * Redistributions of source code must retain the above copyright notice,---       this list of conditions and the following disclaimer.---     * 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 name of the ERICSSON AB nor the names of its contributors---       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 AND CONTRIBUTORS "AS IS"--- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE--- IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE--- ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS--- BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,--- OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF--- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS--- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN--- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)--- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF--- THE POSSIBILITY OF SUCH DAMAGE.------- | Helper functions for producing Haskell code--module Feldspar.Haskell where----import Data.List------ | Types that can represent Haskell types (as source code strings)-class HaskellType a-  where-    -- | Gives the Haskell type denoted by the argument.-    haskellType :: a -> String------ | Types that can represent Haskell values (as source code strings)-class HaskellValue a-  where-    -- | Gives the Haskell code denoted by the argument.-    haskellValue :: a -> String--instance HaskellValue String-  where-    haskellValue = id--instance HaskellValue Int-  where-    haskellValue = show------ | Like 'Data.List.unlines', but no trailing @\'\\n\'@.-unlinesNoTrail :: [String] -> String-unlinesNoTrail = intercalate "\n"---- | Indents a string the given number of columns.-indent :: Int -> String -> String-indent n = unlinesNoTrail . map (spc ++) . lines-  where-    spc = replicate n ' '--newline :: String-newline = "\n"---- | Application-(-$-) :: HaskellValue a => String -> a -> String-fun -$- inp = unwords [fun, haskellValue inp]---- | Binary operator application-opApp :: (HaskellValue a, HaskellValue b) => String -> a -> b -> String-opApp op a b = unwords [haskellValue a, op, haskellValue b]---- | Definition-(-=-) :: (HaskellValue patt, HaskellValue def) => patt -> def -> String-patt -=- def = unwords [haskellValue patt, "=", haskellValue def]---- Places the second string as a local block to the first string.-local :: String -> String -> String-local def ""   = def-local def defs = def ++ newline ++ indent 2 "where" ++ newline ++ indent 4 defs--infixl 8 -$--infix  7 -=--infixr 6 `local`--ifThenElse-    :: (HaskellValue c, HaskellValue t, HaskellValue e) => c -> t -> e -> String-ifThenElse c t e = unwords-    ["if", haskellValue c, "then", haskellValue t, "else", haskellValue e]-
Feldspar/Matrix.hs view
@@ -1,30 +1,4 @@------ Copyright (c) 2009-2010, ERICSSON AB All rights reserved.--- --- Redistribution and use in source and binary forms, with or without--- modification, are permitted provided that the following conditions are met:--- ---     * Redistributions of source code must retain the above copyright notice,---       this list of conditions and the following disclaimer.---     * 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 name of the ERICSSON AB nor the names of its contributors---       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 AND CONTRIBUTORS "AS IS"--- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE--- IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE--- ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS--- BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,--- OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF--- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS--- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN--- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)--- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF--- THE POSSIBILITY OF SUCH DAMAGE.---+{-# LANGUAGE UndecidableInstances #-}  -- | Operations on matrices (doubly-nested parallel vectors). All operations in -- this module assume rectangular matrices.@@ -34,9 +8,10 @@   import qualified Prelude as P+import Data.List (genericLength)+import qualified Data.TypeLevel as TL  import Feldspar.Prelude-import Feldspar.Utils import Feldspar.Core import Feldspar.Vector @@ -47,26 +22,22 @@   -- | Converts a matrix to a core array.-freezeMatrix :: Storable a => Matrix a -> Data [[a]]+freezeMatrix :: Type a => Matrix a -> Data [[a]] freezeMatrix = freezeVector . map freezeVector +-- | Converts a core array to a matrix.+unfreezeMatrix :: Type a => Data [[a]] -> Matrix a+unfreezeMatrix = map unfreezeVector . unfreezeVector+ -- | Converts a core array to a matrix. The first length argument is the number -- of rows (outer vector), and the second argument is the number of columns -- (inner argument).-unfreezeMatrix :: Storable a => Data Length -> Data Length -> Data [[a]] -> Matrix a-unfreezeMatrix y x = map (unfreezeVector x) . (unfreezeVector y)+unfreezeMatrix' :: Type a => Length -> Length -> Data [[a]] -> Matrix a+unfreezeMatrix' y x = map (unfreezeVector' x) . (unfreezeVector' y)  -- | Constructs a matrix. The elements are stored in a core array.-matrix :: Storable a => [[a]] -> Matrix a-matrix as-    | allEqual xs = unfreezeMatrix y x (value as)-    | otherwise   = error "matrix: Not rectangular"-  where-    xs = P.map P.length as-    y  = value $ P.length as-    x  = value $ P.head (xs P.++ [0])--+matrix :: Type a => [[a]] -> Matrix a+matrix = unfreezeMatrix . value  -- | Constructing a matrix from an index function. --@@ -78,25 +49,21 @@ -- --   * @ifx@ is a function mapping indexes to elements (first argument is row --     index; second argument is column index).-indexedMat ::-    Data Int -> Data Int -> (Data Int -> Data Int -> Data a) -> Matrix a-+indexedMat+    :: Data Length+    -> Data Length+    -> (Data Index -> Data Index -> Data a)+    -> Matrix a indexedMat m n idx = indexed m $ \k -> indexed n $ \l -> idx k l -- -- | Transpose of a matrix-transpose :: Matrix a -> Matrix a+transpose :: Type a => Matrix a -> Matrix a transpose a = indexedMat (length $ head a) (length a) $ \y x -> a ! x ! y-  -- XXX This assumes that (head a) can be used even if a is empty. Might this-  --     violate size constraints on the index?-  --     See the conditional in 'flatten'.--+  -- TODO This assumes that (head a) can be used even if a is empty.  -- | Concatenates the rows of a matrix.-flatten :: Matrix a -> Vector (Data a)-flatten matr = Indexed (m*n) ixf+flatten :: Type a => Matrix a -> Vector (Data a)+flatten matr = Indexed (m*n) ixf Empty   where     m = length matr     n = (m==0) ? (0, length (head matr))@@ -105,18 +72,14 @@       where         y = i `div` n         x = i `mod` n-  -- XXX Should use "linear indexing"--+  -- TODO Should use linear indexing  -- | The diagonal vector of a square matrix. It happens to work if the number of -- rows is less than the number of columns, but not the other way around (this -- would require some overhead).-diagonal :: Matrix a -> Vector (Data a)+diagonal :: Type a => Matrix a -> Vector (Data a) diagonal m = zipWith (!) m (0 ... (length m - 1)) -- distributeL :: (a -> b -> c) -> a -> Vector b -> Vector c distributeL f = map . f @@ -130,88 +93,77 @@     type Prod a b      -- | General multiplication operator-    (**) :: a -> b -> Prod a b-      -- XXX This symbol should probably be used for exponentiation instead.+    (***) :: a -> b -> Prod a b  instance Numeric a => Mul (Data a) (Data a)   where     type Prod (Data a) (Data a) = Data a-    (**) = (*)+    (***) = (*)  instance Numeric a => Mul (Data a) (DVector a)   where     type Prod (Data a) (DVector a) = DVector a-    (**) = distributeL (**)+    (***) = distributeL (***)  instance Numeric a => Mul (DVector a) (Data a)   where     type Prod (DVector a) (Data a) = DVector a-    (**) = distributeR (**)+    (***) = distributeR (***)  instance Numeric a => Mul (Data a) (Matrix a)   where     type Prod (Data a) (Matrix a) = Matrix a-    (**) = distributeL (**)+    (***) = distributeL (***)  instance Numeric a => Mul (Matrix a) (Data a)   where     type Prod (Matrix a) (Data a) = Matrix a-    (**) = distributeR (**)+    (***) = distributeR (***)  instance Numeric a => Mul (DVector a) (DVector a)   where     type Prod (DVector a) (DVector a) = Data a-    (**) = scalarProd+    (***) = scalarProd  instance Numeric a => Mul (DVector a) (Matrix a)   where     type Prod (DVector a) (Matrix a) = (DVector a)-    vec ** mat = distributeL (**) vec (transpose mat)+    vec *** mat = distributeL (***) vec (transpose mat)  instance Numeric a => Mul (Matrix a) (DVector a)   where     type Prod (Matrix a) (DVector a) = (DVector a)-    (**) = distributeR (**)+    (***) = distributeR (***)  instance Numeric a => Mul (Matrix a) (Matrix a)   where     type Prod (Matrix a) (Matrix a) = (Matrix a)-    (**) = distributeR (**)+    (***) = distributeR (***)    -- | Matrix multiplication mulMat :: Numeric a => Matrix a -> Matrix a -> Matrix a-mulMat = (**)--{-# DEPRECATED mul "Please use `mulMat` or `(**)` instead." #-}--- | Matrix multiplication-mul :: Numeric a => Matrix a -> Matrix a -> Matrix a-mul = (**)+mulMat = (***)   -class ElemWise a+class Syntactic a => ElemWise a   where     type Elem a      -- | Operator for general element-wise multiplication     elemWise :: (Elem a -> Elem a -> Elem a) -> a -> a -> a -instance ElemWise (Data a)+instance Type a => ElemWise (Data a)   where     type Elem (Data a) = Data a     elemWise = id -instance ElemWise (DVector a)-  where-    type Elem (DVector a) = Data a-    elemWise = zipWith--instance ElemWise (Matrix a)+instance (ElemWise a, Syntactic (Vector a)) => ElemWise (Vector a)   where-    type Elem (Matrix a) = Data a-    elemWise = elemWise . elemWise+    type Elem (Vector a) = Elem a+    elemWise = zipWith . elemWise  (.+) :: (ElemWise a, Num (Elem a)) => a -> a -> a (.+) = elemWise (+)@@ -222,3 +174,12 @@ (.*) :: (ElemWise a, Num (Elem a)) => a -> a -> a (.*) = elemWise (*) +-- * Wrapping for matrices++instance (Type a) => Wrap (Matrix a) (Data [[a]]) where+    wrap = freezeMatrix++instance (Wrap t u, Type a, TL.Nat row, TL.Nat col) => Wrap (Matrix a -> t) (Data' (row,col) [[a]] -> u) where+    wrap f = \(Data' d) -> wrap $ f $ unfreezeMatrix' row' col' d where+        row' = fromInteger $ toInteger $ TL.toInt (undefined :: row)+        col' = fromInteger $ toInteger $ TL.toInt (undefined :: col)
Feldspar/Prelude.hs view
@@ -1,33 +1,5 @@------ Copyright (c) 2009-2010, ERICSSON AB All rights reserved.--- --- Redistribution and use in source and binary forms, with or without--- modification, are permitted provided that the following conditions are met:--- ---     * Redistributions of source code must retain the above copyright notice,---       this list of conditions and the following disclaimer.---     * 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 name of the ERICSSON AB nor the names of its contributors---       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 AND CONTRIBUTORS "AS IS"--- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE--- IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE--- ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS--- BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,--- OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF--- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS--- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN--- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)--- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF--- THE POSSIBILITY OF SUCH DAMAGE.------- | Reexports the "Prelude", but hides all identifiers that are redefined in--- the "Feldspar" library.+-- | Reexports the "Prelude" hiding all identifiers that are redefined in the+-- "Feldspar" library.  module Feldspar.Prelude   ( module Prelude@@ -42,7 +14,7 @@   , (<), (>), (<=), (>=)   , not, (&&), (||)   , min, max-  , (^), (**)+  , (^)   , Integral   , quot, rem   , div, mod@@ -61,5 +33,7 @@   , map   , zipWith   , sum+  , Real+  , truncate, round, ceiling, floor   ) 
Feldspar/Range.hs view
@@ -1,803 +1,1008 @@------ Copyright (c) 2009-2010, ERICSSON AB All rights reserved.--- --- Redistribution and use in source and binary forms, with or without--- modification, are permitted provided that the following conditions are met:--- ---     * Redistributions of source code must retain the above copyright notice,---       this list of conditions and the following disclaimer.---     * 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 name of the ERICSSON AB nor the names of its contributors---       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 AND CONTRIBUTORS "AS IS"--- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE--- IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE--- ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS--- BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,--- OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF--- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS--- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN--- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)--- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF--- THE POSSIBILITY OF SUCH DAMAGE.-----{-# LANGUAGE NoMonomorphismRestriction #-}---- | Ranged values--module Feldspar.Range where----import Control.Monad-import Data.Maybe-import Data.Monoid-import Data.Bits-import Data.Word-import Test.QuickCheck hiding ((.&.))-import qualified Test.QuickCheck as QC-import System.Random -- Should maybe be exported from QuickCheck-import Text.Printf---data Ord a => Range a = Range-  { lowerBound :: Maybe a-  , upperBound :: Maybe a-  }-    deriving (Eq, Show)----instance (Ord a, Num a) => Num (Range a)-  where-    fromInteger = singletonRange . fromInteger--    negate = rangeOp neg-      where-        neg (Range l u) = Range (liftM negate u) (liftM negate l)--    (+) = rangeOp2 add-      where-        add (Range l1 u1) (Range l2 u2) =-          Range (liftM2 (+) l1 l2) (liftM2 (+) u1 u2)--    (*) = rangeMul--    abs = rangeOp abs'-      where-        abs' r@(Range l u)-            | isNatural  r = r-            | isNegative r = Range (liftM abs u) (liftM abs l)-            | otherwise    = -                Range (Just 0) (liftM2 max (liftM abs l) (liftM abs u))--    signum = rangeOp sign-      where-        sign r-          | range (-1) 1     `isSubRangeOf` r = range (-1) 1-          | range (-1) 0     `isSubRangeOf` r = range (-1) 0-          | range 0 1        `isSubRangeOf` r = range 0 1-          | singletonRange 0 `isSubRangeOf` r = singletonRange 0-          | isNatural r                       = singletonRange 1-          | isNegative r                      = singletonRange (-1)--instance (Ord a, Num a) => Monoid (Range a)-  where-    mempty  = emptyRange-    mappend = (\/)----rangeOp :: Ord a => (Range a -> Range a) -> (Range a -> Range a)-rangeOp f r = if isEmpty r then r else f r--rangeOp2 :: Ord a =>-    (Range a -> Range a -> Range a) -> (Range a -> Range a -> Range a)-rangeOp2 f r1 r2-  | isEmpty r1 = r1-  | isEmpty r2 = r2-  | otherwise  = f r1 r2--mapMonotonic :: (Ord a, Ord b) => (a -> b) -> Range a -> Range b-mapMonotonic f (Range l u) = Range (liftM f l) (liftM f u)--rangeMul :: (Ord a, Num a) => Range a -> Range a -> Range a-rangeMul r1 r2 = p1 \/ p2 \/ p3 \/ p4-  where-    split r = (r /\ negativeRange, r /\ naturalRange)--    (r1neg,r1pos) = split r1-    (r2neg,r2pos) = split r2--    p1 = mul (negate r1neg) (negate r2neg)-    p2 = negate $ mul (negate r1neg) r2pos-    p3 = negate $ mul r1pos (negate r2neg)-    p4 = mul r1pos r2pos--    mul = rangeOp2 mul'-      where-        mul' (Range l1 u1) (Range l2 u2) =-          Range (liftM2 (*) l1 l2) (liftM2 (*) u1 u2)----emptyRange :: (Ord a, Num a) => Range a-emptyRange = Range (Just 0) (Just (-1))--fullRange :: Ord a => Range a-fullRange = Range Nothing Nothing--range :: Ord a => a -> a -> Range a-range l u = Range (Just l) (Just u)--rangeByRange :: Ord a => Range a -> Range a -> Range a-rangeByRange r1 r2 = Range (lowerBound r1) (upperBound r2)--singletonRange :: Ord a => a -> Range a-singletonRange a = Range (Just a) (Just a)--naturalRange :: (Ord a, Num a) => Range a-naturalRange = Range (Just 0) Nothing--negativeRange :: (Ord a, Num a) => Range a-negativeRange = Range Nothing (Just (-1))--rangeSize :: (Ord a, Num a) => Range a -> Maybe a-rangeSize (Range l u) = do-    l' <- l-    u' <- u-    return (u'-l'+1)--isEmpty :: Ord a => Range a -> Bool-isEmpty (Range Nothing _)         = False-isEmpty (Range _ Nothing)         = False-isEmpty (Range (Just l) (Just u)) = u < l--isFull :: Ord a => Range a -> Bool-isFull (Range Nothing Nothing) = True-isFull _                       = False--isBounded :: Ord a => Range a -> Bool-isBounded (Range Nothing _) = False-isBounded (Range _ Nothing) = False-isBounded (Range _ _)       = True--isSingleton :: Ord a => Range a -> Bool-isSingleton (Range (Just l) (Just u)) = l==u-isSingleton _                         = False--isSubRangeOf :: Ord a => Range a -> Range a -> Bool-isSubRangeOf r1@(Range l1 u1) r2@(Range l2 u2)-    | isEmpty r1 = True-    | isEmpty r2 = False-    | otherwise-         = (isNothing l2 || (isJust l1 && l1>=l2))-        && (isNothing u2 || (isJust u1 && u1<=u2))---- | Checks whether a range is a sub-range of the natural numbers.-isNatural :: (Ord a, Num a) => Range a -> Bool-isNatural = (`isSubRangeOf` naturalRange)---- | Checks whether a range is a sub-range of the negative numbers.-isNegative :: (Ord a, Num a) => Range a -> Bool-isNegative = (`isSubRangeOf` negativeRange)--inRange :: Ord a => a -> Range a -> Bool-inRange a r = singletonRange a `isSubRangeOf` r--rangeGap :: (Ord a, Num a) => Range a -> Range a -> Range a-rangeGap = rangeOp2 gap-  where-    gap (Range _ (Just u1)) (Range (Just l2) _)-      | u1 < l2 = Range (Just u1) (Just l2)-    gap (Range (Just l1) _) (Range _ (Just u2))-      | u2 < l1 = Range (Just u2) (Just l1)-    gap _ _ = emptyRange-  -- If the result is non-empty, it will include the boundary elements from the-  -- two ranges.----(\/) :: Ord a => Range a -> Range a -> Range a-r1 \/ r2-    | isEmpty r1 = r2-    | isEmpty r2 = r1-    | otherwise  = or r1 r2-  where-    or (Range l1 u1) (Range l2 u2) =-      Range (liftM2 min l1 l2) (liftM2 max u1 u2)--liftMaybe2 :: (a -> a -> a) -> Maybe a -> Maybe a -> Maybe a-liftMaybe2 f Nothing b         = b-liftMaybe2 f a Nothing         = a-liftMaybe2 f (Just a) (Just b) = Just (f a b)--(/\) :: Ord a => Range a -> Range a -> Range a-(/\) = rangeOp2 and-  where-    and (Range l1 u1) (Range l2 u2) =-        Range (liftMaybe2 max l1 l2) (liftMaybe2 min u1 u2)--disjoint :: (Ord a, Num a) => Range a -> Range a -> Bool-disjoint r1 r2 = isEmpty (r1 /\ r2)---- | @r1 \`rangeLess\` r2:@------ Checks if all elements of @r1@ are less than all elements of @r2@.-rangeLess :: Ord a => Range a -> Range a -> Bool-rangeLess r1 r2-  | isEmpty r1 || isEmpty r2 = True-rangeLess (Range _ (Just u1)) (Range (Just l2) _) = u1 < l2-rangeLess _ _                                     = False---- | @r1 \`rangeLessEq\` r2:@------ Checks if all elements of @r1@ are less than or equal to all elements of--- @r2@.-rangeLessEq :: Ord a => Range a -> Range a -> Bool-rangeLessEq (Range _ (Just u1)) (Range (Just l2) _) = u1 <= l2-rangeLessEq _ _                                     = False---- | @rangeAddUnsigned@ correctly and accurately propagates range--- information through an unsigned addition. Code is borrowed from--- Hacker's Delight.-rangeAddUnsigned :: (Ord a, Num a, Bounded a) => Range a -> Range a -> Range a-rangeAddUnsigned = -    rangeProp2 $ \a b c d -> -        if a + c >= a && b + d < b -        then fullRange-        else range (a + c) (b + d)-       --- | @rangeAddSigned@ correctly and accurately propagates range--- information through a signed addition. Code is borrowed from--- Hacker's Delight.-rangeAddSigned :: (Ord a, Num a, Bounded a, Bits a) => -                  Range a -> Range a -> Range a-rangeAddSigned = -    rangeProp2 $ \a b c d -> -        let s = a + c-            t = b + d-            u = a .&. c .&. complement s .&. -                complement (b .&. d .&. complement t)-            v = ((xor a c) .|. complement (xor a s)) .&. -                (complement b .&. complement d .&. t)-        in if (u .|. v) < 0 -           then fullRange-           else range s t---- | @rangeSubUnsigned@ propagates range information through unsigned---   subtraction. Code is borrowed from Hacker's Delight-rangeSubUnsigned :: (Ord a, Num a, Bounded a) => Range a -> Range a -> Range a-rangeSubUnsigned = -    rangeProp2 $ \a b c d -> -        let s = a - d-            t = b - c-        in if s > a && t <= b-           then fullRange-           else range s t---- | Propagates range information through unsigned negation. Code from---   Hacker's Delight-rangeNegUnsigned :: (Ord a, Num a, Bounded a) => Range a -> Range a-rangeNegUnsigned = -    rangeProp1 $ \a b -> -        if a == 0 && b /= 0-        then fullRange-        else range (-b) (-a)---- | Propagates range information through signed negation. Code from---   Hacker's Delight.-rangeNegSigned :: (Ord a, Num a, Bounded a) => Range a -> Range a-rangeNegSigned = -    rangeProp1 $ \a b -> -        if a == minBound && b == minBound -        then singletonRange minBound-        else if a == minBound-             then fullRange-             else range (-b) (-a)---- | Cheap and inaccurate range propagation for '.|.' on unsigned numbers.--- Code from Hacker's Delight-rangeOrUnsignedCheap :: (Ord a, Num a, Bounded a) => -                        Range a -> Range a -> Range a-rangeOrUnsignedCheap = -    rangeProp2 $ \a b c d -> range (max a c) (maxPlus b d)--maxPlus b d = if sum < b then maxBound-              else sum-  where sum = b + d---- | Accurate lower bound for '.|.' on unsigned numbers.-minOrUnsigned :: (Ord a, Num a, Bits a) => a -> a -> a -> a -> a-minOrUnsigned a b c d = loop (bit (bitSize a - 1))-  where loop 0 = a .|. c-        loop m -            | complement a .&. c .&. m > 0 = -                let temp = (a .|. m) .&. negate m-                in if temp <= b -                   then temp .|. c-                   else loop (shiftR m 1)-            | a .&. complement c .&. m > 0=-                let temp = (c .|. m) .&. negate m-                in if temp <= d-                   then a .|. temp-                   else loop (shiftR m 1)-            | otherwise = loop (shiftR m 1)---- | Accurate upper bound for '.|.' on unsigned numbers.-maxOrUnsigned :: (Ord a, Num a, Bits a) => a -> a -> a -> a -> a-maxOrUnsigned a b c d= loop (bit (bitSize a - 1))-  where loop 0 = b .|. d-        loop m-             | b .&. d .&. m > 0 =-                 let temp = (b - m) .|. (m - 1)-                 in if temp >= a-                    then temp .|. d-                    else let temp = (d - m) .|. (m - 1)-                         in if temp >= c-                            then b .|. temp-                            else loop (shiftR m 1)-             | otherwise = loop (shiftR m 1)--rangeOrUnsignedAccurate :: (Ord a, Num a, Bits a, Bounded a) =>-                            Range a -> Range a -> Range a-rangeOrUnsignedAccurate = -    rangeProp2 $ \a b c d -> -        range (minOrUnsigned a b c d) (maxOrUnsigned a b c d)---- | Cheap and inaccurate range propagation for '.&.' on unsigned numbers.--- Code from Hacker's Delight-rangeAndUnsignedCheap :: (Ord a, Num a, Bounded a) => -                         Range a -> Range a -> Range a-rangeAndUnsignedCheap = rangeProp2 $ \a b c d -> range 0 (min b d)---- | Range propagation for 'xor' on unsigned numbers.--- Code from Hacker's Delight-rangeXorUnsigned :: (Ord a, Num a, Bounded a) => Range a -> Range a -> Range a-rangeXorUnsigned = rangeProp2 (\a b c d -> range 0 (maxPlus b d))---- | Auxiliary function for writing range propagation--- functions. Especially suitable for the code borrowed from Hacker's--- Delight.-rangeProp1 :: (Ord a, Bounded a) => (a -> a -> Range a) -> Range a -> Range a-rangeProp1 f (Range l u) = f a b-  where toUpper Nothing  = maxBound-        toUpper (Just u) = u-        toLower Nothing  = minBound-        toLower (Just l) = l-        a = toLower l-        b = toUpper u---- | Auxiliary function for writing range propagation functions for--- two argument functions. Especially suitable for the code borrowed--- from Hacker's Delight.-rangeProp2 :: (Ord a, Bounded a) => -              (a -> a -> a -> a -> Range a) -> Range a -> Range a -> Range a-rangeProp2 f (Range l1 u1) (Range l2 u2) =-    f a b c d-  where toUpper Nothing  = maxBound-        toUpper (Just u) = u-        toLower Nothing  = minBound-        toLower (Just l) = l-        a = toLower l1-        b = toUpper u1-        c = toLower l2-        d = toUpper u2---- | Propagates range information through @max@.-rangeMax :: Ord a => Range a -> Range a -> Range a-rangeMax r1 r2-    | isEmpty r1 = r2-    | isEmpty r2 = r1-rangeMax r1 r2-    | r1 `rangeLess` r2 = r2-    | r2 `rangeLess` r1 = r1-rangeMax (Range (Just l1) u1) (Range (Just l2) u2) -    | l1 < l2   = Range (Just l2) (liftM2 max u1 u2)-    | otherwise = Range (Just l1) (liftM2 max u1 u2)-rangeMax (Range Nothing u1) (Range (Just l2) u2)-    = Range (Just l2) (liftM2 max u1 u2)-rangeMax (Range (Just l1) u1) (Range Nothing u2)-    = Range (Just l1) (liftM2 max u1 u2)-rangeMax (Range Nothing u1) (Range Nothing u2)-    = Range Nothing (liftM2 max u1 u2)---- | Analogous to 'rangeMax'-rangeMin :: Ord a => Range a -> Range a -> Range a-rangeMin r1 r2-    | isEmpty r1 = r2-    | isEmpty r2 = r1-rangeMin r1 r2-    | r1 `rangeLess` r2 = r1-    | r2 `rangeLess` r1 = r2-rangeMin (Range l1 (Just u1)) (Range l2 (Just u2))-    | u1 < u2   = Range (liftM2 min l1 l2) (Just u1)-    | otherwise = Range (liftM2 min l1 l2) (Just u2)-rangeMin (Range l1 Nothing) (Range l2 (Just u2))-    = Range (liftM2 min l1 l2) (Just u2)-rangeMin (Range l1 (Just u1)) (Range l2 Nothing)-    = Range (liftM2 min l1 l2) (Just u1)-rangeMin (Range l1 Nothing) (Range l2 Nothing)-    = Range (liftM2 min l1 l2) Nothing---- | Propagates range information through 'mod'.--- Note that we assume Haskell semantics for 'mod'.-rangeMod :: (Num a, Ord a, Enum a) => Range a -> Range a -> Range a-rangeMod d r-    | d `rangeLess` r && isNatural r && isNatural d = d-    | isNatural r  = Range (Just 0) (fmap pred (upperBound r))-    | r `rangeLess` d && isNegative r && isNegative d = d-    | isNegative r = Range (fmap succ (lowerBound r)) (Just 0)-    where -      isNegative = (`isSubRangeOf` negativeRange)-      negativeRange = Range Nothing (Just 0)-rangeMod d (Range l u)-    = Range (fmap succ l) (fmap pred u)---- | Propagates range information through 'rem'.--- Note that we assume Haskell semantics for 'rem'.-rangeRem :: (Num a, Ord a, Enum a) => Range a -> Range a -> Range a-rangeRem d r-    | d `rangeLess` abs r && isNatural d = d-    | isNatural d  = Range (Just 0) (fmap pred (upperBound (abs r)))-    | abs d `rangeLess` abs r && isNegative d = d-    | isNegative d = Range (fmap negate (upperBound (abs r))) (Just 0)-    where-      isNegative = (`isSubRangeOf` negativeRange)-      negativeRange = Range Nothing (Just 0)-rangeRem d r@(Range l u)-    | l `betterThan` u = -        Range (fmap (succ . negate .abs) l) (fmap (pred . abs) l)-    | otherwise        = -        Range (fmap (succ . negate . abs) u) (fmap (pred . abs) upper)-  where lower = lowerBound r-        upper = upperBound r-        betterThan (Just a) (Just b) = abs a >= abs b-        betterThan Nothing  (Just b) = True-        betterThan (Just a) Nothing  = False-        betterThan Nothing  Nothing  = True--showBound :: Show a => Maybe a -> String-showBound (Just a) = show a-showBound _        = "*"--showRange :: (Show a, Ord a) => Range a -> String-showRange r@(Range l u)-  | isEmpty r     = "[]"-  | isSingleton r = let Just a = upperBound r in show [a]-  | otherwise     = "[" ++ showBound l ++ "," ++ showBound u ++ "]"----instance (Arbitrary a, Ord a, Num a) => Arbitrary (Range a)-  where-    arbitrary = do-        lower <- arbitrary-        size  <- liftM abs arbitrary-        upper <- frequency [(6, return (lower+size)), (1, return (lower-size))]-        liftM2 Range (arbMaybe lower) (arbMaybe upper)-      where-        arbMaybe a = frequency [(5, return (Just a)), (1, return Nothing)]--instance Random Word32 where-  random g = (fromIntegral i,g')-   where (i :: Int,g') = random g-  randomR (l,u) g = (fromIntegral i,g')-    where (i :: Integer, g') = randomR (fromIntegral l,fromIntegral u) g--prop_arith1 :: (forall a . Num a => a -> a) -> Range Int -> Property-prop_arith1 op r = -    not (isEmpty r) ==>-    forAll (fromRange r) $ \x ->-    op x `inRange` op r---prop_arith2-    :: (forall a . Num a => a -> a -> a)-    -> Range Int -> Range Int -> Property-prop_arith2 op r1 r2 = rangePropagationSafety op op r1 r2---prop_fromInteger = isSingleton . fromInteger--prop_neg  = prop_arith1 negate-prop_add  = prop_arith2 (+)-prop_sub  = prop_arith2 (-)-prop_mul  = prop_arith2 (*)-prop_abs  = prop_arith1 abs-prop_sign = prop_arith1 signum--prop_addU = rangePropagationSafety ((+) :: Word32 -> Word32 -> Word32) -                                   rangeAddUnsigned-prop_addS = rangePropagationSafety ((+) :: Int -> Int -> Int)-                                   rangeAddSigned-prop_subU = rangePropagationSafety ((-) :: Word32 -> Word32 -> Word32)-                                   rangeSubUnsigned-prop_negU = rangePropSafety1 (negate :: Word32 -> Word32) rangeNegUnsigned-prop_negS = rangePropSafety1 (negate :: Int -> Int) rangeNegSigned-prop_andUCheap = rangePropagationSafety ((.&.) :: Word32 -> Word32 -> Word32) -                                        rangeAndUnsignedCheap-prop_orUCheap = rangePropagationSafety ((.|.) :: Word32 -> Word32 -> Word32)-                                       rangeOrUnsignedCheap-prop_xorU = rangePropagationSafety (xor :: Word32 -> Word32 -> Word32)-                                   rangeXorUnsigned--prop_abs2 (r::Range Int) = isNatural (abs r)--prop_empty = isEmpty (emptyRange :: Range Int)--prop_full = isFull (fullRange :: Range Int)--prop_isEmpty1 (r::Range Int) = isEmpty r ==> isBounded r-prop_isEmpty2 (r::Range Int) = isEmpty r ==> (upperBound r < lowerBound r)--prop_isFull (r::Range Int) = isFull r ==> not (isBounded r)--prop_fullRange = not $ isBounded (fullRange :: Range Int)--prop_range (a::Int) (b::Int) = isBounded $ range a b--prop_rangeByRange (r1::Range Int) (r2::Range Int) =-    (rangeLess r1 r2 && not (isEmpty (r1/\r2))) ==> isEmpty (rangeByRange r1 r2)--prop_singletonRange1 (a::Int) = isSingleton (singletonRange a)-prop_singletonRange2 (a::Int) = isBounded   (singletonRange a)--prop_singletonSize (r::Range Int) = isSingleton r ==> (rangeSize r == Just 1)--prop_subRange (r1::Range Int) (r2::Range Int) =-    ((r1 < r2) && (r2 < r1) && not (isEmpty r1)) ==> r1==r2-  where-    (<) = isSubRangeOf--prop_emptySubRange1 (r1::Range Int) (r2::Range Int) =-    isEmpty r1 ==> (not (isEmpty r2) ==> not (r2 `isSubRangeOf` r1))--prop_emptySubRange2 (r1::Range Int) (r2::Range Int) =-    isEmpty r1 ==> (not (isEmpty r2) ==> (r1 `isSubRangeOf` r2))--prop_isNegative (r::Range Int) =-    not (isEmpty r) ==> (isNegative r ==> not (isNegative $ negate r))--prop_rangeGap (r1::Range Int) (r2::Range Int) =-    (isEmpty gap1 && isEmpty gap2) || (gap1 == gap2)-  where-    gap1 = rangeGap r1 r2-    gap2 = rangeGap r2 r1--prop_union1 x (r1::Range Int) (r2::Range Int) =-    ((x `inRange` r1) || (x `inRange` r2)) ==> (x `inRange` (r1\/r2))--prop_union2 x (r1::Range Int) (r2::Range Int) =-    (x `inRange` (r1\/r2)) ==>-        ((x `inRange` r1) || (x `inRange` r2) || (x `inRange` rangeGap r1 r2))--prop_union3 (r1::Range Int) (r2::Range Int) = r1 `isSubRangeOf` (r1\/r2)-prop_union4 (r1::Range Int) (r2::Range Int) = r2 `isSubRangeOf` (r1\/r2)--prop_intersect1 x (r1::Range Int) (r2::Range Int) =-    ((x `inRange` r1) && (x `inRange` r2)) ==> (x `inRange` (r1/\r2))--prop_intersect2 x (r1::Range Int) (r2::Range Int) =-    (x `inRange` (r1/\r2)) ==> ((x `inRange` r1) && (x `inRange` r2))--prop_intersect3 (r1::Range Int) (r2::Range Int) = (r1/\r2) `isSubRangeOf` r1-prop_intersect4 (r1::Range Int) (r2::Range Int) = (r1/\r2) `isSubRangeOf` r2-prop_intersect5 (r1::Range Int) (r2::Range Int) =-    isEmpty r1 || isEmpty r2 ==> isEmpty (r1/\r2)--prop_disjoint x (r1::Range Int) (r2::Range Int) =-    disjoint r1 r2 ==> (x `inRange` r1) ==> not (x `inRange` r2)--prop_rangeLess1 (r1::Range Int) (r2::Range Int) =-    rangeLess r1 r2 ==> disjoint r1 r2--prop_rangeLess2 (r1::Range Int) (r2::Range Int) =-    not (isEmpty r1) && not (isEmpty r2) ==>-    forAll (fromRange r1) $ \x ->-    forAll (fromRange r2) $ \y ->-    rangeLess r1 r2 ==> x < y--prop_rangeLessEq (r1::Range Int) (r2::Range Int) =-    not (isEmpty r1) && not (isEmpty r2) ==>-    forAll (fromRange r1) $ \x ->-    forAll (fromRange r2) $ \y ->-    rangeLessEq r1 r2 ==> x <= y--prop_rangeMax1 (r1::Range Int) = rangeMax r1 r1 == r1--prop_rangeMax2 (r1::Range Int) r2 =-    not (isEmpty r1) && not (isEmpty r2) ==>-    upperBound r1 <= upperBound max && upperBound r2 <= upperBound max-    where -      max = rangeMax r1 r2-      Nothing <= Nothing = True-      Just _  <= Nothing = True-      Just a  <= Just b  = a Prelude.<= b-      _       <= _       = False--prop_rangeMax3 (r1::Range Int) r2 =-    not (isEmpty r1) && not (isEmpty r2) ==> -  lowerBound (rangeMax r1 r2) == liftMaybe2 max (lowerBound r1) (lowerBound r2)--prop_rangeMax4 (r1::Range Int) r2 = -    not (isEmpty r1) && not (isEmpty r2) ==>-    rangeMax r1 r2 == rangeMax r2 r1--prop_rangeMax5 (r1::Range Int) r2 = -    (isEmpty r1 && not (isEmpty r2) ==>-    rangeMax r1 r2 == r2)-    QC..&.-    (isEmpty r2 && not (isEmpty r1) ==>-    rangeMax r1 r2 == r1)--prop_rangeMax6 (v1::Int) v2 = -    max v1 v2 `inRange` rangeMax (singletonRange v1) (singletonRange v2)--prop_rangeMax7 (r1::Range Int) r2 = -    rangePropagationSafety max rangeMax r1 r2--prop_rangeMin1 (r1::Range Int) = rangeMin r1 r1 == r1--prop_rangeMin2 (r1::Range Int) r2 =-    not (isEmpty r1) && not (isEmpty r2) ==>-    lowerBound min <= lowerBound r1 && lowerBound min <= lowerBound r2-    where -      min = rangeMin r1 r2-      Nothing <= Nothing = True-      Nothing <= Just _  = True-      Just a  <= Just b  = a Prelude.<= b-      _       <= _       = False--prop_rangeMin3 (r1::Range Int) r2 =-    not (isEmpty r1) && not (isEmpty r2) ==> -  upperBound (rangeMin r1 r2) == liftMaybe2 min (upperBound r1) (upperBound r2)--prop_rangeMin4 (r1::Range Int) r2 = -    not (isEmpty r1) && not (isEmpty r2) ==>-    rangeMin r1 r2 == rangeMin r2 r1--prop_rangeMin5 (r1::Range Int) r2 = -    (isEmpty r1 && not (isEmpty r2) ==>-    rangeMin r1 r2 == r2)-    QC..&.-    (isEmpty r2 && not (isEmpty r1) ==>-    rangeMin r1 r2 == r1)--prop_rangeMin6 (v1::Int) v2 = -    min v1 v2 `inRange` rangeMin (singletonRange v1) (singletonRange v2)--prop_rangeMin7 (r1::Range Int) r2 = -    rangePropagationSafety min rangeMin r1 r2--prop_rangeMod1 (v1::Int) v2 =-    v2 /= 0 ==>-    mod v1 v2 `inRange` rangeMod (singletonRange v1) (singletonRange v2)--prop_rangeMod2 = -    rangePropagationSafetyPre mod rangeMod (\v1 (v2::Int) -> v2 /= 0)--prop_rangeRem  = -    rangePropagationSafetyPre rem rangeRem (\v1 (v2::Int) -> v2 /= 0)---- This function is useful for range propagation functions like--- rangeMax, rangeMod etc. --- It takes two ranges, picks an element out of either ranges and--- checks if applying the operation to the individual elements is in--- the resulting range after range propagation --- The third argument is a precondition that is satisfied before the test is run-rangePropagationSafetyPre :: (Random a, Ord a, Show a, Bounded a,-                              Random b, Ord b, Show b, Bounded b,-                              Ord c) =>-    (a -> b -> c) -> (Range a -> Range b -> Range c) -> -    (a -> b -> Bool) ->-    Range a -> Range b -> Property-rangePropagationSafetyPre op rop pre r1 r2 =-    not (isEmpty r1) && not (isEmpty r2) ==>-    forAll (fromRange r1) $ \v1 ->-    forAll (fromRange r2) $ \v2 ->-        pre v1 v2 ==>-        op v1 v2 `inRange` rop r1 r2--rangePropagationSafety op rop r1 r2 = -    rangePropagationSafetyPre op rop noPre r1 r2--noPre _ _ = True--rangePropSafety1 :: (Ord a, Show a, Random a, Bounded a, Ord b) => -                    (a -> b) -> (Range a -> Range b) -> Range a -> Property-rangePropSafety1 op rop ran = -    not (isEmpty ran) ==>-    forAll (fromRange ran) $ \val ->-        op val `inRange` rop ran--lowBound,uppBound :: (Bounded a, Ord a) => Range a -> a-lowBound r | Just l <- lowerBound r = l-lowBound r = minBound-uppBound r | Just u <- upperBound r = u-uppBound r = maxBound--fromRange :: (Random a, Bounded a, Ord a) => Range a -> Gen a-fromRange r = choose (lowBound r,uppBound r)--testAll = do-    -- This one is wrong but QuickCheck doesn't spot it-    myCheck "prop_neg"             prop_neg--    myCheck "prop_negU"            prop_negU-    myCheck "prop_negS"            prop_negS--    -- These three suffer from overflow behaviour-    myCheck "prop_add"             prop_add-    myCheck "prop_sub"             prop_sub-    myCheck "prop_mul"             prop_mul--    myCheck "prop_addU"            prop_addU-    myCheck "prop_addS"            prop_addS-    myCheck "prop_subU"            prop_subU-    myCheck "prop_andUCheap"       prop_andUCheap-    myCheck "prop_orUCheap"        prop_orUCheap-    myCheck "prop_xorU"            prop_xorU--    myCheck "prop_abs"             prop_abs-    myCheck "prop_sign"            prop_sign-    myCheck "prop_abs2"            prop_abs2-    myCheck "prop_fromInteger"     prop_fromInteger-    myCheck "prop_empty"           prop_empty-    myCheck "prop_full"            prop_full-    myCheck "prop_isEmpty1"        prop_isEmpty1-    myCheck "prop_isEmpty2"        prop_isEmpty2-    myCheck "prop_isFull"          prop_isFull-    myCheck "prop_fullRange"       prop_fullRange-    myCheck "prop_range"           prop_range-    -- myCheck prop_rangeByRange-    -- XXX "Arguments exhausted after 0 test"-    --     Something must be wrong with generator...-    myCheck "prop_singletonRange1" prop_singletonRange1-    myCheck "prop_singletonRange2" prop_singletonRange2-    myCheck "prop_singletonSize"   prop_singletonSize-    myCheck "prop_subRange"        prop_subRange-    myCheck "prop_emptySubRange1"  prop_emptySubRange1-    myCheck "prop_emptySubRange2"  prop_emptySubRange2-    myCheck "prop_isNegative"      prop_isNegative-    myCheck "prop_rangeGap"        prop_rangeGap-    myCheck "prop_union1"          prop_union1-    myCheck "prop_union2"          prop_union2-    myCheck "prop_union3"          prop_union3-    myCheck "prop_union4"          prop_union4-    myCheck "prop_intersect1"      prop_intersect1-    myCheck "prop_intersect2"      prop_intersect2-    myCheck "prop_intersect3"      prop_intersect3-    myCheck "prop_intersect4"      prop_intersect4-    myCheck "prop_intersect5"      prop_intersect5-    myCheck "prop_disjoint"        prop_disjoint-    myCheck "prop_rangeLess1"      prop_rangeLess1-    myCheck "prop_rangeLess2"      prop_rangeLess2-    myCheck "prop_rangeLessEq"     prop_rangeLessEq-    myCheck "prop_rangeMax1"       prop_rangeMax1-    myCheck "prop_rangeMax2"       prop_rangeMax2-    myCheck "prop_rangeMax3"       prop_rangeMax3-    myCheck "prop_rangeMax4"       prop_rangeMax4-    myCheck "prop_rangeMax5"       prop_rangeMax5-    myCheck "prop_rangeMax6"       prop_rangeMax6-    myCheck "prop_rangeMax7"       prop_rangeMax7-    myCheck "prop_rangeMin1"       prop_rangeMin1-    myCheck "prop_rangeMin2"       prop_rangeMin2-    myCheck "prop_rangeMin3"       prop_rangeMin3-    myCheck "prop_rangeMin4"       prop_rangeMin4-    myCheck "prop_rangeMin5"       prop_rangeMin5-    myCheck "prop_rangeMin6"       prop_rangeMin6-    myCheck "prop_rangeMin7"       prop_rangeMin7-    myCheck "prop_rangeMod1"       prop_rangeMod1-    myCheck "prop_rangeMod2"       prop_rangeMod2-    myCheck "prop_rangeRem"        prop_rangeRem-  where-    myCheck name test = -        do printf "%-25s" name-           quickCheckWith stdArgs {maxDiscard = 10000} test+{-# LANGUAGE UndecidableInstances #-}++-- | Bounded integer ranges++module Feldspar.Range where++++import Data.Bits+import Data.Int+import Data.Word+import Data.Typeable+import System.Random -- Should maybe be exported from QuickCheck+import Test.QuickCheck hiding ((.&.))+import qualified Test.QuickCheck as QC+import Text.Printf++import Feldspar.Set++++--------------------------------------------------------------------------------+-- * Definition+--------------------------------------------------------------------------------++-- | A bounded range of values of type @a@+data Range a = Range+  { lowerBound :: a+  , upperBound :: a+  }+    deriving (Eq, Show)++-- | Convenience alias for bounded integers+class    (Eq a, Ord a, Show a, Num a, Bounded a, Integral a, Bits a) => BoundedInt a+instance (Eq a, Ord a, Show a, Num a, Bounded a, Integral a, Bits a) => BoundedInt a++-- | A convenience function for defining range propagation. +--   @handleSign propU propS@ chooses @propU@ for unsigned types and+--   @propS@ for signed types.+handleSign :: forall a b . BoundedInt a =>+    (Range a -> b) -> (Range a -> b) -> (Range a -> b)+handleSign u s+    | isSigned (minBound::a) = s+    | otherwise              = u++-- | Shows a bound.+showBound :: BoundedInt a => a -> String+showBound a+    | a  `elem` [maxBound,minBound] = "*"+    | otherwise                     = show a++-- | A textual representation of ranges.+showRange :: BoundedInt a => Range a -> String+showRange r@(Range l u)+  | isEmpty r     = "[]"+  | isSingleton r = show u+  | otherwise     = "[" ++ showBound l ++ "," ++ showBound u ++ "]"++-- | Requires a monotonic function+mapMonotonic :: (a -> b) -> Range a -> Range b+mapMonotonic f (Range l u) = Range (f l) (f u)++-- | Requires a monotonic function+mapMonotonic2 :: (a -> b -> c) -> Range a -> Range b -> Range c+mapMonotonic2 f (Range l1 u1) (Range l2 u2) = Range (f l1 l2) (f u1 u2)++++--------------------------------------------------------------------------------+-- * Set operations+--------------------------------------------------------------------------------++instance BoundedInt a => Set (Range a)+  where+    empty     = emptyRange+    universal = fullRange+    (\/)      = rangeUnion+    (/\)      = rangeIntersection++-- | The range containing no elements+emptyRange :: BoundedInt a => Range a+emptyRange = Range maxBound minBound++-- | The range containing all elements of a type+fullRange :: BoundedInt a => Range a+fullRange = Range minBound maxBound++-- | Construct a range+range :: a -> a -> Range a+range = Range++rangeByRange :: Range a -> Range a -> Range a+rangeByRange r1 r2 = Range (lowerBound r1) (upperBound r2)+  -- TODO Think about semantics of this function++-- | The range containing one element+singletonRange :: a -> Range a+singletonRange a = Range a a++-- | The range from @0@ to the maximum element+naturalRange :: BoundedInt a => Range a+naturalRange = Range 0 maxBound++-- | The range from the smallest negative element to @-1@.+--   Undefined for unsigned types+negativeRange :: BoundedInt a => Range a+negativeRange = Range minBound (-1)++-- | The size of a range. Beware that the size may not always be representable+--   for signed types. For instance +--   @rangeSize (range minBound maxBound) :: Int@ gives a nonsense answer.+rangeSize :: BoundedInt a => Range a -> a+rangeSize (Range l u) = u-l+1++-- | Checks if the range is empty+isEmpty :: BoundedInt a => Range a -> Bool+isEmpty (Range l u) = u < l++-- | Checks if the range contains all values of the type+isFull :: BoundedInt a => Range a -> Bool+isFull r = lowerBound r == minBound && upperBound r == maxBound++-- | Checks is the range contains exactly one element+isSingleton :: BoundedInt a => Range a -> Bool+isSingleton (Range l u) = l==u++-- | @r1 \`isSubRangeOf\` r2@ checks is all the elements in @r1@ are included+--   in @r2@+isSubRangeOf :: BoundedInt a => Range a -> Range a -> Bool+isSubRangeOf r1@(Range l1 u1) r2@(Range l2 u2)+    | isEmpty r1 = True+    | isEmpty r2 = False+    | otherwise  = (l1>=l2) && (u1<=u2)++-- | Checks whether a range is a sub-range of the natural numbers.+isNatural :: BoundedInt a => Range a -> Bool+isNatural = (`isSubRangeOf` naturalRange)++-- | Checks whether a range is a sub-range of the negative numbers.+isNegative :: BoundedInt a => Range a -> Bool+isNegative = (`isSubRangeOf` negativeRange)++-- | @a \`inRange\` r@ checks is @a@ is an element of the range @r@.+inRange :: BoundedInt a => a -> Range a -> Bool+inRange a r = singletonRange a `isSubRangeOf` r++-- | A convenience function for defining range propagation. If the input+--   range is empty then the result is also empty.+rangeOp :: BoundedInt a => (Range a -> Range a) -> (Range a -> Range a)+rangeOp f r = if isEmpty r then r else f r++-- | See 'rangeOp'.+rangeOp2 :: BoundedInt a =>+    (Range a -> Range a -> Range a) -> (Range a -> Range a -> Range a)+rangeOp2 f r1 r2+  | isEmpty r1 = r1+  | isEmpty r2 = r2+  | otherwise  = f r1 r2++-- | Union on ranges.+rangeUnion :: BoundedInt a => Range a -> Range a -> Range a+r1 `rangeUnion` r2+    | isEmpty r1 = r2+    | isEmpty r2 = r1+    | otherwise  = union r1 r2+  where+    union (Range l1 u1) (Range l2 u2) = Range (min l1 l2) (max u1 u2)++-- | Intersection on ranges.+rangeIntersection :: BoundedInt a => Range a -> Range a -> Range a+rangeIntersection = rangeOp2 intersection+  where+    intersection (Range l1 u1) (Range l2 u2) = Range (max l1 l2) (min u1 u2)++-- | @disjoint r1 r2@ returns true when @r1@ and @r2@ have no elements in+--   common.+disjoint :: BoundedInt a => Range a -> Range a -> Bool+disjoint r1 r2 = isEmpty (r1 /\ r2)++-- | @rangeGap r1 r2@ returns a range of all the elements between @r1@ and+--   @r2@ including the boundary elements. If @r1@ and @r2@ have elements in+--   common the result is an empty range.+rangeGap :: BoundedInt a => Range a -> Range a -> Range a+rangeGap = rangeOp2 gap+  where+    gap (Range l1 u1) (Range l2 u2)+      | u1 < l2 = range u1 l2+      | u2 < l1 = range u2 l1+    gap _ _     = emptyRange+  -- If the result is non-empty, it will include the boundary elements from the+  -- two ranges.++-- | @r1 \`rangeLess\` r2:@+--+-- Checks if all elements of @r1@ are less than all elements of @r2@.+rangeLess :: BoundedInt a => Range a -> Range a -> Bool+rangeLess r1 r2+  | isEmpty r1 || isEmpty r2 = True+rangeLess (Range _ u1) (Range l2 _) = u1 < l2++-- | @r1 \`rangeLessEq\` r2:@+--+-- Checks if all elements of @r1@ are less than or equal to all elements of+-- @r2@.+rangeLessEq :: BoundedInt a => Range a -> Range a -> Bool+rangeLessEq (Range _ u1) (Range l2 _) = u1 <= l2++++--------------------------------------------------------------------------------+-- * Propagation+--------------------------------------------------------------------------------++-- | Implements 'fromInteger' as a 'singletonRange', and implements correct+-- range propagation for arithmetic operations.+instance BoundedInt a => Num (Range a)+  where+    fromInteger = singletonRange . fromInteger+    abs         = rangeAbs+    signum      = rangeSignum+    negate      = rangeNeg+    (+)         = rangeAdd+    (*)         = rangeMul++-- | Propagates range information through @abs@.+rangeAbs :: BoundedInt a => Range a -> Range a+rangeAbs = rangeOp $ \r -> case r of+    Range l u+      | isNatural  r -> r+      | r == singletonRange minBound -> r+      | minBound `inRange` r -> range minBound maxBound+      | isNegative r -> range (abs u) (abs l)+      | otherwise    -> range 0 (abs l `max` abs u)++-- | Propagates range information through 'signum'.+rangeSignum :: BoundedInt a => Range a -> Range a+rangeSignum = handleSign rangeSignumUnsigned rangeSignumSigned++-- | Signed case for 'rangeSignum'.+rangeSignumSigned :: BoundedInt a => Range a -> Range a+rangeSignumSigned = rangeOp sign+  where+    sign r+      | range (-1) 1 `isSubRangeOf` r = range (-1) 1+      | range (-1) 0 `isSubRangeOf` r = range (-1) 0+      | range 0 1    `isSubRangeOf` r = range 0 1+      | inRange 0 r                   = 0+      | isNatural r                   = 1+      | isNegative r                  = -1++-- | Unsigned case for 'rangeSignum'.+rangeSignumUnsigned :: BoundedInt a => Range a -> Range a+rangeSignumUnsigned = rangeOp sign+    where+      sign r+          | r == singletonRange 0 = r+          | not (0 `inRange` r)   = singletonRange 1+          | otherwise             = range 0 1++-- | Propagates range information through negation.+rangeNeg :: BoundedInt a => Range a -> Range a+rangeNeg = handleSign rangeNegUnsigned rangeNegSigned++-- | Unsigned case for 'rangeNeg'.+rangeNegUnsigned :: BoundedInt a => Range a -> Range a+rangeNegUnsigned (Range l u)+    | l == 0 && u /= 0 = fullRange+    | otherwise        = range (-u) (-l)+-- Code from Hacker's Delight++-- | Signed case for 'rangeNeg'.+rangeNegSigned :: BoundedInt a => Range a -> Range a+rangeNegSigned (Range l u)+    | l == minBound && u == minBound = singletonRange minBound+    | l == minBound                  = fullRange+    | otherwise                      = range (-u) (-l)+-- Code from Hacker's Delight++-- | Propagates range information through addition.+rangeAdd :: BoundedInt a => Range a -> Range a -> Range a+rangeAdd = handleSign rangeAddUnsigned rangeAddSigned++-- | Unsigned case for 'rangeAdd'.+rangeAddUnsigned :: BoundedInt a => Range a -> Range a -> Range a+rangeAddUnsigned (Range l1 u1) (Range l2 u2)+    | s >= l1 && t < u1 = fullRange+    | otherwise         = range s t+  where+    s = l1 + l2+    t = u1 + u2+-- Code from Hacker's Delight++-- | Signed case for 'rangeAdd'.+rangeAddSigned :: BoundedInt a => Range a -> Range a -> Range a+rangeAddSigned (Range l1 u1) (Range l2 u2)+    | (u .|. v) < 0 = fullRange+    | otherwise     = range s t+  where+    s = l1 + l2+    t = u1 + u2+    u = l1 .&. l2 .&. complement s .&.+        complement (u1 .&. u2 .&. complement t)+    v = ((xor l1 l2) .|. complement (xor l1 s)) .&.+        (complement u1 .&. complement u2 .&. t)+-- Code from Hacker's Delight++-- | Propagates range information through subtraction.+rangeSub :: BoundedInt a => Range a -> Range a -> Range a+rangeSub = handleSign rangeSubUnsigned (-)++-- | Unsigned case for 'rangeSub'.+rangeSubUnsigned :: BoundedInt a => Range a -> Range a -> Range a+rangeSubUnsigned (Range l1 u1) (Range l2 u2)+    | s > l1 && t <= u1 = fullRange+    | otherwise         = range s t+  where+    s = l1 - u2+    t = u1 - l2+  -- Note: This is more accurate than the default definition using 'negate',+  --       because 'negate' always overflows for unsigned numbers.+  -- Code from Hacker's Delight++-- | Propagates range information through multiplication+rangeMul :: BoundedInt a => Range a -> Range a -> Range a+rangeMul = handleSign rangeMulUnsigned rangeMulSigned++-- | Signed case for 'rangeMul'.+rangeMulSigned :: forall a . BoundedInt a => Range a -> Range a -> Range a+rangeMulSigned r1 r2+    | r1 == singletonRange 0 || r2 == singletonRange 0 = singletonRange 0+    -- The following case is important because the 'maxAbs' function doesn't+    -- work for 'minBound' on signed numbers.+    | lowerBound r1 == minBound || lowerBound r2 == minBound+        = range minBound maxBound+    | bits (maxAbs r1) + bits (maxAbs r2) <= bitSize (undefined :: a) - 1+        = range (minimum [b1,b2,b3,b4]) (maximum [b1,b2,b3,b4])+    | otherwise = range minBound maxBound+  where maxAbs (Range l u) = max (abs l) (abs u)+        b1 = lowerBound r1 * lowerBound r2+        b2 = lowerBound r1 * upperBound r2+        b3 = upperBound r1 * lowerBound r2+        b4 = upperBound r1 * upperBound r2++-- | Unsigned case for 'rangeMul'.+rangeMulUnsigned :: forall a . BoundedInt a => Range a -> Range a -> Range a+rangeMulUnsigned r1 r2+    | bits (upperBound r1) + bits (upperBound r2)+      <= bitSize (undefined :: a)+        = mapMonotonic2 (*) r1 r2+    | otherwise = universal++-- | Returns the position of the highest bit set to 1. Counting starts at 1.+-- Beware! It doesn't terminate for negative numbers.+bits :: Bits b => b -> Int+bits b = loop b 0+    where loop 0 c = c+          loop n c = loop (n `shiftR` 1) (c+1)++-- | Propagates range information through exponentiation.+rangeExp :: BoundedInt a => Range a -> Range a -> Range a+rangeExp = handleSign rangeExpUnsigned rangeExpSigned++-- | Unsigned case for 'rangeExp'.+rangeExpUnsigned :: BoundedInt a => Range a -> Range a -> Range a+rangeExpUnsigned m@(Range l1 u1) e@(Range l2 u2) +    | toInteger (bits u1) * toInteger u2 > toInteger (bitSize l1) + 1 = universal+    | toInteger u1 ^ toInteger u2 > toInteger (maxBound `asTypeOf` l1) = universal+    | 0 `inRange` m && 0 `inRange` e = range 0 (max b1 b2)+    | otherwise = range b1 b2+  where b1 = (l1 ^ l2)+        b2 = (u1 ^ u2)++-- | Sigend case for 'rangeExp'+rangeExpSigned :: BoundedInt a => Range a -> Range a -> Range a+rangeExpSigned _ _ = universal++-- | Propagates range information through '.|.'.+rangeOr :: forall a . BoundedInt a => Range a -> Range a -> Range a+rangeOr = handleSign rangeOrUnsignedAccurate (\_ _ -> universal)++-- | Cheap and inaccurate range propagation for '.|.' on unsigned numbers.+rangeOrUnsignedCheap :: BoundedInt a => Range a -> Range a -> Range a+rangeOrUnsignedCheap (Range l1 u1) (Range l2 u2) =+    range (max l1 l2) (maxPlus u1 u2)+-- Code from Hacker's Delight.++-- | @a \`maxPlus\` b@ adds @a@ and @b@ but if the addition overflows then+--   'maxBound' is returned.+maxPlus :: BoundedInt a => a -> a -> a+maxPlus b d = if sum < b then maxBound+              else sum+  where sum = b + d++-- | Accurate lower bound for '.|.' on unsigned numbers.+minOrUnsigned :: BoundedInt a => a -> a -> a -> a -> a+minOrUnsigned a b c d = loop (bit (bitSize a - 1))+  where loop 0 = a .|. c+        loop m+            | complement a .&. c .&. m > 0 =+                let temp = (a .|. m) .&. negate m+                in if temp <= b+                   then temp .|. c+                   else loop (shiftR m 1)+            | a .&. complement c .&. m > 0 =+                let temp = (c .|. m) .&. negate m+                in if temp <= d+                   then a .|. temp+                   else loop (shiftR m 1)+            | otherwise = loop (shiftR m 1)+-- Code from Hacker's Delight.++-- | Accurate upper bound for '.|.' on unsigned numbers.+maxOrUnsigned :: BoundedInt a => a -> a -> a -> a -> a+maxOrUnsigned a b c d = loop (bit (bitSize a - 1))+  where loop 0 = b .|. d+        loop m+             | b .&. d .&. m > 0 =+                 let temp = (b - m) .|. (m - 1)+                 in if temp >= a+                    then temp .|. d+                    else let temp = (d - m) .|. (m - 1)+                         in if temp >= c+                            then b .|. temp+                            else loop (shiftR m 1)+             | otherwise = loop (shiftR m 1)+-- Code from Hacker's Delight.++-- | Accurate range propagation through '.|.' for unsigned types.+rangeOrUnsignedAccurate :: BoundedInt a => Range a -> Range a -> Range a+rangeOrUnsignedAccurate (Range l1 u1) (Range l2 u2) =+    range (minOrUnsigned l1 u1 l2 u2) (maxOrUnsigned l1 u1 l2 u2)+-- Code from Hacker's Delight.++-- | Propagating range information through '.&.'.+rangeAnd :: forall a . BoundedInt a => Range a -> Range a -> Range a+rangeAnd = handleSign rangeAndUnsignedCheap (\_ _ -> universal)++-- | Cheap and inaccurate range propagation for '.&.' on unsigned numbers.+rangeAndUnsignedCheap :: BoundedInt a => Range a -> Range a -> Range a+rangeAndUnsignedCheap (Range l1 u1) (Range l2 u2) = range 0 (min u1 u2)+-- Code from Hacker's Delight.++-- | Propagating range information through 'xor'.+rangeXor :: forall a . BoundedInt a => Range a -> Range a -> Range a+rangeXor = handleSign rangeXorUnsigned  (\_ _ -> universal)++-- | Unsigned case for 'rangeXor'.+rangeXorUnsigned :: BoundedInt a => Range a -> Range a -> Range a+rangeXorUnsigned (Range l1 u1) (Range l2 u2) = range 0 (maxPlus u1 u2)+-- Code from Hacker's Delight.++-- | Propagating range information through 'shiftLU'.+rangeShiftLU :: BoundedInt a => Range a -> Range Word32 -> Range a+rangeShiftLU = handleSign rangeShiftLUUnsigned (\_ _ -> universal)+-- TODO: improve accuracy++-- | Unsigned case for 'rangeShiftLU'.+rangeShiftLUUnsigned (Range l1 u1) (Range l2 u2)+    | toInteger (bits u1) + fromIntegral u2 > toInteger (bitSize u1) = universal+rangeShiftLUUnsigned (Range l1 u1) (Range l2 u2)+    = range (shiftL l1 (fromIntegral l2)) (shiftL u1 (fromIntegral u2))++-- | Propagating range information through 'shiftRU'.+rangeShiftRU :: BoundedInt a => Range a -> Range Word32 -> Range a+rangeShiftRU = handleSign rangeShiftRUUnsigned (\_ _ -> universal)+-- TODO: improve accuracy++-- | Unsigned case for 'rangeShiftRU'.+rangeShiftRUUnsigned (Range l1 u1) (Range l2 u2)+    = range (correctShiftRU l1 u2) (correctShiftRU u1 l2)++-- | This is a replacement fror Haskell's shiftR. If we carelessly use+--   Haskell's variant then we will get left shifts for very large shift values.+correctShiftRU :: Bits a => a -> Word32 -> a+correctShiftRU a i | i > fromIntegral (maxBound :: Int) = 0+correctShiftRU a i = shiftR a (fromIntegral i)++-- | Propagates range information through 'max'.+rangeMax :: BoundedInt a => Range a -> Range a -> Range a+rangeMax r1 r2+    | isEmpty r1        = r2+    | isEmpty r2        = r1+    | r1 `rangeLess` r2 = r2+    | r2 `rangeLess` r1 = r1+    | otherwise         = mapMonotonic2 max r1 r2++-- | Analogous to 'rangeMax'+rangeMin :: BoundedInt a => Range a -> Range a -> Range a+rangeMin r1 r2+    | isEmpty r1        = r2+    | isEmpty r2        = r1+    | r1 `rangeLess` r2 = r1+    | r2 `rangeLess` r1 = r2+    | otherwise         = mapMonotonic2 min r1 r2++-- | Propagates range information through 'mod'.+-- Note that we assume Haskell semantics for 'mod'.+rangeMod :: BoundedInt a => Range a -> Range a -> Range a+rangeMod d r+    | isSigned (lowerBound d) && +      minBound `inRange` d && (-1) `inRange` r = fullRange+    | d `rangeLess` r && isNatural r && isNatural d = d+    | isNatural r = range 0 (pred (upperBound r))+    | r `rangeLess` d && isNeg r && isNeg d = d+    | isNeg r = range (succ (lowerBound r)) 0+    where+      isNeg = (`isSubRangeOf` negs)+      negs  = negativeRange \/ 0+rangeMod d (Range l u) = Range (succ l) (pred u)++-- | Propagates range information through 'rem'.+-- Note that we assume Haskell semantics for 'rem'.+rangeRem :: BoundedInt a => Range a -> Range a -> Range a+rangeRem d r+    | isSigned (lowerBound d) &&+      minBound `inRange` d && (-1) `inRange` r = fullRange+    | d `rangeLessAbs` r && isNatural d = d+    | isNatural d = range 0 (pred (upperBound (abs r)))+    | d `absRangeLessAbs` r && isNeg d = d+    | isNeg d = range (negate (upperBound (abs r))) 0+    where+      isNeg = (`isSubRangeOf` negs)+      negs  = negativeRange \/ 0+rangeRem d r@(Range l u)+    | abs l >= abs u || l == minBound = range (succ $ negate $ abs l) (predAbs l)+    | otherwise      = range (succ $ negate $ abs u) (predAbs u)++predAbs l | l == minBound = abs (succ l)+          | otherwise     = pred (abs l)++-- | Propagates range information through 'quot'.+rangeQuot :: BoundedInt a => Range a -> Range a -> Range a+rangeQuot = handleSign rangeQuotU (\_ _ -> universal)++-- | Unsigned case for 'rangeQuot'.+rangeQuotU :: BoundedInt a => Range a -> Range a -> Range a+rangeQuotU (Range l1 u1) (Range l2 u2) | l2 == 0 || u2 == 0 = universal+rangeQuotU (Range l1 u1) (Range l2 u2) = Range (l1 `quot` u2) (u1 `quot` l2)++-- | Writing @d \`rangeLess\` abs r@ doesn't mean what you think it does because+-- 'r' may contain minBound which doesn't have a positive representation.+-- Instead, this function should be used.+rangeLessAbs d r+    | r == singletonRange minBound+        = lowerBound d /= minBound+    | lowerBound r == minBound+        = d `rangeLess` (abs (range (succ (lowerBound r)) (upperBound r)))+    | otherwise = d `rangeLess` (abs r)++-- | Similar to 'rangeLessAbs' but replaces the expression +--   @abs d \`rangeLess\` r@ instead.+absRangeLessAbs d r+    | lowerBound d == minBound = False+    | otherwise = abs d `rangeLessAbs` r+++--------------------------------------------------------------------------------+-- * Testing+--------------------------------------------------------------------------------++instance (BoundedInt a, Arbitrary a) => Arbitrary (Range a)+  where+    arbitrary = do+      [bound1,bound2] <- vectorOf 2 $ oneof+                         [ arbitrary+                         , elements [minBound,-1,0,1,maxBound]]+      frequency+                [ (10, return $+                     Range (min bound1 bound2) (max bound1 bound2))+                , (1 , return $+                     Range (max bound1 bound2) (min bound1 bound2)) -- Empty+                , (1 , return $+                     Range bound1 bound1)  -- Singleton+                ]++    shrink (Range x y) =+      [ Range x' y | x' <- shrink x ] +++      [ Range x y' | y' <- shrink y ]++instance Random Word32 where+  random g = (fromIntegral i,g')+   where (i :: Int,g') = random g+  randomR (l,u) g = (fromIntegral i,g')+    where (i :: Integer, g') = randomR (fromIntegral l,fromIntegral u) g++instance Random Int8 where+  random g = (fromIntegral i,g')+   where (i :: Int,g') = random g+  randomR (l,u) g = (fromIntegral i,g')+    where (i :: Integer, g') = randomR (fromIntegral l,fromIntegral u) g++instance Random Word8 where+  random g = (fromIntegral i,g')+   where (i :: Int,g') = random g+  randomR (l,u) g = (fromIntegral i,g')+    where (i :: Integer, g') = randomR (fromIntegral l,fromIntegral u) g+++fromRange :: Random a => Range a -> Gen a+fromRange r = choose (lowerBound r, upperBound r)++rangeTy :: Range t -> t -> Range t+rangeTy r t = r++-- | Applies a (monadic) function to all the types we are interested in testing+-- with for Feldspar.+--+-- Example usage: 'atAllTypes (quickCheck . prop_mul)'+atAllTypes :: (Monad m) =>+              (forall t . (BoundedInt t, Random t, Arbitrary t, Typeable t) =>+                      t -> m a)+                  -> m ()+atAllTypes test = sequence_ [test (undefined :: Int)+                            ,test (undefined :: Int8)+                            ,test (undefined :: Word32)+                            ,test (undefined :: Word8)+                            ]++--------------------------------------------------------------------------------+-- ** Set operations+--------------------------------------------------------------------------------++prop_empty t = isEmpty (emptyRange `rangeTy` t)++prop_full t = isFull (fullRange `rangeTy` t)++prop_isEmpty t r = isEmpty r ==> (upperBound r < lowerBound (r `rangeTy` t))+{-+prop_rangeByRange t r1 r2 =+    (rangeLess r1 r2 && not (isEmpty (r1/\r2))) ==> isEmpty (rangeByRange r1 r2)+  where _ = r1 `rangeTy` t+-}+prop_rangeByRange1 t r1 r2 =+    lowerBound r1 < lowerBound r2 && upperBound r1 < upperBound r2 ==>+    r1 `isSubRangeOf` rangeByRange r1 r2+  where _ = r1 `rangeTy` t++prop_rangeByRange2 t r1 r2 =+    lowerBound r1 < lowerBound r2 && upperBound r1 < upperBound r2 ==>+    r2 `isSubRangeOf` rangeByRange r1 r2+  where _ = r1 `rangeTy` t++prop_rangeByRange3 t r1 r2 =+    lowerBound r1 < lowerBound r2 && upperBound r1 < upperBound r2 ==>+    (r1 `rangeUnion` r2) `isSubRangeOf` rangeByRange r1 r2+  where _ = r1 `rangeTy` t++prop_singletonRange t a = isSingleton (singletonRange (a `asTypeOf` t))++prop_singletonSize t r = isSingleton (r `rangeTy` t) ==> (rangeSize r == 1)++prop_emptySubRange1 t r1 r2 =+    isEmpty (r1 `rangeTy` t) ==> (not (isEmpty r2) ==>+                                      not (r2 `isSubRangeOf` r1))++prop_emptySubRange2 t r1 r2 =+    isEmpty (r1 `rangeTy` t) ==> (not (isEmpty r2) ==> (r1 `isSubRangeOf` r2))++prop_rangeGap t r1 r2 =+    (isEmpty gap1 && isEmpty gap2) || (gap1 == gap2)+  where+    gap1 = rangeGap r1 r2+    gap2 = rangeGap r2 r1+    _    = r1 `rangeTy` t++prop_union1 t x r1 r2 =+    ((x `inRange` r1) || (x `inRange` r2)) ==> (x `inRange` (r1\/r2))+  where _ = x `asTypeOf` t++prop_union2 t x r1 r2 =+    (x `inRange` (r1\/r2)) ==>+        ((x `inRange` r1) || (x `inRange` r2) || (x `inRange` rangeGap r1 r2))+  where _ = x `asTypeOf` t++prop_union3 t r1 r2 = (r1 `rangeTy` t) `isSubRangeOf` (r1\/r2)+prop_union4 t r1 r2 = (r2 `rangeTy` t) `isSubRangeOf` (r1\/r2)+++prop_intersect1 t x r1 r2 =+    ((x `inRange` r1) && (x `inRange` r2)) ==> (x `inRange` (r1/\r2))+  where _ = x `asTypeOf` t+prop_intersect2 t x r1 r2 =+    (x `inRange` (r1/\r2)) ==> ((x `inRange` r1) && (x `inRange` r2))+  where _ = x `asTypeOf` t++prop_intersect3 t r1 r2 = (r1/\r2) `isSubRangeOf` (r1 `rangeTy` t)+prop_intersect4 t r1 r2 = (r1/\r2) `isSubRangeOf` (r2 `rangeTy` t)++prop_intersect5 t r1 r2 =+    isEmpty r1 || isEmpty r2 ==> isEmpty (r1/\r2)+  where _ = r1 `rangeTy` t++prop_disjoint t x r1 r2 =+    disjoint r1 r2 ==> (x `inRange` r1) ==> not (x `inRange` r2)+  where _ = x `asTypeOf` t+++prop_rangeLess1 t r1 r2 =+    rangeLess r1 r2 ==> disjoint r1 (r2 `rangeTy` t)++prop_rangeLess2 t r1 r2 =+    not (isEmpty r1) && not (isEmpty r2) ==>+    forAll (fromRange r1) $ \x ->+    forAll (fromRange r2) $ \y ->+    rangeLess r1 r2 ==> x < y+  where _ = r1 `rangeTy` t++prop_rangeLessEq t r1 r2 =+    not (isEmpty r1) && not (isEmpty r2) ==>+    forAll (fromRange r1) $ \x ->+    forAll (fromRange r2) $ \y ->+    rangeLessEq r1 r2 ==> x <= y+  where _ = r1 `rangeTy` t+++--------------------------------------------------------------------------------+-- ** Propagation+--------------------------------------------------------------------------------++prop_propagation1 :: (BoundedInt t, Random t) =>+                     t -> (forall a . Num a => a -> a) -> Range t -> Property+prop_propagation1 t op r =+    not (isEmpty r) ==>+    forAll (fromRange r) $ \x ->+    op x `inRange` op r++-- | This function is useful for range propagation functions like+-- 'rangeMax', 'rangeMod' etc.+-- It takes two ranges, picks an element out of either ranges and+-- checks if applying the operation to the individual elements is in+-- the resulting range after range propagation.+--+-- The third argument is a precondition that is satisfied before the test is +-- run. A good example is to make sure that the second argument is non-zero+-- when testing division.+rangePropagationSafetyPre :: (Random t, BoundedInt t, BoundedInt a) =>+    t ->+    (t -> t -> a) -> (Range t -> Range t -> Range a) ->+    (t -> t -> Bool) ->+    Range t -> Range t -> Property+rangePropagationSafetyPre t op rop pre r1 r2 =+    not (isEmpty r1) && not (isEmpty r2) ==>+    forAll (fromRange r1) $ \v1 ->+    forAll (fromRange r2) $ \v2 ->+        pre v1 v2 ==>+        op v1 v2 `inRange` rop r1 r2++rangePropagationSafetyPre2 ::+    (Random t, BoundedInt t, Random t2, BoundedInt t2, BoundedInt a) =>+    t ->+    (t -> t2 -> a) -> (Range t -> Range t2 -> Range a) ->+    (t -> t2 -> Bool) ->+    Range t -> Range t2 -> Property+rangePropagationSafetyPre2 t op rop pre r1 r2 =+    not (isEmpty r1) && not (isEmpty r2) ==>+    forAll (fromRange r1) $ \v1 ->+    forAll (fromRange r2) $ \v2 ->+        pre v1 v2 ==>+        op v1 v2 `inRange` rop r1 r2++rangePropagationSafety t op rop = rangePropagationSafetyPre t op rop noPre+  where+    noPre _ _ = True++rangePropSafety1 t op rop ran =+    not (isEmpty ran) ==>+    forAll (fromRange ran) $ \val ->+        op val `inRange` rop ran+  where _ = ran `rangeTy` t++prop_propagation2+    :: (BoundedInt t, Random t) => t -> (forall a . Num a => a -> a -> a)+    -> Range t -> Range t -> Property+prop_propagation2 t op r1 r2 = rangePropagationSafety t op op r1 r2+++prop_fromInteger t a = isSingleton (fromInteger a `rangeTy` t)++prop_abs  t = prop_propagation1 t abs+prop_sign t = prop_propagation1 t signum+prop_neg  t = prop_propagation1 t negate+prop_add  t = prop_propagation2 t (+)+prop_sub  t = prop_propagation2 t (-)+prop_mul  t = prop_propagation2 t (*)++prop_exp  t = rangePropagationSafetyPre t (^) rangeExp (\_ e -> e >= 0)++prop_mulU t = rangePropagationSafety t (*) rangeMulUnsigned++-- This property doesn't hold!+-- The problem is the singleton range minBound minBound+prop_isNegative (r::Range Int) =+    not (isEmpty r) ==> (isNegative r ==> not (isNegative $ negate r))++prop_abs2 t r = +    (if isSigned (minBound `asTypeOf` t) then+        lowerBound r /= (minBound `asTypeOf` t)+     else True)+    ==> isNatural (abs r)+++prop_or t = rangePropagationSafety t (.|.) rangeOr++prop_and t = rangePropagationSafety t (.&.) rangeAnd++prop_xor t = rangePropagationSafety t xor rangeXor++prop_shiftLU t+    = rangePropagationSafetyPre2 t fixShiftL rangeShiftLU (\_ _ -> True)+  where fixShiftL a b = shiftL a (fromIntegral b)++prop_shiftRU t+    = rangePropagationSafetyPre2 t fixShiftR rangeShiftRU (\_ _ -> True)+  where fixShiftR a b = correctShiftRU a (fromIntegral b)++prop_rangeMax1 t r1 = rangeMax r1 r1 == (r1 `rangeTy` t)++prop_rangeMax2 t r1 r2 =+    not (isEmpty r1) && not (isEmpty r2) ==>+    upperBound r1 <= upperBound max && upperBound r2 <= upperBound max+    where+      max = rangeMax r1 (r2 `rangeTy` t)++prop_rangeMax3 t r1 r2 =+    not (isEmpty r1) && not (isEmpty r2) ==>+  lowerBound (rangeMax r1 r2) == max (lowerBound r1) (lowerBound r2)+  where _ = r1 `rangeTy` t++prop_rangeMax4 t r1 r2 =+    not (isEmpty r1) && not (isEmpty r2) ==>+    rangeMax r1 r2 == rangeMax r2 r1+  where _ = r1 `rangeTy` t++prop_rangeMax5 t r1 r2 =+    (isEmpty r1 && not (isEmpty r2) ==>+    rangeMax r1 r2 == r2)+    QC..&.+    (isEmpty r2 && not (isEmpty r1) ==>+    rangeMax r1 r2 == r1)+  where _ = r1 `rangeTy` t++prop_rangeMax6 t v1 v2 =+    max v1 v2 `inRange` rangeMax (singletonRange v1) (singletonRange v2)+  where _ = v1 `asTypeOf` t++prop_rangeMax7 a r1 r2 =+    rangePropagationSafety a max rangeMax r1 r2++prop_rangeMin1 t r1 = rangeMin r1 r1 == (r1 `rangeTy` t)++prop_rangeMin2 t r1 r2 =+    not (isEmpty r1) && not (isEmpty r2) ==>+    lowerBound min <= lowerBound r1 && lowerBound min <= lowerBound r2+    where+      min = rangeMin r1 (r2 `rangeTy` t)++prop_rangeMin3 t r1 r2 =+    not (isEmpty r1) && not (isEmpty r2) ==>+  upperBound (rangeMin r1 r2) == min (upperBound r1) (upperBound r2)+  where _ = r1 `rangeTy` t++prop_rangeMin4 t r1 r2 =+    not (isEmpty r1) && not (isEmpty r2) ==>+    rangeMin r1 r2 == rangeMin r2 r1+  where _ = r1 `rangeTy` t++prop_rangeMin5 t r1 r2 =+    (isEmpty r1 && not (isEmpty r2) ==>+    rangeMin r1 r2 == r2)+    QC..&.+    (isEmpty r2 && not (isEmpty r1) ==>+    rangeMin r1 r2 == r1)+  where _ = r1 `rangeTy` t++prop_rangeMin6 t v1 v2 =+    min v1 v2 `inRange` rangeMin (singletonRange v1) (singletonRange v2)+  where _ = v1 `asTypeOf` t++prop_rangeMin7 t r1 r2 =+    rangePropagationSafety t min rangeMin r1 r2++prop_rangeMod1 t v1 v2 =+    v2 /= 0 ==>+    mod v1 v2 `inRange` rangeMod (singletonRange v1) (singletonRange v2)+  where _ = v1 `asTypeOf` t++prop_rangeMod2 t =+    rangePropagationSafetyPre t mod rangeMod divPre++prop_rangeMod3 t =+    if isSigned t then+        isFull $ rangeMod (singletonRange (minBound `asTypeOf` t))+                          (singletonRange (-1))+    else+        True++prop_rangeRem t =+    rangePropagationSafetyPre t rem rangeRem divPre++prop_rangeRem1 t =+    if isSigned t then+        isFull $ rangeRem (singletonRange (minBound `asTypeOf` t))+                          (singletonRange (-1))+    else+        True+++prop_rangeQuot t =+    rangePropagationSafetyPre t quot rangeQuot divPre++prop_rangeQuot1 t =+    if isSigned t then+        isFull $ rangeQuot (singletonRange (minBound `asTypeOf` t))+                           (singletonRange (-1))+    else+        True+++-- | Precondition for division like operators. +--   Avoids division by zero and arithmetic overflow.+divPre v1 v2 = v2 /= 0 && not (v1 == minBound && v2 == (-1))++--------------------------------------------------------------------------------+-- ** Running+--------------------------------------------------------------------------------++data TestCase = forall t. Testable t => TC String t++typedTests :: forall a. (BoundedInt a, Random a, Arbitrary a, Integral a) =>+              a -> [TestCase]+typedTests a =+    [TC "prop_empty"           (prop_empty a)+    ,TC "prop_full"            (prop_full a)+    ,TC "prop_isEmpty"         (prop_isEmpty a)+--    ,TC "prop_rangeByRange"    (prop_rangeByRange a)+      -- TODO "*** Gave up! Passed only 0 tests."+    ,TC "prop_rangeByRange1"   (prop_rangeByRange1 a)+    ,TC "prop_rangeByRange2"   (prop_rangeByRange2 a)+    ,TC "prop_rangeByRange3"   (prop_rangeByRange3 a)+    ,TC "prop_singletonRange"  (prop_singletonRange a)+    ,TC "prop_singletonSize"   (prop_singletonSize a)+    ,TC "prop_emptySubRange1"  (prop_emptySubRange1 a)+    ,TC "prop_emptySubRange2"  (prop_emptySubRange2 a)+    ,TC "prop_rangeGap"        (prop_rangeGap a)+    ,TC "prop_union1"          (prop_union1 a)+    ,TC "prop_union2"          (prop_union2 a)+    ,TC "prop_union3"          (prop_union3 a)+    ,TC "prop_union4"          (prop_union4 a)+    ,TC "prop_intersect1"      (prop_intersect1 a)+    ,TC "prop_intersect2"      (prop_intersect2 a)+    ,TC "prop_intersect3"      (prop_intersect3 a)+    ,TC "prop_intersect4"      (prop_intersect4 a)+    ,TC "prop_intersect5"      (prop_intersect5 a)+    ,TC "prop_disjoint"        (prop_disjoint a)+    ,TC "prop_rangeLess1"      (prop_rangeLess1 a)+    ,TC "prop_rangeLess2"      (prop_rangeLess2 a)+    ,TC "prop_rangeLessEq"     (prop_rangeLessEq a)+    ,TC "prop_fromInteger"     (prop_fromInteger a)+    ,TC "prop_abs"             (prop_abs a)+    ,TC "prop_sign"            (prop_sign a)+    ,TC "prop_neg"             (prop_neg a)+    ,TC "prop_add"             (prop_add a)+    ,TC "prop_sub"             (prop_sub a)+    ,TC "prop_mul"             (prop_mul a)+    ,TC "prop_exp"             (prop_exp a)+--    ,TC "prop_isNegative"      (prop_isNegative a)+    ,TC "prop_abs2"            (prop_abs2 a)+    ,TC "prop_and"             (prop_and a)+    ,TC "prop_or"              (prop_or a)+    ,TC "prop_xor"             (prop_xor a)+    ,TC "prop_shiftLU"         (prop_shiftLU a)+    ,TC "prop_shiftRU"         (prop_shiftRU a)+    ,TC "prop_rangeMax1"       (prop_rangeMax1 a)+    ,TC "prop_rangeMax2"       (prop_rangeMax2 a)+    ,TC "prop_rangeMax3"       (prop_rangeMax3 a)+    ,TC "prop_rangeMax4"       (prop_rangeMax4 a)+    ,TC "prop_rangeMax5"       (prop_rangeMax5 a)+    ,TC "prop_rangeMax6"       (prop_rangeMax6 a)+    ,TC "prop_rangeMax7"       (prop_rangeMax7 a)+    ,TC "prop_rangeMin1"       (prop_rangeMin1 a)+    ,TC "prop_rangeMin2"       (prop_rangeMin2 a)+    ,TC "prop_rangeMin3"       (prop_rangeMin3 a)+    ,TC "prop_rangeMin4"       (prop_rangeMin4 a)+    ,TC "prop_rangeMin5"       (prop_rangeMin5 a)+    ,TC "prop_rangeMin6"       (prop_rangeMin6 a)+    ,TC "prop_rangeMin7"       (prop_rangeMin7 a)+    ,TC "prop_rangeMod1"       (prop_rangeMod1 a)+    ,TC "prop_rangeMod2"       (prop_rangeMod2 a)+    ,TC "prop_rangeMod3"       (prop_rangeMod3 a)+    ,TC "prop_rangeRem"        (prop_rangeRem a)+    ,TC "prop_rangeRem1"       (prop_rangeRem1 a)+    ,TC "prop_rangeQuot"       (prop_rangeQuot a)+    ,TC "prop_rangeQuot1"      (prop_rangeQuot1 a)+    ]++testAll = do testAtType (undefined :: Int)+             testAtType (undefined :: Int8)+             testAtType (undefined :: Word32)+             testAtType (undefined :: Word8)++myCheck (TC name test) =+    do printf "%-25s" name+       quickCheckWith stdArgs {maxDiscard = 10000} test++testAtType t = do let tn = tyConString $ typeRepTyCon $ typeOf t+                  putStrLn $ "Testing using type: " ++ tn+                  mapM_ myCheck (typedTests t) 
+ Feldspar/Set.hs view
@@ -0,0 +1,85 @@+-- | General operations on sets++module Feldspar.Set where++++-- | A 'Set' is an *over-approximation* of a set of values. The class does not+-- care about how the set is interpreted, but it only makes sense to use+-- interpretations for which the operations are sound.+class Eq a => Set a+  where+    empty     :: a+    universal :: a+    -- | Union+    (\/)      :: a -> a -> a+    -- | Intersection+    (/\)      :: a -> a -> a++-- | Approximates all sets as @()@, which is the 'universal' set.+instance Set ()+  where+    empty     = ()+    universal = ()+    () \/ ()  = ()+    () /\ ()  = ()++-- | Set product+instance (Set a, Set b) => Set (a,b)+  where+    empty     = (empty,empty)+    universal = (universal,universal)+    (a1,a2) \/ (b1,b2) = (a1 \/ b1, a2 \/ b2)+    (a1,a2) /\ (b1,b2) = (a1 /\ b1, a2 /\ b2)++-- | Three-way product+instance (Set a, Set b, Set c) => Set (a,b,c)+  where+    empty     = (empty,empty,empty)+    universal = (universal,universal,universal)+    (a1,a2,a3) \/ (b1,b2,b3) = (a1 \/ b1, a2 \/ b2, a3 \/ b3)+    (a1,a2,a3) /\ (b1,b2,b3) = (a1 /\ b1, a2 /\ b2, a3 /\ b3)++-- | Four-way product+instance (Set a, Set b, Set c, Set d) => Set (a,b,c,d)+  where+    empty     = (empty,empty,empty,empty)+    universal = (universal,universal,universal,universal)+    (a1,a2,a3,a4) \/ (b1,b2,b3,b4) = (a1 \/ b1, a2 \/ b2, a3 \/ b3, a4 \/ b4)+    (a1,a2,a3,a4) /\ (b1,b2,b3,b4) = (a1 /\ b1, a2 /\ b2, a3 /\ b3, a4 /\ b4)++unions :: Set a => [a] -> a+unions = foldr (\/) empty++intersections :: Set a => [a] -> a+intersections = foldr (/\) universal++-- Computing fixed points++-- | Take the fixed point of a monotonic function. The second argument is+--   an initial element. A sensible default for the initial element is+--   'empty'.+fixedPoint :: Set a => (a -> a) -> a -> a+fixedPoint f a | fa == a   = fa+               | otherwise = fixedPoint f fa+  where fa = f a \/ a++-- | Much like 'fixedPoint' but keeps track of the number of iterations+--   in the fixed point iteration. Useful for defining widening operators.+indexedFixedPoint :: Set a => (Int -> a -> a) -> a -> (a,Int)+indexedFixedPoint f a = go 0 f a+  where go i f a | fa == a   = (fa,i)+                 | otherwise = go (i+1) f fa+          where fa = f i a \/ a++-- | The type of widening operators. A widening operator modifies a+--   function that is subject to fixed point analysis. A widening+--   operator introduces approximations in order to guarantee (fast)+--   termination of the fixed point analysis.+type Widening a = (Int -> a -> a) -> (Int -> a -> a)++-- | A widening operator which defaults to 'universal' when the number of+--   iterations goes over the specified value.+cutOffAt :: Set a => Int -> Widening a+cutOffAt n f i a | i >= n    = universal+                 | otherwise = f i a
Feldspar/Stream.hs view
@@ -1,57 +1,27 @@------ Copyright (c) 2009-2010, ERICSSON AB All rights reserved.--- --- Redistribution and use in source and binary forms, with or without--- modification, are permitted provided that the following conditions are met:--- ---     * Redistributions of source code must retain the above copyright notice,---       this list of conditions and the following disclaimer.---     * 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 name of the ERICSSON AB nor the names of its contributors---       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 AND CONTRIBUTORS "AS IS"--- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE--- IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE--- ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS--- BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,--- OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF--- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS--- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN--- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)--- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF--- THE POSSIBILITY OF SUCH DAMAGE.-----module Feldspar.Stream +module Feldspar.Stream     (Stream     ,head     ,tail-    ,map+    ,map,mapNth+    ,maps     ,intersperse     ,interleave+    ,downsample+    ,duplicate     ,scan     ,mapAccum     ,iterate     ,repeat     ,unfold     ,drop-    ,dropWhile-    ,filter-    ,partition-    ,zip-    ,zipWith+    ,zip,zipWith     ,unzip     ,take     ,splitAt     ,cycle-    ,recurrence-    ,recurrenceI-    ,iir-    ,fir+    ,streamAsVector, streamAsVectorSize+    ,recurrenceO,recurrenceI,recurrenceIO+    ,iir,fir     )     where @@ -62,142 +32,113 @@ import Control.Arrow  import Feldspar.Vector (Vector, DVector-                       ,vector-                       ,freezeVector,indexed-                       ,sum,length,replicate)+                       ,vector,freezeVector,unfreezeVector,indexed+                       ,sum,length,replicate,reverse,scalarProd)  -- | Infinite streams.-data Stream a = forall state . (Computable a, Computable state) =>-                Stream (StepFunction state a) state--data StepFunction state a -    = Continuous (state -> (a,state))-    | Stuttering (state -> (a,Data Bool, state))---- When we want to treat a step function as if it was continuous.--- Use with care! It introduces an extra while loop if the --- argument is stuttering-step :: (Computable state, Computable a) =>-        StepFunction state a -> (state -> (a,state))-step (Continuous next) init = next init-step (Stuttering next) init = (a,st)-    where (a,_,st) = while (not . snd3) (next . thd3) (next init)---- When we cannot optimize for the continuous case we can use this function--- to consider all step functions as stuttering and reduce the amount of--- code we have to write.-stuttering :: StepFunction state a -> (state -> (a, Data Bool, state))-stuttering (Stuttering next) = next-stuttering (Continuous next) = \state -> let (a,st) = next state-                                         in (a,true,st)---- This helper function enables us to write function using the stuttering --- case only while still propagating the continuous information.--- Helps writing less code.-mapStep :: ((stateA -> (a,Data Bool, stateA)) -> -                (stateB -> (b,Data Bool, stateB))) -        -> StepFunction stateA a -> StepFunction stateB b-mapStep mkStep (Stuttering next) = Stuttering (mkStep next)-mapStep mkStep (Continuous next) = Continuous newStep-  where newStep a = let (b,_,st) = mkStep (\a -> let (b,st) = next a-                                                 in (b,true,st)) a-                    in (b,st)---- Helper functions for working on triplets-fst3 (a,_,_) = a-snd3 (_,b,_) = b-thd3 (_,_,c) = c-first3  f (a,b,c) = (f a,b,c)-second3 f (a,b,c) = (a,f b,c)-third3  f (a,b,c) = (a,b,f c)+data Stream a where+  Stream :: Syntactic state => (state -> (a,state)) -> state -> Stream a  -- | Take the first element of a stream-head :: Computable a => Stream a -> a-head (Stream next init) = fst $ step next init+head :: Syntactic a => Stream a -> a+head (Stream next init) = fst $ next init  -- | Drop the first element of a stream-tail :: Computable a => Stream a -> Stream a-tail (Stream next init) = Stream next (snd $ step next init)+tail :: Syntactic a => Stream a -> Stream a+tail (Stream next init) = Stream next (snd $ next init)  -- | 'map f str' transforms every element of the stream 'str' using the --   function 'f'-map :: (Computable a, Computable b) =>+map :: (Syntactic a, Syntactic b) =>        (a -> b) -> Stream a -> Stream b-map f (Stream next init) = Stream (mapStep (first3 f .) next) init+map f (Stream next init) = Stream newNext init+  where newNext st = let (a,st') = next st in (f a, st') +-- | 'mapNth f n k str' transforms every 'n'th element with offset 'k'+--    of the stream 'str' using the function 'f'+mapNth :: (Syntactic a) => +          (a -> a) -> Data Index -> Data Index -> Stream a -> Stream a+mapNth f n k (Stream next init) = Stream newNext (init,0)+  where newNext (st,i) = let (a,st') = next st in (i==k?(f a,a),(st',(i+1) `mod` n))++-- | 'maps fs str' uses one of the functions from 'fs' successively to modify+--   the elements of 'str'+maps :: (Syntactic a) =>+        [(a -> a)] -> Stream a -> Stream a+maps fs (Stream next init) = Stream newNext (init,0 :: Data Index)+  where newNext (st,i) = +            let (a,st') = next st in+            (Prelude.foldr (\ (k,f) r -> +                                i==(fromIntegral k)?(f a,r)) +                           a (Prelude.zip [1..] fs)+            ,(st',(i+1) `mod` fromIntegral (Prelude.length fs))+            )+ -- | 'intersperse a str' inserts an 'a' between each element of the stream --    'str'.-intersperse :: a -> Stream a -> Stream a-intersperse a (Stream next init) = -    Stream (mapStep newNext next) (true,init)-  where newNext next (b,st) = b ? (let (e,isValid,st') = next st-                                   in isValid ? ( (e,true,(false,st'))-                                                , (e,false,(true,st'))-                                                )-                                  ,(a,true,(true,st))-                                  )+intersperse :: Syntactic a => a -> Stream a -> Stream a+intersperse a (Stream next init) =+    Stream newNext (true,init)+  where newNext (b,st) = b ? (let (e,st') = next st+                              in (e,(false,st'))+                             ,(a,(true,st))+                             ) --- | Create a new stream by alternating between the elements from +-- | Create a new stream by alternating between the elements from --   the two input streams-interleave :: Stream a -> Stream a -> Stream a-interleave (Stream (Continuous next1) init1) (Stream (Continuous next2) init2)-    = Stream (Continuous next) (true,init1,init2)+interleave :: Syntactic a => Stream a -> Stream a -> Stream a+interleave (Stream next1 init1) (Stream next2 init2)+    = Stream next (true,init1,init2)   where next (b,st1,st2) = b ? (let (a,st1') = next1 st1                                 in (a,(false,st1',st2))                                ,let (a,st2') = next2 st2                                 in (a,(true,st1,st2'))                                )-interleave (Stream next1 init1) (Stream next2 init2)-    = Stream (Stuttering next) (true,init1,init2)-  where next (b,st1,st2) = b ? (let (a,isValid,st1') = stuttering next1 st1-                                in isValid ? ( (a,true,(false,st1',st2))-                                             , (a,false,(true,st1',st2))-                                             )-                               ,let (a,isValid,st2') = stuttering next2 st2-                                in isValid ? ( (a,true,(true,st1,st2'))-                                             , (a,false,(false,st1,st2'))-                                             )-                               ) +-- | 'downsample n str' takes every 'n'th element of the input stream+downsample :: Syntactic a => Data Index -> Stream a -> Stream a+downsample n (Stream next init) = Stream newNext init+  where newNext st = forLoop (n-1) (next st) (\_ (_,st) -> next st)++-- | 'duplicate n str' stretches the stream by duplicating the elements 'n' times+duplicate :: Syntactic a => Data Index -> Stream a -> Stream a+duplicate n (Stream next init) = Stream newNext (next init,1)+  where newNext (p@(a,st),i) = i==0 ? (let (b,st') = next st in (b,((b,st'),1))+                                      ,(a,(p,(i+1)`mod`n))+                                      )+ -- | 'scan f a str' produces a stream by successively applying 'f' to---   each element of the input stream 'str' and the previous element of +--   each element of the input stream 'str' and the previous element of --   the output stream.-scan :: Computable a => (a -> b -> a) -> a -> Stream b -> Stream a+scan :: Syntactic a => (a -> b -> a) -> a -> Stream b -> Stream a scan f a (Stream next init)-    = Stream (mapStep newNext next) (a,init)-  where newNext next (acc,st) = let (a,isValid,st') = next st-                                in isValid ? ( (acc,true,  (f acc a,st') )-                                             , (acc,false, (acc,st')     )-                                             )+    = Stream newNext (a,init)+  where newNext (acc,st) = let (a,st') = next st+                           in (acc,  (f acc a,st') )  {- This function is problematic to define for the same reason the index    function is problematic, plus that it has the same quirk as correctScan. -}  -- | A scan but without an initial element.-scan1 :: Computable a => (a -> a -> a) -> Stream a -> Stream a+scan1 :: Syntactic a => (a -> a -> a) -> Stream a -> Stream a scan1 f (Stream next init)-    = Stream (mapStep newNext next) (a,true,newInit)-  where (a,newInit) = step next init-        newNext next (a,isFirst,st)-            = isFirst ? ( (a, true, (a,false,st))-                        , let (b,isValid,st') = next st-                          in isValid ? ( let elem = f a b-                                         in (elem, true, (elem,false,st'))-                                       , (a,false, (a,false,st'))-                                       )+    = Stream newNext (a,true,newInit)+  where (a,newInit) = next init+        newNext (a,isFirst,st)+            = isFirst ? ( (a, (a,false,st))+                        , let (b,st') = next st+                          in let elem = f a b+                             in (elem, (elem,false,st'))                         ) --- mapAccum creates a nested loop. It's either that or recomputing the --- function even for non-valid elements in the input stream.- -- | Maps a function over a stream using an accumulator.-mapAccum :: (Computable acc, Computable b) => +mapAccum :: (Syntactic acc, Syntactic b) =>             (acc -> a -> (acc,b)) -> acc -> Stream a -> Stream b mapAccum f acc (Stream next init)-    = Stream (Continuous newNext) (init,acc)+    = Stream newNext (init,acc)   where newNext (st,acc)-            = let (a,st')  = step next st+            = let (a,st')  = next st                   (acc',b) = f acc a               in (b, (st',acc')) @@ -205,236 +146,209 @@ --   results are used to create a stream. -- -- @iterate f a == [a, f a, f (f a), f (f (f a)) ...]@-iterate :: Computable a => (a -> a) -> a -> Stream a-iterate f init = Stream (Continuous next) init+iterate :: Syntactic a => (a -> a) -> a -> Stream a+iterate f init = Stream next init   where next a = (a, f a)  -- | Repeat an element indefinitely. -- -- @repeat a = [a, a, a, ...]@-repeat :: Computable a => a -> Stream a-repeat a = Stream (Continuous next) unit-  where next _ = (a,unit)+repeat :: Syntactic a => a -> Stream a+repeat a = Stream next (value ())+  where next _ = (a,value ())  -- | @unfold f acc@ creates a new stream by successively applying 'f' to --   to the accumulator 'acc'.-unfold :: (Computable a, Computable c) => (c -> (a,c)) -> c -> Stream a-unfold next init = Stream (Continuous next) init+unfold :: (Syntactic a, Syntactic c) => (c -> (a,c)) -> c -> Stream a+unfold next init = Stream next init  -- | Drop a number of elements from the front of a stream-drop :: Data Unsigned32 -> Stream a -> Stream a-{- This version creates a conditional inside the loop-   The output stream is always stuttering-drop i (Stream next init) = Stream (Stuttering newNext) (i,init)-  where newNext (i,st) = i == 0 ? (let (a,isValid,st') = stuttering next st-                                   in isValid ? ( (a,true,  (0,st'))-                                                , (a,false, (0,st')) -                                                )-                                  ,let (a,isValid,st') = stuttering next st-                                   in isValid ? ( (a,false, (i-1,st'))-                                                , (a,false, (i,  st'))-                                                )-                                  )--}--- This version generates a while loop to compute the initial state--- The output stream is continuous if the input stream is+drop :: Data Length -> Stream a -> Stream a drop i (Stream next init) = Stream next newState-  where (newState,_) = while cond body (init,i)-        cond (st,i)  = i > 0-        body (st,i)  = let (_,b,st') = stuttering next st-                       in b ? ( (st',i-1)-                              , (st',i))---- | @dropWhile p str@ drops element from the stream @str@ as long as the--- elements fulfill the predicate @p@.-dropWhile p (Stream next init) = Stream next newState-  where (_,newState) = while cond body (step next init)-        cond (a,st)  = p a-        body (_,st)  = step next st---- | 'filter p str' removes elements from the stream 'str' if they are false---   according to the predicate 'p'-filter :: (a -> Data Bool) -> Stream a -> Stream a-filter p (Stream next init) = Stream (Stuttering newNext) init-  where newNext st = let (a,isValid,st') = stuttering next st-                     in isValid && p a ? ( (a,true, st')-                                         , (a,false,st')-                                         )---- | Splits a stream in two according to the predicate function. All ---   elements which return true go in the first stream, the rest go in the---   second.-partition :: (a -> Data Bool) -> Stream a -> (Stream a, Stream a)-partition p stream = (filter p stream, filter (not . p) stream)---- In the case that the input streams are stuttering this function--- will introduce nested loops+  where newState  = forLoop i init body+        body _    = snd . next  -- | Pairs together two streams into one. zip :: Stream a -> Stream b -> Stream (a,b) zip (Stream next1 init1) (Stream next2 init2)-    = Stream (Continuous next) (init1,init2)+    = Stream next (init1,init2)   where next (st1,st2) = ( (a,b), (st1',st2') )-            where (a,st1') = step next1 st1-                  (b,st2') = step next2 st2---- This function can also potentially introduce nested loops, just like zip+            where (a,st1') = next1 st1+                  (b,st2') = next2 st2 --- | Pairs together two streams using a function to combine the +-- | Pairs together two streams using a function to combine the --   corresponding elements.-zipWith :: Computable c => (a -> b -> c) -> Stream a -> Stream b -> Stream c+zipWith :: Syntactic c => (a -> b -> c) -> Stream a -> Stream b -> Stream c zipWith f (Stream next1 init1) (Stream next2 init2)-    = Stream (Continuous next) (init1,init2)+    = Stream next (init1,init2)   where next (st1,st2) = ( f a b, (st1',st2'))-            where (a,st1') = step next1 st1-                  (b,st2') = step next2 st2+            where (a,st1') = next1 st1+                  (b,st2') = next2 st2 --- | Given a stream of pairs, split it into two stream. -unzip :: (Computable a, Computable b) => Stream (a,b) -> (Stream a, Stream b)+-- | Given a stream of pairs, split it into two stream.+unzip :: (Syntactic a, Syntactic b) => Stream (a,b) -> (Stream a, Stream b) unzip stream = (map fst stream, map snd stream) -instance RandomAccess (Stream a) where+instance Syntactic a => RandomAccess (Stream a) where   type Element (Stream a) = a-  (Stream next init) ! n = fst3 $ while ((/= 0) . thd3) body (a,st,n)-      where body (a,st,i) = let (a,isValid,st') = stuttering next st-                            in isValid ? ( (a,st',i-1)-                                         , (a,st',i)-                                         )-            (a,st) = step next init -- I would like to get rid of this one+  (Stream next init) ! n = fst $ forLoop n (next init) body+    where body _ (_,st) = next st  -- | 'take n str' allocates 'n' elements from the stream 'str' into a --   core array.-take :: Storable a => Data Int -> Stream (Data a) -> Data [a]-take n (Stream next init) -    = snd3 $ while cond body -      (0,array (mapMonotonic fromIntegral (dataSize n) :> universal) [],init)-  where cond (i,_  ,_ ) = i < n-        body (i,arr,st) = let (a,isValid,st') = stuttering next st-                          in isValid ? ( (i+1,setIx arr i a,st')-                                       , (i,  arr,          st')-                                       )+take :: (Type a) => Data Length -> Stream (Data a) -> Data [a]+take n (Stream next init)+    = sequential n init step (const $ value [])+  where step i st = next st --- | 'splitAt n str' allocates 'n' elements from the stream 'str' into a ---   core array and returns the rest of the stream continuing from +-- | 'splitAt n str' allocates 'n' elements from the stream 'str' into a+--   core array and returns the rest of the stream continuing from --   element 'n+1'.-splitAt :: Storable a => -           Data Int -> Stream (Data a) -> (Data [a], Stream (Data a))-splitAt n (Stream next init) = (arr,Stream next st)-  where -    (_,arr,st) = -        while cond body -        (0,array (mapMonotonic fromIntegral (dataSize n) :> universal) [],init)-    cond (i,_  ,_ ) = i < n-    body (i,arr,st) = let (a,isValid,st') = stuttering next st-                      in isValid ? ( (i+1,setIx arr i a,st')-                                   , (i,  arr,          st')-                                   )+splitAt :: (Type a) =>+           Data Length -> Stream (Data a) -> (Data [a], Stream (Data a))+splitAt n stream = (take n stream,drop n stream)  -- | Loops through a vector indefinitely to produce a stream.-cycle :: Computable a => Vector a -> Stream a-cycle vec = Stream (Continuous next) 0+cycle :: Syntactic a => Vector a -> Stream a+cycle vec = Stream next 0   where next i = (vec ! i, (i + 1) `rem` length vec) +unsafeVectorToStream :: Syntactic a => Vector a -> Stream a+unsafeVectorToStream vec = Stream next 0+  where next i = (vec ! i, i + 1) +-- | A convenience function for translating an algorithm on streams to an algorithm on vectors.+--   The result vector will have the same length as the input vector.+--   It is important that the stream function doesn't drop any elements of+--   the input stream.+-- +--   This function allocates memory for the output vector.+streamAsVector :: (Type a, Type b) => +                  (Stream (Data a) -> Stream (Data b)) +               -> (Vector (Data a) -> Vector (Data b))+streamAsVector f v +    = unfreezeVector $ take (length v) $ f $ unsafeVectorToStream v++-- | Similar to 'streamAsVector' except the size of the output array is computed by the second argument+--   which is given the size of the input vector as a result.+streamAsVectorSize :: (Type a, Type b) => +                      (Stream (Data a) -> Stream (Data b)) -> (Data Length -> Data Length) +                   -> (Vector (Data a) -> Vector (Data b))+streamAsVectorSize f s v = unfreezeVector $ take (s $ length v) $ f $ cycle v+ -- | A combinator for descibing recurrence equations, or feedback loops.---   It uses memory proportional to the input vector+--   The recurrence equation may refer to previous outputs of the stream,+--   but only as many as the length of the input stream+--   It uses memory proportional to the input vector. -- -- For exaple one can define the fibonacci sequence as follows: ----- > fib = recurrence (vector [0,1]) (\fib -> fib 1 + fib 2)+-- > fib = recurrenceO (vector [0,1]) (\fib -> fib!0 + fib!1) ----- The expressions @fib 1@ and @fib 2@ refer to previous elements in the +-- The expressions @fib 1@ and @fib 2@ refer to previous elements in the -- stream defined one step back and two steps back respectively.-recurrence :: Storable a => -              DVector a -> ((Int -> Data a) -> Data a) -> Stream (Data a)-recurrence init mkExpr = Stream (Continuous next) (buf,0)+recurrenceO :: Type a =>+               DVector a -> +               (DVector a -> Data a) -> +               Stream (Data a)+recurrenceO init mkExpr = Stream next (buf,0)   where buf            = freezeVector init-        len            = length init-        next (buf,ix)  = -            let a = mkExpr (\i -> getIx buf ((value i + ix) `rem` len))+        len            = getLength buf+        next (buf,ix)  =+            let a = mkExpr (indexed len (\i -> getIx buf ((i + ix) `rem` len)))             in (getIx buf (ix `rem` len), (setIx buf (ix `rem` len) a, ix + 1)) --- | A recurrence combinator with input++-- | A recurrence combinator with input. The function 'recurrenceI' is +--   similar to 'recurrenceO'. The difference is that that it has an input+--   stream, and that the recurrence equation may only refer to previous+--   inputs, it may not refer to previous outputs. -- -- The sliding average of a stream can easily be implemented using -- 'recurrenceI'. ----- > slidingAvg :: Data Int -> Stream (Data Int) -> Stream (Data Int)--- > slidingAvg n str = recurrenceI (replicate n 0) str (vector [])--- >                    (\input _ -> sum (indexed n input) `quot` n)-recurrenceI :: (Storable a, Storable b) => -               DVector a -> Stream (Data a) -> DVector b ->-               ((Data Int -> Data a) -> (Data Int -> Data b) -> Data b) ->+-- > slidingAvg :: Data DefaultWord -> Stream (Data DefaultWord) -> Stream (Data DefaultWord)+-- > slidingAvg n str = recurrenceI (replicate n 0) str+-- >                    (\input _ -> sum input `quot` n)+recurrenceI :: (Type a, Type b) =>+               DVector a -> Stream (Data a) ->+               (DVector a -> Data b) ->                Stream (Data b)-recurrenceI ii (Stream (Continuous st) s) io mkExpr -    = Stream (Continuous step) (ibuf,obuf,s,0)+recurrenceI ii stream mkExpr +    = recurrenceIO ii stream (vector []) (\i o -> mkExpr i)++-- | 'recurrenceIO' is a combination of 'recurrenceO' and 'recurrenceI'. It+--   has an input stream and the recurrence equation may refer both to+--   previous inputs and outputs.+--+--   'recurrenceIO' is used when defining the 'iir' filter.+recurrenceIO :: (Type a, Type b) =>+                DVector a -> Stream (Data a) -> DVector b ->+                (DVector a -> DVector b -> Data b) ->+                Stream (Data b)+recurrenceIO ii (Stream st s) io mkExpr+    = Stream step (ibuf,obuf,s,0)   where ibuf = freezeVector ii         obuf = freezeVector io-        p    = length ii-        q    = length io-        step (ibuf,obuf,s,ix) = +        p    = getLength ibuf+        q    = getLength obuf+        step (ibuf,obuf,s,ix) =             let (a,s') = st s                 ibuf'  = p /= 0 ? (setIx ibuf (ix `rem` p) a, ibuf)-                b = mkExpr (\i -> getIx ibuf' ((i + ix)     `rem` p))-                           (\i -> getIx obuf  ((i + ix - 1) `rem` q))-            in (q /= 0 ? (getIx obuf (ix `rem` q),b), +                b = mkExpr +                    (indexed p (\i -> getIx ibuf' ((i + ix)     `rem` p)))+                    (indexed q (\i -> getIx obuf  ((i + ix - 1) `rem` q)))+            in (q /= 0 ? (getIx obuf (ix `rem` q),b),                           (ibuf'                           ,q /= 0 ? (setIx obuf (ix `rem` q) b,obuf)                           ,s'                           ,ix + 1))-recurrenceI ii (Stream (Stuttering st) s) io mkExpr-    = Stream (Stuttering step) (ibuf,obuf,s,0)-  where ibuf = freezeVector ii-        obuf = freezeVector io-        p    = length ii-        q    = length io-        step (ibuf,obuf,s,ix) = -            let (a,isValid,s') = st s-                ibuf'  = p /= 0 ? (setIx ibuf (ix `rem` p) a,ibuf)-                b = mkExpr (\i -> getIx ibuf' ((i + ix)     `rem` p))-                           (\i -> getIx obuf  ((i + ix - 1) `rem` q))-            in isValid ?( (q /= 0 ? (getIx obuf (ix `rem` q), b), true,-                                     (ibuf'-                                     ,q /= 0 ? (setIx obuf (ix `rem` q) b,obuf)-                                     ,s'-                                     ,ix + 1))-                        , (q /= 0 ? (getIx obuf (ix `rem` q),b), false,-                                     (ibuf-                                     ,obuf-                                     ,s'-                                     ,ix))-                        ) -slidingAvg :: Data Int -> Stream (Data Int) -> Stream (Data Int)-slidingAvg n str = recurrenceI (replicate n 0) str (vector [])-                   (\input _ -> sum (indexed n input) `quot` n)+recurrenceIIO :: (Type a, Type b, Type c) =>+                 DVector a -> Stream (Data a) -> DVector b -> Stream (Data b) ->+                 DVector c ->+                 (DVector a -> DVector b -> DVector c -> Data c) ->+                 Stream (Data c)+recurrenceIIO i1 (Stream next1 init1) i2 (Stream next2 init2) io mkExpr+    = Stream next ((ibuf1,init1),(ibuf2,init2),obuf,0)+  where ibuf1 = freezeVector i1+        ibuf2 = freezeVector i2+        obuf  = freezeVector io+        l1    = getLength ibuf1+        l2    = getLength ibuf2+        lo    = getLength obuf+        next ((ibuf1,st1),(ibuf2,st2),obuf,ix) =             +            let (a,st1') = next1 st1+                (b,st2') = next2 st2+                ibuf1'  = l1 /= 0 ? (setIx ibuf1 (ix `rem` l1) a, ibuf1)+                ibuf2'  = l2 /= 0 ? (setIx ibuf2 (ix `rem` l2) b, ibuf2)+                c = mkExpr (indexed l1 (\i -> getIx ibuf1' ((i + ix)     `rem` l1)))+                           (indexed l2 (\i -> getIx ibuf2' ((i + ix)     `rem` l2)))+                           (indexed lo (\i -> getIx obuf   ((i + ix - 1) `rem` lo)))+            in (lo /= 0 ? (getIx obuf (ix `rem` lo),c),+                          ((ibuf1',st1')+                          ,(ibuf2',st2')+                          ,lo /= 0 ? (setIx obuf (ix `rem` lo) c,obuf)+                          ,ix + 1)) +slidingAvg :: Data DefaultWord -> Stream (Data DefaultWord) -> Stream (Data DefaultWord)+slidingAvg n str = recurrenceI (replicate n 0) str+                   (\input -> sum input `quot` n)+ -- | A fir filter on streams-fir :: DVector Float -> +fir :: DVector Float ->        Stream (Data Float) -> Stream (Data Float)-fir b input = -    recurrenceI (replicate n 0) input-                (vector [])-                (\input _ -> sum (indexed n (\i -> b!i * input!(n-i))))-  where n = length b+fir b input =+    recurrenceI (replicate (length b) 0) input+                (\input -> scalarProd b input)  -- | An iir filter on streams-iir :: Data Float -> DVector Float -> DVector Float -> +iir :: Data Float -> DVector Float -> DVector Float ->        Stream (Data Float) -> Stream (Data Float)-iir a0 a b input = -    recurrenceI (replicate q 0) input -                (replicate p 0)-      (\input output -> 1 / a0 * -                        ( sum (indexed p (\i -> b!i *  input!(p-i)))-                        - sum (indexed q (\j -> a!j * output!(q-j))))+iir a0 a b input =+    recurrenceIO (replicate (length b) 0) input+                 (replicate (length a) 0)+      (\input output -> 1 / a0 *+                        ( scalarProd b input+                        - scalarProd a output)       )-  where p = length b-        q = length a---- A nice instance to have when using the recurrence functions.-instance RandomAccess (Data Int -> Data a) where-  type Element (Data Int -> Data a) = Data a-  (!) = ($)---- Function to be used with filter for debuggin purposes-even n = n `rem` 2 == 0
− Feldspar/Utils.hs
@@ -1,101 +0,0 @@------ Copyright (c) 2009-2010, ERICSSON AB All rights reserved.--- --- Redistribution and use in source and binary forms, with or without--- modification, are permitted provided that the following conditions are met:--- ---     * Redistributions of source code must retain the above copyright notice,---       this list of conditions and the following disclaimer.---     * 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 name of the ERICSSON AB nor the names of its contributors---       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 AND CONTRIBUTORS "AS IS"--- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE--- IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE--- ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS--- BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,--- OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF--- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS--- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN--- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)--- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF--- THE POSSIBILITY OF SUCH DAMAGE.------- | General utility functions--module Feldspar.Utils where----import Control.Monad.State-import Data.List-import Data.Map (Map)-import qualified Data.Map as Map------ | Checks if all elements in the list are equal.-allEqual :: Eq a => [a] -> Bool-allEqual []     = True-allEqual (a:as) = all (==a) as---- | @`showSeq` open strs close@:------ Shows the strings @strs@ separated by commas and enclosed within the @open@--- and @close@ strings.-showSeq :: String -> [String] -> String -> String-showSeq open strs close = open ++ intercalate "," strs ++ close---- | Append the first argument to the first line of the second argument.-appendFirstLine :: String -> String -> String-appendFirstLine extra str = str1 ++ extra ++ str2-  where-    (str1,str2) = break (=='\n') str------ | A 'Map' lookup that treats undefined keys as mapping to empty lists.-(!!!) :: Ord a => Map a [b] -> a -> [b]-m !!! a = case Map.lookup a m of-    Just as -> as-    _       -> []---- | Inverts a 'Map'. The argument map may have several keys mapping to the same--- element, so the inverted map has a list of elements for each key.-invertMap :: (Ord a, Ord b) => Map a b -> Map b [a]-invertMap m = Map.fromListWith (++) [(b,[a]) | (a,b) <- Map.toList m]------ | Topological sort. Lists the nodes in the map such that each node appears--- before its children. The function only terminates for acyclic maps.-topSort :: Ord a => Map a [a] -> [a]-topSort = reverse . evalState sorter-  where-    findLeaf a = do-      dag <- get-      let bs = [b | b <- dag Map.! a, Just _ <- [Map.lookup b dag]]-      case bs of-        []  -> modify (Map.delete a) >> return a-        b:_ -> findLeaf b--    sorter = do-        dag <- get-        if Map.null dag-           then return []-           else do-             let (a,_) = Map.elemAt 0 dag-             leaf <- findLeaf a-             liftM (leaf:) sorter--  -- XXX It might be slightly inefficient to always restart findLeaf at the-  --     first element (which can be considered a random node in the dag). It-  --     would probably be better to restart at the parent of the last leaf.--  -- XXX QuickCheck?-
Feldspar/Vector.hs view
@@ -1,62 +1,17 @@------ Copyright (c) 2009-2010, ERICSSON AB All rights reserved.--- --- Redistribution and use in source and binary forms, with or without--- modification, are permitted provided that the following conditions are met:--- ---     * Redistributions of source code must retain the above copyright notice,---       this list of conditions and the following disclaimer.---     * 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 name of the ERICSSON AB nor the names of its contributors---       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 AND CONTRIBUTORS "AS IS"--- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE--- IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE--- ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS--- BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,--- OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF--- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS--- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN--- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)--- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF--- THE POSSIBILITY OF SUCH DAMAGE.---+{-# LANGUAGE UndecidableInstances #-} --- | A high-level interface to the operations in the core language--- ("Feldspar.Core"). Many of the functions defined here are imitations of--- Haskell's list operations, and to a first approximation they behave--- accordingly.------ A symbolic vector ('Vector') can be thought of as a representation of a--- 'parallel' core array. This view is made precise by the function--- 'freezeVector', which converts a symbolic vector to a core vector using--- 'parallel'.------ 'Vector' is instantiated under the 'Computable' class, which means that--- symbolic vectors can be used quite seamlessly with the interface in--- "Feldspar.Core".------ Unlike core arrays vectors don't use any physical memory. All--- operations on vectors are \"fused\" which means that intermediate vectors--- are removed. As an example, the following function uses only constant--- space despite using two intermediate vectors of length @n@.------ > sumSq n = sum (map (^2) (1...n))+-- | A module for /virtual vectors/. Many of the functions defined here are+-- imitations of Haskell's list operations, and to a first approximation they+-- behave accordingly. ----- Memory is only introduced when a vector is explicitly--- written to memory using the function 'memorize' or converted to a core--- array using 'freezeVector'. The function 'vector' for creating a--- vector also allocates memory.+-- A virtual vector normally doesn't use any physical memory. Memory is only+-- introduced explicitly using the function 'force' or converted to a core array+-- using 'freezeVector'. The function 'vector' for creating a vector also+-- allocates memory. -- -- Note also that most operations only introduce a small constant overhead on -- the vector. The exceptions are -----   * 'dropWhile'--- --   * 'fold' -- --   * 'fold1'@@ -69,9 +24,7 @@ -- vector. -- -- Finally, note that 'freezeVector' can be introduced implicitly by functions--- overloaded by the 'Computable' class. This means that, for example,--- @`printCore` f@, where @f :: Vector (Data Int) -> Vector (Data Int)@, will--- introduce storage for the input and output of @f@.+-- overloaded by the 'Syntactic' class.  module Feldspar.Vector where @@ -79,25 +32,26 @@  import qualified Prelude import Control.Arrow ((&&&))-import qualified Data.List  -- Only for documentation of 'unfold'+import Data.List (genericLength)+import qualified Data.TypeLevel as TL +import Feldspar.DSL.Network hiding (In,Out) import Feldspar.Prelude-import Feldspar.Range-import Feldspar.Core.Expr+import Feldspar.Core.Representation import Feldspar.Core    -- * Types --- | Vector index-type Ix = Int- -- | Symbolic vector-data Vector a = Indexed-  { length :: Data Length-  , index  :: Data Ix -> a-  }+data Vector a+    = Empty+    | Indexed+        { segmentLength :: Data Length+        , segmentIndex  :: Data Index -> a+        , continuation  :: Vector a+        }  -- | Short-hand for non-nested parallel vector type DVector a = Vector (Data a)@@ -106,113 +60,118 @@  -- * Construction/conversion --- | Converts a non-nested vector to a core vector.-freezeVector :: Storable a => Vector (Data a) -> Data [a]-freezeVector (Indexed l ixf) = parallel l ixf---- | Converts a non-nested core vector to a parallel vector.-unfreezeVector :: Storable a => Data Length -> Data [a] -> Vector (Data a)-unfreezeVector l arr = Indexed l (getIx arr)+indexed :: Data Length -> (Data Index -> a) -> Vector a+indexed l idxFun = Indexed l idxFun Empty --- | Optimizes vector lookup by computing all elements and storing them in a--- core array.-memorize :: Storable a => Vector (Data a) -> Vector (Data a)-memorize vec = unfreezeVector (length vec) $ freezeVector vec-  -- XXX Should be generalized to arbitrary dimensions.+-- | Breaks up a segmented vector into a list of single-segment vectors.+segments :: Vector a -> [Vector a]+segments Empty                = []+segments (Indexed l ixf cont) = indexed l ixf : segments cont -indexed :: Data Length -> (Data Ix -> a) -> Vector a-indexed = Indexed+length :: Vector a -> Data Length+length Empty = 0+length vec   = Prelude.foldr (+) 0 $ Prelude.map segmentLength $ segments vec --- | Constructs a non-nested vector. The elements are stored in a core vector.-vector :: Storable a => [a] -> Vector (Data a)-vector as = unfreezeVector l (value as)+-- | Converts a segmented vector to a vector with a single segment.+mergeSegments :: Syntactic a => Vector a -> Vector a+mergeSegments vec = indexed (length vec) (ixFun (segments vec))   where-    l = value $ Prelude.length as-  -- XXX Should be generalized to arbitrary dimensions.+    ixFun (Indexed l ixf _ : vs) = case vs of+      [] -> ixf+      _  -> \i -> condition (i<l) (ixf i) (ixFun vs (i-l)) -modifyLength :: (Data Length -> Data Length) -> Vector a -> Vector a-modifyLength f vec = vec {length = f (length vec)}+-- | Converts a non-nested vector to a core vector.+freezeVector :: Type a => Vector (Data a) -> Data [a]+freezeVector vec = help True vec+  where+    help _   Empty                = value []+    help opt (Indexed l ixf cont) = parallel'' opt l ixf $ help False cont -setLength :: Data Length -> Vector a -> Vector a-setLength = modifyLength . const+-- | Converts a non-nested core vector to a parallel vector.+unfreezeVector :: Type a => Data [a] -> Vector (Data a)+unfreezeVector arr = indexed (getLength arr) (getIx arr) -boundVector :: Int -> Vector a -> Vector a-boundVector maxLen = modifyLength (cap r)+-- | Variant of `unfreezeVector` with additional static size information.+unfreezeVector' :: (Type a) => Length -> Data [a] -> Vector (Data a)+unfreezeVector' len arr = unfreezeVector $ cap (r :> elemSize) arr   where-    r = negativeRange + singletonRange (fromIntegral maxLen) + 1-      -- XXX fromIntegral might not be needed in future.+    (_ :> elemSize) = dataSize arr+    r = Range len len +-- | Optimizes vector lookup by computing all elements and storing them in a+-- core array.+memorize :: Syntactic (Vector a) => Vector a -> Vector a+memorize = force+{-# DEPRECATED memorize "Please use `force` instead." #-} +-- | Constructs a non-nested vector. The elements are stored in a core vector.+vector :: Type a => [a] -> Vector (Data a)+vector as = unfreezeVector (value as)+  -- TODO Generalize to arbitrary dimensions. -instance Storable a => Computable (Vector (Data a))+instance+    ( Syntactic a+    , Role a ~ ()+    , Info a ~ EdgeSize () (Internal a)+    ) => EdgeInfo (Vector a)   where-    type Internal (Vector (Data a)) = (Length, [Internal (Data a)])--    internalize vec =-      internalize (length vec, freezeVector $ map internalize vec)--    externalize l_a = map externalize $ unfreezeVector l a-      where-        l = externalize $ get21 l_a-        a = externalize $ get22 l_a+    type Info (Vector a) = EdgeSize () [Internal a]+    edgeInfo             = edgeInfo . toEdge -instance Storable a => Computable (Vector (Vector (Data a)))+instance+    ( Syntactic a+    , Role a ~ ()+    , Info a ~ EdgeSize () (Internal a)+    ) =>+    MultiEdge (Vector a) Feldspar EdgeSize   where-    type Internal (Vector (Vector (Data a))) =-           (Length, [Length], [[Internal (Data a)]])+    type Role     (Vector a) = ()+    type Internal (Vector a) = [Internal a] -    internalize vec = internalize-      ( length vec-      , freezeVector $ map length vec-      , freezeVector $ map (freezeVector . map internalize) vec-      )+    toEdge           = toEdge . freezeVector . map edgeCast+    fromInEdge       = map edgeCast . unfreezeVector . fromInEdge+    fromOutEdge info = map edgeCast . unfreezeVector . fromOutEdge info -    externalize inp-        = map (map externalize . uncurry unfreezeVector)-        $ zip l2sV (unfreezeVector l1 a)-      where-        l1   = externalize $ get31 inp-        l2s  = externalize $ get32 inp-        a    = externalize $ get33 inp-        l2sV = unfreezeVector l1 l2s+instance (Syntactic a, Role a ~ (), Info a ~ EdgeSize () (Internal a)) =>+    Syntactic (Vector a)    -- * Operations -instance RandomAccess (Vector a)+instance Syntactic a => RandomAccess (Vector a)   where     type Element (Vector a) = a-    (!) = index--+    (!) = segmentIndex . mergeSegments --- | Introduces an 'ifThenElse' for each element; use with care!-(++) :: Computable a => Vector a -> Vector a -> Vector a-Indexed l1 ixf1 ++ Indexed l2 ixf2 = Indexed (l1+l2) ixf-  where-    ixf i = ifThenElse (i < l1) ixf1 (ixf2 . subtract l1) i+(++) :: Vector a -> Vector a -> Vector a+Empty              ++ v     = v+v                  ++ Empty = v+Indexed l ixf cont ++ v     = Indexed l ixf (cont ++ v)  infixr 5 ++ -take :: Data Int -> Vector a -> Vector a-take n (Indexed l ixf) = Indexed (min n l) ixf--drop :: Data Int -> Vector a -> Vector a-drop n (Indexed l ixf) = Indexed (max 0 (l-n)) (\x -> ixf (x+n))+take :: Data Length -> Vector a -> Vector a+take _ Empty                = Empty+take n (Indexed l ixf cont) = indexed nHead ixf ++ take nCont cont+  where+    nHead = n<l ? (n,l)+    nCont = n<l ? (0,n-l) -dropWhile :: (a -> Data Bool) -> Vector a -> Vector a-dropWhile cont vec = drop i vec+drop :: Data Length -> Vector a -> Vector a+drop _ Empty = Empty+drop n (Indexed l ixf cont) = indexed nHead (ixf . (+n)) ++ drop nCont cont   where-    i = while ((< length vec) &&* (cont . (vec !))) (+1) 0+    nHead = n > l ? (0,l-n)+    nCont = l > n ? (0,n-l) -splitAt :: Data Int -> Vector a -> (Vector a, Vector a)+splitAt :: Data Index -> Vector a -> (Vector a, Vector a) splitAt n vec = (take n vec, drop n vec) -head :: Vector a -> a+head :: Syntactic a => Vector a -> a head = (!0) -last :: Vector a -> a+last :: Syntactic a => Vector a -> a last vec = vec ! (length vec - 1)  tail :: Vector a -> Vector a@@ -222,49 +181,81 @@ init vec = take (length vec - 1) vec  tails :: Vector a -> Vector (Vector a)-tails vec = Indexed (length vec + 1) (\n -> drop n vec)+tails vec = indexed (length vec + 1) (\n -> drop n vec)  inits :: Vector a -> Vector (Vector a)-inits vec = Indexed (length vec + 1) (\n -> take n vec)+inits vec = indexed (length vec + 1) (\n -> take n vec)  inits1 :: Vector a -> Vector (Vector a) inits1 = tail . inits -permute :: (Data Length -> Data Ix -> Data Ix) -> (Vector a -> Vector a)-permute perm (Indexed l ixf) = Indexed l (ixf . perm l)+-- | Permute a single-segment vector+permute' :: (Data Length -> Data Index -> Data Index) -> (Vector a -> Vector a)+permute' _    Empty                 = Empty+permute' perm (Indexed l ixf Empty) = indexed l (ixf . perm l) -reverse :: Vector a -> Vector a+-- | Permute a vector+permute :: Syntactic a =>+    (Data Length -> Data Index -> Data Index) -> (Vector a -> Vector a)+permute perm = permute' perm . mergeSegments++reverse :: Syntactic a => Vector a -> Vector a reverse = permute $ \l i -> l-1-i+  -- TODO Can be optimized (reversing each segment separately, and then+  --      reversing the segment order) -replicate :: Data Int -> a -> Vector a-replicate n a = Indexed n (const a)+rotateVecL :: Syntactic a => Data Index -> Vector a -> Vector a+rotateVecL ix = permute $ \l i -> (i + ix) `rem` l -enumFromTo :: Data Int -> Data Int -> Vector (Data Int)-enumFromTo m n = Indexed (n-m+1) (+m)-  -- XXX Type should be generalized.+rotateVecR :: Syntactic a => Data Index -> Vector a -> Vector a+rotateVecR ix = reverse . rotateVecL ix . reverse -(...) :: Data Int -> Data Int -> Vector (Data Int)-(...) = enumFromTo+replicate :: Data Length -> a -> Vector a+replicate n a = Indexed n (const a) Empty -zip :: Vector a -> Vector b -> Vector (a,b)-zip (Indexed l1 ixf1) (Indexed l2 ixf2) = Indexed (min l1 l2) (ixf1 &&& ixf2)+enumFromTo :: Data Index -> Data Index -> Vector (Data Index)+enumFromTo m n = indexed l (+m)+  where+    l = n<m ? (0, n-m+1)+  -- TODO Type should be generalized. -unzip :: Vector (a,b) -> (Vector a, Vector b)-unzip (Indexed l ixf) = (Indexed l (fst.ixf), Indexed l (snd.ixf))+(...) :: Data Index -> Data Index -> Vector (Data Index)+(...) = enumFromTo  map :: (a -> b) -> Vector a -> Vector b-map f (Indexed l ixf) = Indexed l (f . ixf)+map _ Empty = Empty+map f (Indexed l ixf cont) = Indexed l (f . ixf) $ map f cont -zipWith :: (a -> b -> c) -> Vector a -> Vector b -> Vector c+-- | Zipping a single-segment vector+zip' :: Vector a -> Vector b -> Vector (a,b)+zip' Empty _ = Empty+zip' _ Empty = Empty+zip' (Indexed l1 ixf1 Empty) (Indexed l2 ixf2 Empty) =+    indexed (min l1 l2) (ixf1 &&& ixf2)++zip :: (Syntactic a, Syntactic b) => Vector a -> Vector b -> Vector (a,b)+zip vec1 vec2 = zip' (mergeSegments vec1) (mergeSegments vec2)++unzip :: Vector (a,b) -> (Vector a, Vector b)+unzip Empty = (Empty, Empty)+unzip (Indexed l ixf cont) =+    (Indexed l (fst.ixf) cont1, Indexed l (snd.ixf) cont2)+  where+    (cont1,cont2) = unzip cont++zipWith :: (Syntactic a, Syntactic b) =>+    (a -> b -> c) -> Vector a -> Vector b -> Vector c zipWith f aVec bVec = map (uncurry f) $ zip aVec bVec --- | Corresponds to 'foldl'.-fold :: Computable a => (a -> b -> a) -> a -> Vector b -> a-fold f x (Indexed l ixf) = for 0 (l-1) x (\i s -> f s (ixf i))+-- | Corresponds to the standard 'foldl'.+fold :: Syntactic a => (a -> b -> a) -> a -> Vector b -> a+fold _ x Empty = x+fold f x (Indexed l ixf cont) =+    fold f (forLoop l x $ \ix s -> f s (ixf ix)) cont --- | Corresponds to 'foldl1'.-fold1 :: Computable a => (a -> a -> a) -> Vector a -> a-fold1 f a = fold f (head a) a+-- | Corresponds to the standard 'foldl1'.+fold1 :: Type a => (Data a -> Data a -> Data a) -> Vector (Data a) -> Data a+fold1 f a = fold f (head a) (tail a)  sum :: Numeric a => Vector (Data a) -> Data a sum = fold (+) 0@@ -279,3 +270,11 @@ scalarProd :: Numeric a => Vector (Data a) -> Vector (Data a) -> Data a scalarProd a b = sum (zipWith (*) a b) +-- * Wrapping for vectors++instance (Type a) => Wrap (Vector (Data a)) (Data [a]) where+    wrap v = freezeVector v++instance (Wrap t u, Type a, TL.Nat s) => Wrap (DVector a -> t) (Data' s [a] -> u) where+    wrap f = \(Data' d) -> wrap $ f $ unfreezeVector' s' d where+        s' = fromInteger $ toInteger $ TL.toInt (undefined :: s)
LICENSE view
@@ -1,4 +1,4 @@-Copyright (c) 2009-2010, ERICSSON AB+Copyright (c) 2009-2011, ERICSSON AB All rights reserved.  Redistribution and use in source and binary forms, with or without
Setup.hs view
@@ -1,31 +1,3 @@------ Copyright (c) 2009-2010, ERICSSON AB All rights reserved.--- --- Redistribution and use in source and binary forms, with or without--- modification, are permitted provided that the following conditions are met:--- ---     * Redistributions of source code must retain the above copyright notice,---       this list of conditions and the following disclaimer.---     * 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 name of the ERICSSON AB nor the names of its contributors---       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 AND CONTRIBUTORS "AS IS"--- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE--- IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE--- ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS--- BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,--- OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF--- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS--- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN--- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)--- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF--- THE POSSIBILITY OF SUCH DAMAGE.---- import Distribution.Simple  main = defaultMain
− examples/Memocode2010.hs
@@ -1,228 +0,0 @@-import qualified Prelude-import Feldspar hiding (cos, cycle)-import Feldspar.Stream (Stream, recurrenceI, cycle)-import qualified Feldspar.Stream as S-import Feldspar.Compiler--------------------------------------------------------- Missing functions------ These ad hoc functions are for various reasons--- not directly included in Feldspar.------------------------------------------------------- Will appear as a call to "intToFloat" in the generated code.-intToFloat :: Data Int -> Data Float-intToFloat = function "intToFloat" (\_ -> universal) (fromInteger.toInteger)---- Will appear as a call to "cos" in the generated code.-cos :: Data Float -> Data Float-cos = function "cos" (\_ -> universal) Prelude.cos--toList :: Int -> Vector (Data a) -> [Data a]-toList n v@(Indexed l ix) = Prelude.map (v!) (Prelude.map value [0..n-1])---- This function generates very inefficient code.-fromList :: Storable a => [Data a] -> Vector (Data a)-fromList ls = unfreezeVector (value len)-    (loop 1 (parallel (value len) (const (Prelude.head ls))))-  where loop i arr-            | i Prelude.< len = loop (i+1) (setIx arr (value i) (ls !! i))-            | otherwise = arr-        len = Prelude.length ls--------------------------------------------------------- Examples-----------------------------------------------------square :: Data Int -> Data Int-square x = x*x--sumSq :: Data Int -> Data Int-sumSq n = (sum . map square) (1...n)---- Convolver-conv1D :: DVector Float -> DVector Float -> DVector Float-conv1D kernel = map (scalarProd kernel . reverse) . inits1--modulus :: Data Int -> Data Int -> Data Int-modulus a b = while (>=b) (subtract b) a--powersOfTwo :: Data [Int]-powersOfTwo = parallel 8 (\i -> 2^i)--------------------------------------------------------- Discrete cosine transform-----------------------------------------------------dct2 :: DVector Float -> DVector Float-dct2 xn = mat ** xn-    where-      mat = indexedMat (length xn) (length xn)-              (\k l -> dct2nkl (length xn) k l)--dct2nkl :: Data Int -> Data Int -> Data Int -> Data Float-dct2nkl n k l = cos ( (k' * (2*l' + 1)*3.14)/(2*n') )-  where-    (n',k',l') = (intToFloat n, intToFloat k, intToFloat l)--------------------------------------------------------- Sorter-----------------------------------------------------minP :: (Storable a, Ord a) => Data a -> Data a -> Data a-minP = function2 "min" (\_ _ -> universal) Prelude.min--maxP :: (Storable a, Ord a) => Data a -> Data a -> Data a-maxP = function2 "max" (\_ _ -> universal) Prelude.max--comp :: (Storable a, Ord a) => (Data a,Data  a) -> (Data a, Data a)-comp (a,b) = (min a b, max a b)--cswap :: Data [Int] -> (Data Int, Data Int) -> Data [Int]-cswap as (l,r) = setIx (setIx as r mx) l mn-  where-    (mn,mx) = comp (as!l,as!r)--ones k = 2^k-1---- j ones, shifted k bits to the left-onesZeros :: Data Int -> Data Int -> Data Int-onesZeros j k = shiftL (ones j) k--allones = 2^31-1---- zero out rightmost i bits of k-zeroBitsR :: Data Int -> Data Int -> Data Int-zeroBitsR i k =  k .&. (shiftL allones i)---- shifts bits j and upwards leftwards one and sets bit j to zero-setBitAndShift :: Data Int -> Data Int -> Data Int-setBitAndShift j k = k + (zeroBitsR j k)--swapsT n = indexed (n+1) (\j -> (indexed (j+1) (\k -> swapcol n (n-j) (j-k))))--swapcol n i v = indexed (2^n) (\k -> g (setBitAndShift (i+v) k))-  where-    g k = (k, xor (onesZeros (v+1) i) k)--sort0 :: Data Length -> Data [Int] -> Data [Int]-sort0 n as = fold (fold (fold cswap)) as (swapsT n)--------------------------------------------------------- Blake-----------------------------------------------------type MessageBlock = DVector Unsigned32 -- 0..15-type Round = Data Int-type State = Matrix Unsigned32 -- 0..3 0..3--co :: DVector Unsigned32-co = vector [0x243F6A88,0x85A308D3,0x13198A2E,0x03707344,-             0xA4093822,0x299F31D0,0x082EFA98,0xEC4E6C89,-             0x452821E6,0x38D01377,0xBE5466CF,0x34E90C6C,-             0xC0AC29B7,0xC97C50DD,0x3F84D5B5,0xB5470917]--sigma :: Matrix Int-sigma = matrix-      [[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15]-      ,[14,10,4,8,9,15,13,6,1,12,0,2,11,7,5,3]-      ,[11,8,12,0,5,2,15,13,10,14,3,6,7,1,9,4]-      ,[7,9,3,1,13,12,11,14,2,6,5,10,4,0,15,8]-      ,[9,0,5,7,2,4,10,15,14,1,11,12,6,8,3,13]-      ,[2,12,6,10,0,11,8,3,4,13,7,5,15,14,1,9]-      ,[12,5,1,15,14,13,4,10,0,7,6,3,9,2,8,11]-      ,[13,11,7,14,12,1,3,9,5,0,15,4,8,6,2,10]-      ,[6,15,14,9,11,3,0,8,12,2,13,7,1,4,10,5]-      ,[10,2,8,4,7,6,1,5,15,11,9,14,3,12,13,0]-      ]--diagonals :: Matrix a -> Matrix a-diagonals m = map (diag m) (0 ... (length (head m) - 1))---- Return the i'th diagonal-diag :: Matrix a -> Data Int -> Vector (Data a)-diag m i = zipWith lookup m (i ... (l + i))-  where l = length m - 1-        lookup v i = v ! (i `mod` length v)--invDiagonals :: Storable a => Matrix a -> Matrix a-invDiagonals m = zipWith shiftVectorR (0 ... (length m - 1)) (transpose m)--shiftVectorR :: Computable a => Data Int -> Vector a -> Vector a-shiftVectorR i v = reverse (drop i rev ++ take i rev)-  where rev = reverse v--blakeRound :: MessageBlock -> State -> Round -> State-blakeRound m state r =- (invDiagonals .-  zipWith (g m r) (4 ... 7) .-  diagonals .-  transpose .-  zipWith (g m r) (0 ... 3) .-  transpose)-  state--g :: MessageBlock -> Round -> Data Int-  -> DVector Unsigned32 -> DVector Unsigned32-g m r i v = fromList [a'',b'',c'',d'']-  where [a,b,c,d] = toList 4 v-        a' = a + b +-             (m!(sigma!r!(2*i)) ⊕ (co!(sigma!r!(2*i+1))))-        d' = (d ⊕ a') >> 16-        c' = c + d'-        b' = (b ⊕ c') >> 12-        a'' = a' + b' +-              (m!(sigma!r!(2*i+1)) ⊕ (co!(sigma!r!(2*i))))-        d'' = (d' ⊕ a'') >> 8-        c'' = c' + d''-        b'' = (b' ⊕ c'') >> 7--------------------------------------------------------- Streams------------------------------------------------------- IIR filter-iir :: Data Float -> DVector Float -> DVector Float-    -> Stream (Data Float) -> Stream (Data Float)-iir a0 a b input =-    recurrenceI (replicate q 0) input-                (replicate p 0)-      (\x y -> 1 / a0 *-          ( sum (indexed p (\i -> b!i * x!(p-i)))-          - sum (indexed q (\j -> a!j * y!(q-j))))-      )-  where p  = length b-        q  = length a--------------------------------------------------------- Tests-----------------------------------------------------test1 = eval (sumSq 10)-test2 = printCore sumSq-test3 = icompile' sumSq "sumSq" defaultOptions-test4 = printCore conv1D-test5 = eval (modulus 22 6)-test6 = eval powersOfTwo-test7 = printCore dct2-test8 = printCore sort0-test9 = printCore iirVec-  where-    -- Wrapper code to make it operate on vectors-    iirVec a0 a b = S.take 100 . iir a0 a b . cycle-
feldspar-language.cabal view
@@ -1,12 +1,12 @@ name:           feldspar-language-version:        0.3.3+version:        0.4.0.2 synopsis:       A functional embedded language for DSP and parallelism description:    Feldspar (Functional Embedded Language for DSP and PARallelism)                 is an embedded DSL for describing digital signal processing                 algorithms. This package contains the language front-end and an                 interpreter. category:       Language-copyright:      Copyright (c) 2009-2010, ERICSSON AB+copyright:      Copyright (c) 2009-2011, ERICSSON AB author:         Functional programming group at Chalmers University of Technology maintainer:     Emil Axelsson <emax@chalmers.se> license:        BSD3@@ -15,50 +15,73 @@ homepage:       http://feldspar.inf.elte.hu/feldspar/ build-type:     Simple cabal-version:  >= 1.6-tested-with:    GHC==6.10.*+tested-with:    GHC==6.12.*, GHC==7.0.2 -data-files:-  examples/Memocode2010.hs+extra-source-files:+  Examples/Tutorial/*.hs,+  Examples/Simple/*.hs,+  Examples/Effects/*.hs,+  Examples/Math/*.hs  library   exposed-modules:     Feldspar.Prelude-    Feldspar.Utils-    Feldspar.Haskell+    Feldspar.DSL.Expression+    Feldspar.DSL.Lambda+    Feldspar.DSL.Sharing+    Feldspar.DSL.Val+    Feldspar.DSL.Network+    Feldspar.Set     Feldspar.Range     Feldspar.Core.Types-    Feldspar.Core.Ref-    Feldspar.Core.Expr-    Feldspar.Core.Graph-    Feldspar.Core.Show-    Feldspar.Core.Reify+    Feldspar.Core.Representation+    Feldspar.Core.Constructs+    Feldspar.Core.Functions.Logic+    Feldspar.Core.Functions.Eq+    Feldspar.Core.Functions.Ord+    Feldspar.Core.Functions.Num+    Feldspar.Core.Functions.Bits+    Feldspar.Core.Functions.Integral+    Feldspar.Core.Functions.Fractional+    Feldspar.Core.Functions.Floating+    Feldspar.Core.Functions.Complex+    Feldspar.Core.Functions.Tuple+    Feldspar.Core.Functions.Array+    Feldspar.Core.Functions.Conversion+    Feldspar.Core.Functions.Trace     Feldspar.Core.Functions-    Feldspar.Core.Trace+    Feldspar.Core.Wrap     Feldspar.Core     Feldspar.Vector     Feldspar.Matrix-    Feldspar.FixedPoint     Feldspar.Stream+    Feldspar.FixedPoint     Feldspar    build-depends:-    base >= 4 && < 4.3,+    array,+    base >= 4 && < 4.4,     containers,     mtl,+    QuickCheck >= 2.4 && < 3,     random,-    QuickCheck >= 2.3 && < 3+    tagged == 0.2.*,+    type-level >= 0.2.4    extensions:+    EmptyDataDecls     FlexibleInstances     FlexibleContexts+    FunctionalDependencies     GADTs+    GeneralizedNewtypeDeriving     MultiParamTypeClasses-    NoMonomorphismRestriction-    OverlappingInstances     PatternGuards     Rank2Types     ScopedTypeVariables+    StandaloneDeriving     TypeFamilies     TypeOperators     TypeSynonymInstances     UndecidableInstances+    DeriveDataTypeable