feldspar-language 0.1 → 0.2
raw patch · 18 files changed
+1898/−1254 lines, 18 filesdep +QuickCheckdep −directorydep −processdep −tfpPVP ok
version bump matches the API change (PVP)
Dependencies added: QuickCheck
Dependencies removed: directory, process, tfp
API changes (from Hackage documentation)
- Feldspar.Core: class (Storable a) => Primitive a
- Feldspar.Core.Expr: GetTuple :: T n -> Data a -> Expr (Part n a)
- Feldspar.Core.Expr: Info :: NodeId -> Map Unique NodeId -> Info
- Feldspar.Core.Expr: buildGraph :: Data a -> GraphBuilder ()
- Feldspar.Core.Expr: buildSubFun :: (Typeable a, Typeable b) => (Data a -> Data b) -> GraphBuilder Interface
- Feldspar.Core.Expr: checkNode :: Data a -> GraphBuilder (Maybe NodeId)
- Feldspar.Core.Expr: class Program a
- Feldspar.Core.Expr: data Info
- Feldspar.Core.Expr: deref :: Data a -> Expr a
- Feldspar.Core.Expr: functionFold :: (Storable a, Storable b) => String -> (a -> b) -> (Data a -> Data b)
- Feldspar.Core.Expr: functionFold2 :: (Storable a, Storable b, Storable c) => String -> (a -> b -> c) -> (Data a -> Data b -> Data c)
- Feldspar.Core.Expr: functionFold3 :: (Storable a, Storable b, Storable c, Storable d) => String -> (a -> b -> c -> d) -> (Data a -> Data b -> Data c -> Data d)
- Feldspar.Core.Expr: functionFold4 :: (Storable a, Storable b, Storable c, Storable d, Storable e) => String -> (a -> b -> c -> d -> e) -> (Data a -> Data b -> Data c -> Data d -> Data e)
- Feldspar.Core.Expr: hasArg :: (Program a) => T a -> Bool
- Feldspar.Core.Expr: index :: Info -> NodeId
- Feldspar.Core.Expr: instance [incoherent] (Computable a) => Program a
- Feldspar.Core.Expr: instance [incoherent] (Computable a, Computable b) => Computable (a, b)
- Feldspar.Core.Expr: instance [incoherent] (Computable a, Computable b) => Program (a -> b)
- Feldspar.Core.Expr: instance [incoherent] (Computable a, Computable b, Computable c) => Computable (a, b, c)
- Feldspar.Core.Expr: instance [incoherent] (Computable a, Computable b, Computable c) => Program (a -> b -> c)
- Feldspar.Core.Expr: instance [incoherent] (Computable a, Computable b, Computable c, Computable d) => Computable (a, b, c, d)
- Feldspar.Core.Expr: instance [incoherent] (Computable a, Computable b, Computable c, Computable d) => Program (a -> b -> c -> d)
- Feldspar.Core.Expr: instance [incoherent] (Computable a, Computable b, Computable c, Computable d, Computable e) => Program (a -> b -> c -> d -> e)
- Feldspar.Core.Expr: instance [incoherent] (NaturalT n, Storable a) => RandomAccess (Data (n :> a))
- Feldspar.Core.Expr: instance [incoherent] (Num n, Primitive n) => Num (Data n)
- Feldspar.Core.Expr: instance [incoherent] (Primitive a) => Show (Data a)
- Feldspar.Core.Expr: instance [incoherent] (Storable a) => Computable (Data a)
- Feldspar.Core.Expr: instance [incoherent] Eq (Data a)
- Feldspar.Core.Expr: instance [incoherent] Fractional (Data Float)
- Feldspar.Core.Expr: instance [incoherent] Ord (Data a)
- Feldspar.Core.Expr: newIndex :: GraphBuilder NodeId
- Feldspar.Core.Expr: node :: (Typeable a) => Data a -> Function -> Tuple Source -> Tuple StorableType -> GraphBuilder ()
- Feldspar.Core.Expr: printCore :: (Program a) => a -> IO ()
- Feldspar.Core.Expr: ref :: (Typeable a) => Expr a -> Data a
- Feldspar.Core.Expr: refId :: Data a -> Unique
- Feldspar.Core.Expr: remember :: Data a -> NodeId -> GraphBuilder ()
- Feldspar.Core.Expr: runGraph :: GraphBuilder a -> Info -> (a, ([Node], Info))
- Feldspar.Core.Expr: showCore :: (Program a) => a -> String
- Feldspar.Core.Expr: source :: [Int] -> Data a -> GraphBuilder Source
- Feldspar.Core.Expr: sourceNode :: Data a -> Function -> GraphBuilder ()
- Feldspar.Core.Expr: startInfo :: Info
- Feldspar.Core.Expr: toGraph :: (Program a) => a -> Graph
- Feldspar.Core.Expr: toGraphD :: (Typeable a, Typeable b) => (Data a -> Data b) -> Graph
- Feldspar.Core.Expr: traceTuple :: Data a -> GraphBuilder (Tuple Source)
- Feldspar.Core.Expr: tupleBind :: (Typeable a) => NodeId -> T a -> Tuple Variable
- Feldspar.Core.Expr: type GraphBuilder a = WriterT [Node] (State Info) a
- Feldspar.Core.Expr: typeOfData :: (Typeable a) => Data a -> Tuple StorableType
- Feldspar.Core.Expr: unwrap :: (Computable a, Computable b) => (Data (Internal a) -> Data (Internal b)) -> (a -> b)
- Feldspar.Core.Expr: value_ :: (Storable a) => a -> Data a
- Feldspar.Core.Expr: visited :: Info -> Map Unique NodeId
- Feldspar.Core.Expr: wrap :: (Computable a, Computable b) => (a -> b) -> (Data (Internal a) -> Data (Internal b))
- Feldspar.Core.Haskell: (-$-) :: (HaskellValue a) => String -> a -> String
- Feldspar.Core.Haskell: (-=-) :: (HaskellValue patt, HaskellValue def) => patt -> def -> String
- Feldspar.Core.Haskell: ifThenElse :: (HaskellValue c, HaskellValue t, HaskellValue e) => c -> t -> e -> String
- Feldspar.Core.Haskell: indent :: Int -> String -> String
- Feldspar.Core.Haskell: local :: String -> String -> String
- Feldspar.Core.Haskell: newline :: String
- Feldspar.Core.Haskell: opApp :: (HaskellValue a, HaskellValue b) => String -> a -> b -> String
- Feldspar.Core.Haskell: unlinesNoTrail :: [String] -> String
- Feldspar.Core.Types: ArrayList :: [a] -> :> n a
- Feldspar.Core.Types: class (NaturalT n) => GetTuple n a where { type family Part n a; }
- Feldspar.Core.Types: class HaskellType a
- Feldspar.Core.Types: class HaskellValue a
- Feldspar.Core.Types: fromList :: (Storable a) => ListBased a -> a
- Feldspar.Core.Types: getTup :: (GetTuple n a) => T n -> a -> Part n a
- Feldspar.Core.Types: haskellType :: (HaskellType a) => a -> String
- Feldspar.Core.Types: haskellValue :: (HaskellValue a) => a -> String
- Feldspar.Core.Types: instance [overlap ok] (NaturalT n, Storable a) => Storable (n :> a)
- Feldspar.Core.Types: instance [overlap ok] (NaturalT n, Storable a) => Typeable (n :> a)
- Feldspar.Core.Types: instance [overlap ok] (NaturalT n, Storable a, Eq a) => Eq (n :> a)
- Feldspar.Core.Types: instance [overlap ok] (NaturalT n, Storable a, Ord a) => Ord (n :> a)
- Feldspar.Core.Types: instance [overlap ok] (NaturalT n, Storable a, Show (ListBased a)) => Show (n :> a)
- Feldspar.Core.Types: instance [overlap ok] GetTuple D0 (a, b)
- Feldspar.Core.Types: instance [overlap ok] GetTuple D0 (a, b, c)
- Feldspar.Core.Types: instance [overlap ok] GetTuple D0 (a, b, c, d)
- Feldspar.Core.Types: instance [overlap ok] GetTuple D1 (a, b)
- Feldspar.Core.Types: instance [overlap ok] GetTuple D1 (a, b, c)
- Feldspar.Core.Types: instance [overlap ok] GetTuple D1 (a, b, c, d)
- Feldspar.Core.Types: instance [overlap ok] GetTuple D2 (a, b, c)
- Feldspar.Core.Types: instance [overlap ok] GetTuple D2 (a, b, c, d)
- Feldspar.Core.Types: instance [overlap ok] GetTuple D3 (a, b, c, d)
- Feldspar.Core.Types: instance [overlap ok] HaskellValue Int
- Feldspar.Core.Types: instance [overlap ok] HaskellValue String
- Feldspar.Core.Types: isPrimitive :: (Typeable a) => T a -> Bool
- Feldspar.Core.Types: isRectangular :: (Storable a) => a -> Bool
- Feldspar.Core.Types: mapArray :: (NaturalT n, Storable a, Storable b) => (a -> b) -> (n :> a) -> (n :> b)
- Feldspar.Core.Types: numberT :: (IntegerT n) => T n -> Int
- Feldspar.Core.Types: replicateArray :: (Storable a) => Element a -> a
- Feldspar.Core.Types: toData :: (Storable a) => a -> StorableData
- Feldspar.Core.Types: toList :: (Storable a) => a -> ListBased a
- Feldspar.Vector: Unfold :: Data Size -> (s -> (a, s)) -> s -> Seq n :>> a
- Feldspar.Vector: class AccessPattern t
- Feldspar.Vector: data (:>>) n a
- Feldspar.Vector: data Par n
- Feldspar.Vector: data Seq n
- Feldspar.Vector: genericVector :: (AccessPattern t) => (Par n :>> a) -> (Seq n :>> a) -> (t n :>> a)
- Feldspar.Vector: instance [overlap ok] (NaturalT n, Storable a, AccessPattern t) => Computable (t n :>> Data a)
- Feldspar.Vector: instance [overlap ok] (NaturalT n1, NaturalT n2, Storable a, AccessPattern t1, AccessPattern t2) => Computable (t1 n1 :>> (t2 n2 :>> Data a))
- Feldspar.Vector: instance [overlap ok] AccessPattern Par
- Feldspar.Vector: instance [overlap ok] AccessPattern Seq
- Feldspar.Vector: instance [overlap ok] RandomAccess (Par n :>> a)
- Feldspar.Vector: resize :: (NaturalT n) => (t m :>> a) -> (t n :>> a)
- Feldspar.Vector: scan1 :: (Computable a) => (a -> a -> a) -> (t n :>> a) -> (Seq n :>> a)
- Feldspar.Vector: toPar :: (NaturalT n, Storable a) => (t n :>> Data a) -> VectorP n a
- Feldspar.Vector: toSeq :: (t n :>> a) -> (Seq n :>> a)
- Feldspar.Vector: type Size = Int
- Feldspar.Vector: type VectorP n a = Par n :>> Data a
- Feldspar.Vector: type VectorS n a = Seq n :>> Data a
+ Feldspar.Core: (:>) :: a -> b -> :> a b
+ Feldspar.Core: Range :: Maybe a -> Maybe a -> Range a
+ Feldspar.Core: arrayLen :: (Storable a) => Data Length -> [a] -> Data [a]
+ Feldspar.Core: cap :: (Storable a, (Size a) ~ (Range b), Ord b) => Range b -> Data a -> Data a
+ Feldspar.Core: class (Num a, Primitive a, Num (Size a)) => Numeric a
+ Feldspar.Core: class Set a
+ Feldspar.Core: data (Ord a) => Range a
+ Feldspar.Core: dataSize :: Data a -> Size a
+ Feldspar.Core: lowerBound :: Range a -> Maybe a
+ Feldspar.Core: printCoreWithSize :: (Program a) => a -> IO ()
+ Feldspar.Core: showCoreWithSize :: (Program a) => a -> String
+ Feldspar.Core: type Length = Int
+ Feldspar.Core: universal :: (Set a) => a
+ Feldspar.Core: upperBound :: Range a -> Maybe a
+ Feldspar.Core.Expr: Get21 :: Data (a, b) -> Expr a
+ Feldspar.Core.Expr: Get22 :: Data (a, b) -> Expr b
+ Feldspar.Core.Expr: Get31 :: Data (a, b, c) -> Expr a
+ Feldspar.Core.Expr: Get32 :: Data (a, b, c) -> Expr b
+ Feldspar.Core.Expr: Get33 :: Data (a, b, c) -> Expr c
+ Feldspar.Core.Expr: Get41 :: Data (a, b, c, d) -> Expr a
+ Feldspar.Core.Expr: Get42 :: Data (a, b, c, d) -> Expr b
+ Feldspar.Core.Expr: Get43 :: Data (a, b, c, d) -> Expr c
+ Feldspar.Core.Expr: Get44 :: Data (a, b, c, d) -> Expr d
+ Feldspar.Core.Expr: SubFunction :: (Data a -> Data b) -> (Data a) -> (Data b) -> :-> a b
+ 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: data (:->) a b
+ Feldspar.Core.Expr: dataId :: Data a -> Unique
+ 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: exprSize :: (Typeable a) => Expr a -> Size a
+ Feldspar.Core.Expr: exprToData :: (Typeable a) => Expr a -> Data a
+ Feldspar.Core.Expr: externalizeE :: (Computable a) => Expr (Internal a) -> a
+ 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] (Numeric a) => Num (Data a)
+ 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] Fractional (Data Float)
+ Feldspar.Core.Expr: instance [overlap ok] Ord (Data a)
+ Feldspar.Core.Expr: instance [overlap ok] Show (Data a)
+ 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: mkSubFun :: (Typeable a) => Size a -> (Data a -> Data b) -> (a :-> b)
+ Feldspar.Core.Expr: subAp :: (a :-> b) -> (Data a -> Data b)
+ Feldspar.Core.Expr: subFunSize :: (a :-> b) -> Size b
+ Feldspar.Core.Expr: whileSized :: (Computable state) => Size (Internal state) -> (state -> Data Bool) -> (state -> state) -> (state -> state)
+ 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 Int -> Data a
+ Feldspar.Core.Functions: (<<<) :: Data Int -> Data Int -> Data Bool
+ Feldspar.Core.Functions: (>>) :: (Bits a) => Data a -> Data Int -> Data a
+ Feldspar.Core.Functions: (>>>) :: Data Int -> Data Int -> Data Bool
+ Feldspar.Core.Functions: (⊕) :: (Bits a) => Data a -> Data a -> Data a
+ Feldspar.Core.Functions: bit :: (Bits a) => Data Int -> Data a
+ Feldspar.Core.Functions: bitSize :: (Bits a) => Data a -> Data Int
+ Feldspar.Core.Functions: class (Bits a, Storable a) => Bits a
+ Feldspar.Core.Functions: clearBit :: (Bits a) => Data a -> Data Int -> 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: instance [overlap ok] Bits Int
+ Feldspar.Core.Functions: isSigned :: (Bits a) => Data a -> Data Bool
+ Feldspar.Core.Functions: maxX :: Data Int -> Data Int -> Data Int
+ Feldspar.Core.Functions: minX :: Data Int -> Data Int -> Data Int
+ Feldspar.Core.Functions: noSizeProp :: a -> ()
+ Feldspar.Core.Functions: noSizeProp2 :: a -> b -> ()
+ Feldspar.Core.Functions: rotateL :: (Bits a) => Data a -> Data Int -> Data a
+ Feldspar.Core.Functions: rotateR :: (Bits a) => Data a -> Data Int -> Data a
+ Feldspar.Core.Functions: setBit :: (Bits a) => Data a -> Data Int -> Data a
+ Feldspar.Core.Functions: shiftL :: (Bits a) => Data a -> Data Int -> Data a
+ Feldspar.Core.Functions: shiftR :: (Bits a) => Data a -> Data Int -> Data a
+ Feldspar.Core.Functions: testBit :: (Bits a) => Data a -> Data Int -> Data Bool
+ Feldspar.Core.Functions: unfoldCore :: (Computable state, Storable a) => Data Length -> state -> (Data Int -> state -> (Data a, state)) -> (Data [a], state)
+ Feldspar.Core.Functions: xor :: (Bits a) => Data a -> Data a -> Data a
+ 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: 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: showCore :: (Program a) => a -> String
+ Feldspar.Core.Reify: showCoreWithSize :: (Program a) => a -> String
+ Feldspar.Core.Show: sizeComment :: Tuple StorableType -> String
+ Feldspar.Core.Types: (:>) :: a -> b -> :> a b
+ Feldspar.Core.Types: bitSize :: PrimitiveType -> Int
+ Feldspar.Core.Types: class (Num a, Primitive a, Num (Size a)) => Numeric a
+ Feldspar.Core.Types: class Set a
+ Feldspar.Core.Types: instance [overlap ok] (Eq a, Eq b) => Eq (a :> b)
+ 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 b) => Show (a :> b)
+ 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] Numeric Float
+ Feldspar.Core.Types: instance [overlap ok] Numeric Int
+ Feldspar.Core.Types: instance [overlap ok] Set ()
+ Feldspar.Core.Types: listSize :: (Storable a) => T a -> Size a -> [Range Length]
+ Feldspar.Core.Types: mkT :: a -> T a
+ Feldspar.Core.Types: primitiveData :: (Primitive a) => a -> PrimitiveData
+ Feldspar.Core.Types: primitiveType :: (Primitive a) => Size a -> T a -> PrimitiveType
+ Feldspar.Core.Types: showStorableSize :: StorableType -> 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: type Length = Int
+ 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.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.Range: (/\) :: (Ord a) => Range a -> Range a -> Range a
+ Feldspar.Range: (\/) :: (Ord a) => Range a -> Range a -> Range a
+ Feldspar.Range: Range :: Maybe a -> Maybe a -> Range a
+ Feldspar.Range: data (Ord a) => Range a
+ Feldspar.Range: disjoint :: (Ord a, Num a) => Range a -> Range a -> Bool
+ Feldspar.Range: emptyRange :: (Ord a, Num a) => Range a
+ Feldspar.Range: fullRange :: (Ord a) => Range a
+ Feldspar.Range: inRange :: (Ord a) => a -> Range a -> Bool
+ 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: isBounded :: (Ord a) => Range a -> Bool
+ Feldspar.Range: isEmpty :: (Ord a) => Range a -> Bool
+ Feldspar.Range: isFull :: (Ord a) => Range a -> Bool
+ Feldspar.Range: isNatural :: (Ord a, Num a) => Range a -> Bool
+ Feldspar.Range: isNegative :: (Ord a, Num a) => Range a -> Bool
+ Feldspar.Range: isSingleton :: (Ord a) => Range a -> Bool
+ Feldspar.Range: isSubRangeOf :: (Ord a) => Range a -> Range a -> Bool
+ Feldspar.Range: liftMaybe2 :: (a -> a -> a) -> Maybe a -> Maybe a -> Maybe a
+ Feldspar.Range: lowerBound :: Range a -> Maybe a
+ Feldspar.Range: mapMonotonic :: (Ord a, Ord b) => (a -> b) -> Range a -> Range b
+ Feldspar.Range: naturalRange :: (Ord a, Num a) => Range a
+ Feldspar.Range: negativeRange :: (Ord a, Num a) => Range a
+ Feldspar.Range: prop_arith1 :: (forall a. (Num a) => a -> a) -> Int -> Range Int -> Property
+ Feldspar.Range: prop_arith2 :: (forall a. (Num a) => a -> a -> a) -> Int -> Int -> Range Int -> Range Int -> Property
+ Feldspar.Range: range :: (Ord a) => a -> a -> Range a
+ Feldspar.Range: rangeByRange :: (Ord a) => Range a -> Range a -> Range a
+ Feldspar.Range: rangeGap :: (Ord a, Num a) => Range a -> Range a -> Range a
+ Feldspar.Range: rangeLess :: (Ord a) => Range a -> Range a -> Bool
+ Feldspar.Range: rangeLessEq :: (Ord a) => Range a -> Range a -> Bool
+ Feldspar.Range: rangeMul :: (Ord a, Num a) => Range a -> Range a -> Range a
+ Feldspar.Range: rangeOp :: (Ord 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: rangeSize :: (Ord a, Num a) => Range a -> Maybe a
+ Feldspar.Range: showBound :: (Show a) => Maybe a -> String
+ Feldspar.Range: showRange :: (Show a, Ord a) => Range a -> String
+ Feldspar.Range: singletonRange :: (Ord a) => a -> Range a
+ Feldspar.Range: upperBound :: Range a -> Maybe a
+ Feldspar.Utils: appendFirstLine :: String -> String -> String
+ Feldspar.Vector: (...) :: Data Int -> Data Int -> Vector (Data Int)
+ Feldspar.Vector: boundVector :: Int -> Vector a -> Vector a
+ Feldspar.Vector: data Vector a
+ Feldspar.Vector: inits1 :: Vector a -> Vector (Vector 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: mapAccum :: (Storable a, Computable acc, Storable b) => (acc -> Data a -> (acc, Data b)) -> acc -> Vector (Data a) -> (acc, Vector (Data b))
+ Feldspar.Vector: memorize :: (Storable a) => Vector (Data a) -> Vector (Data a)
+ Feldspar.Vector: modifyLength :: (Data Length -> Data Length) -> Vector a -> Vector a
+ Feldspar.Vector: setLength :: Data Length -> Vector a -> Vector a
+ Feldspar.Vector: type DVector a = Vector (Data a)
+ Feldspar.Vector: unfoldVec :: (Computable state, Storable a) => Data Length -> state -> (Data Int -> state -> (Data a, state)) -> (Vector (Data a), state)
- Feldspar.Core: (!) :: (RandomAccess a) => a -> Data Int -> Elem a
+ Feldspar.Core: (!) :: (RandomAccess a) => a -> Data Int -> Element a
- Feldspar.Core: array :: (NaturalT n, Storable a) => ListBased (n :> a) -> Data (n :> a)
+ Feldspar.Core: array :: (Storable a) => Size a -> a -> Data a
- Feldspar.Core: class RandomAccess a where { type family Elem a; }
+ Feldspar.Core: class RandomAccess a where { type family Element a; }
- Feldspar.Core: class (Typeable a) => Storable a where { type family ListBased a :: *; }
+ Feldspar.Core: class (Typeable a) => Storable a
- Feldspar.Core: data (:>) n a
+ Feldspar.Core: data (:>) a b
- Feldspar.Core: getIx :: (NaturalT n, Storable a) => Data (n :> a) -> Data Int -> Data a
+ Feldspar.Core: getIx :: (Storable a) => Data [a] -> Data Int -> Data a
- Feldspar.Core: parallel :: (NaturalT n, Storable a) => Data Int -> (Data Int -> Data a) -> Data (n :> a)
+ Feldspar.Core: parallel :: (Storable a) => Data Length -> (Data Int -> Data a) -> Data [a]
- Feldspar.Core: setIx :: (NaturalT n, Storable a) => Data (n :> a) -> Data Int -> Data a -> Data (n :> a)
+ Feldspar.Core: setIx :: (Storable a) => Data [a] -> Data Int -> Data a -> Data [a]
- Feldspar.Core: size :: (NaturalT n, Storable a) => Data (n :> a) -> [Int]
+ Feldspar.Core: size :: (Storable a) => Data [a] -> [Range Length]
- Feldspar.Core: value :: (Primitive a) => a -> Data a
+ Feldspar.Core: value :: (Storable a) => a -> Data a
- Feldspar.Core: while :: (Computable a) => (a -> Data Bool) -> (a -> a) -> (a -> a)
+ Feldspar.Core: while :: (Computable state) => (state -> Data Bool) -> (state -> state) -> (state -> state)
- Feldspar.Core.Expr: (!) :: (RandomAccess a) => a -> Data Int -> Elem a
+ Feldspar.Core.Expr: (!) :: (RandomAccess a) => a -> Data Int -> Element a
- Feldspar.Core.Expr: Data :: (Ref (Expr a)) -> Data a
+ Feldspar.Core.Expr: Data :: (Size a) -> (Ref (Expr a)) -> Data a
- Feldspar.Core.Expr: Function :: String -> (a -> b) -> Data a -> Expr b
+ Feldspar.Core.Expr: Function :: String -> Size b -> (a -> b) -> Data a -> Expr b
- Feldspar.Core.Expr: IfThenElse :: Data Bool -> (Data a -> Data b) -> (Data a -> Data b) -> Data a -> Expr b
+ Feldspar.Core.Expr: IfThenElse :: Data Bool -> (a :-> b) -> (a :-> b) -> Data a -> Expr b
- Feldspar.Core.Expr: Input :: Expr a
+ Feldspar.Core.Expr: Input :: Size a -> Expr a
- Feldspar.Core.Expr: NoInline :: String -> Ref (Data a -> Data b) -> Data a -> Expr b
+ Feldspar.Core.Expr: NoInline :: String -> Ref (a :-> b) -> Data a -> Expr b
- Feldspar.Core.Expr: Parallel :: Data Int -> (Data Int -> Data a) -> Expr (n :> a)
+ Feldspar.Core.Expr: Parallel :: Data Length -> (Int :-> a) -> Expr [a]
- Feldspar.Core.Expr: Value :: a -> Expr a
+ Feldspar.Core.Expr: Value :: Size a -> a -> Expr a
- Feldspar.Core.Expr: While :: (Data a -> Data Bool) -> (Data a -> Data a) -> Data a -> Expr a
+ Feldspar.Core.Expr: While :: (a :-> Bool) -> (a :-> a) -> Data a -> Expr a
- Feldspar.Core.Expr: array :: (NaturalT n, Storable a) => ListBased (n :> a) -> Data (n :> a)
+ Feldspar.Core.Expr: array :: (Storable a) => Size a -> a -> Data a
- Feldspar.Core.Expr: class RandomAccess a where { type family Elem a; }
+ Feldspar.Core.Expr: class RandomAccess a where { type family Element a; }
- Feldspar.Core.Expr: function :: (Storable a, Storable b) => String -> (a -> b) -> (Data a -> Data b)
+ 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 -> (a -> b -> c) -> (Data a -> Data b -> Data c)
+ 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 -> (a -> b -> c -> d) -> (Data a -> Data b -> Data c -> Data d)
+ 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 -> (a -> b -> c -> d -> e) -> (Data a -> Data b -> Data c -> Data d -> Data e)
+ 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: getIx :: (NaturalT n, Storable a) => Data (n :> a) -> Data Int -> Data a
+ Feldspar.Core.Expr: getIx :: (Storable a) => Data [a] -> Data Int -> Data a
- Feldspar.Core.Expr: parallel :: (NaturalT n, Storable a) => Data Int -> (Data Int -> Data a) -> Data (n :> a)
+ Feldspar.Core.Expr: parallel :: (Storable a) => Data Length -> (Data Int -> Data a) -> Data [a]
- Feldspar.Core.Expr: setIx :: (NaturalT n, Storable a) => Data (n :> a) -> Data Int -> Data a -> Data (n :> a)
+ Feldspar.Core.Expr: setIx :: (Storable a) => Data [a] -> Data Int -> Data a -> Data [a]
- Feldspar.Core.Expr: size :: (NaturalT n, Storable a) => Data (n :> a) -> [Int]
+ Feldspar.Core.Expr: size :: (Storable a) => Data [a] -> [Range Length]
- Feldspar.Core.Expr: value :: (Primitive a) => a -> Data a
+ Feldspar.Core.Expr: value :: (Storable a) => a -> Data a
- Feldspar.Core.Expr: while :: (Computable a) => (a -> Data Bool) -> (a -> a) -> (a -> a)
+ Feldspar.Core.Expr: while :: (Computable state) => (state -> Data Bool) -> (state -> state) -> (state -> state)
- Feldspar.Core.Graph: Parallel :: Int -> Interface -> Function
+ Feldspar.Core.Graph: Parallel :: Interface -> Function
- Feldspar.Core.Show: showGraph :: String -> Bool -> Graph -> String
+ Feldspar.Core.Show: showGraph :: Bool -> String -> Bool -> Graph -> String
- Feldspar.Core.Show: showNode :: Node -> [Hierarchy] -> String
+ Feldspar.Core.Show: showNode :: Bool -> Node -> [Hierarchy] -> String
- Feldspar.Core.Show: showSF :: (HaskellValue inp, HaskellValue outp) => Hierarchy -> String -> inp -> outp -> String
+ Feldspar.Core.Show: showSF :: (HaskellValue inp, HaskellValue outp) => Bool -> Hierarchy -> String -> inp -> outp -> String
- Feldspar.Core.Show: showSubFun :: (HaskellValue inp, HaskellValue outp) => Hierarchy -> String -> Maybe inp -> outp -> String
+ Feldspar.Core.Show: showSubFun :: (HaskellValue inp, HaskellValue outp) => Bool -> Hierarchy -> String -> Maybe inp -> outp -> String
- Feldspar.Core.Types: FloatType :: PrimitiveType
+ Feldspar.Core.Types: FloatType :: (Range Float) -> PrimitiveType
- Feldspar.Core.Types: IntData :: Int -> PrimitiveData
+ Feldspar.Core.Types: IntData :: Integer -> PrimitiveData
- Feldspar.Core.Types: IntType :: PrimitiveType
+ Feldspar.Core.Types: IntType :: Bool -> Int -> (Range Integer) -> PrimitiveType
- Feldspar.Core.Types: StorableData :: Int -> [StorableData] -> StorableData
+ Feldspar.Core.Types: StorableData :: [StorableData] -> StorableData
- Feldspar.Core.Types: StorableType :: [Int] -> PrimitiveType -> StorableType
+ Feldspar.Core.Types: StorableType :: [Range Length] -> PrimitiveType -> StorableType
- Feldspar.Core.Types: UnitData :: PrimitiveData
+ Feldspar.Core.Types: UnitData :: () -> PrimitiveData
- Feldspar.Core.Types: class (Typeable a) => Storable a where { type family ListBased a :: *; type family Element a :: *; }
+ Feldspar.Core.Types: class (Typeable a) => Storable a
- Feldspar.Core.Types: class (Eq a, Ord a) => Typeable a
+ Feldspar.Core.Types: class (Eq a, Ord a, Monoid (Size a), Set (Size a)) => Typeable a where { type family Size a; }
- Feldspar.Core.Types: data (:>) n a
+ Feldspar.Core.Types: data (:>) a b
- Feldspar.Core.Types: typeOf :: (Typeable a) => T a -> Tuple StorableType
+ Feldspar.Core.Types: typeOf :: (Typeable a) => Size a -> T a -> Tuple StorableType
- Feldspar.Matrix: diagonal :: Matrix n n a -> VectorP n a
+ Feldspar.Matrix: diagonal :: Matrix a -> Vector (Data a)
- Feldspar.Matrix: flatten :: Matrix m n a -> VectorP (m :* n) a
+ Feldspar.Matrix: flatten :: Matrix a -> Vector (Data a)
- Feldspar.Matrix: freezeMatrix :: (NaturalT m, NaturalT n, Storable a) => Matrix m n a -> Data (m :> (n :> a))
+ Feldspar.Matrix: freezeMatrix :: (Storable a) => Matrix a -> Data [[a]]
- Feldspar.Matrix: matrix :: (NaturalT m, NaturalT n, Storable a, (ListBased a) ~ a) => [[a]] -> Matrix m n a
+ Feldspar.Matrix: matrix :: (Storable a) => [[a]] -> Matrix a
- Feldspar.Matrix: mul :: (Primitive a, Num a) => Matrix m n a -> Matrix n p a -> Matrix m p a
+ Feldspar.Matrix: mul :: (Numeric a) => Matrix a -> Matrix a -> Matrix a
- Feldspar.Matrix: transpose :: Matrix m n a -> Matrix n m a
+ Feldspar.Matrix: transpose :: Matrix a -> Matrix a
- Feldspar.Matrix: type Matrix m n a = Par m :>> (Par n :>> Data a)
+ Feldspar.Matrix: type Matrix a = Vector (Vector (Data a))
- Feldspar.Matrix: unfreezeMatrix :: (NaturalT m, NaturalT n, Storable a) => Data Int -> Data Int -> Data (m :> (n :> a)) -> Matrix m n a
+ Feldspar.Matrix: unfreezeMatrix :: (Storable a) => Data Length -> Data Length -> Data [[a]] -> Matrix a
- Feldspar.Vector: (++) :: (Computable a) => (t m :>> a) -> (t n :>> a) -> (t (m :+ n) :>> a)
+ Feldspar.Vector: (++) :: (Computable a) => Vector a -> Vector a -> Vector a
- Feldspar.Vector: Indexed :: Data Size -> (Data Ix -> a) -> Par n :>> a
+ Feldspar.Vector: Indexed :: Data Length -> (Data Ix -> a) -> Vector a
- Feldspar.Vector: drop :: Data Int -> (t n :>> a) -> (t n :>> a)
+ Feldspar.Vector: drop :: Data Int -> Vector a -> Vector a
- Feldspar.Vector: dropWhile :: (a -> Data Bool) -> (t n :>> a) -> (t n :>> a)
+ Feldspar.Vector: dropWhile :: (a -> Data Bool) -> Vector a -> Vector a
- Feldspar.Vector: enumFromTo :: (AccessPattern t) => Data Int -> Data Int -> (t n :>> Data Int)
+ Feldspar.Vector: enumFromTo :: Data Int -> Data Int -> Vector (Data Int)
- Feldspar.Vector: fold :: (Computable a) => (a -> b -> a) -> a -> (t n :>> b) -> a
+ Feldspar.Vector: fold :: (Computable a) => (a -> b -> a) -> a -> Vector b -> a
- Feldspar.Vector: fold1 :: (Computable a) => (a -> a -> a) -> (t n :>> a) -> a
+ Feldspar.Vector: fold1 :: (Computable a) => (a -> a -> a) -> Vector a -> a
- Feldspar.Vector: freezeVector :: (NaturalT n, Storable a) => (t n :>> Data a) -> Data (n :> a)
+ Feldspar.Vector: freezeVector :: (Storable a) => Vector (Data a) -> Data [a]
- Feldspar.Vector: head :: (t n :>> a) -> a
+ Feldspar.Vector: head :: Vector a -> a
- Feldspar.Vector: index :: (t :>> a) -> Data Ix -> a
+ Feldspar.Vector: index :: Vector a -> Data Ix -> a
- Feldspar.Vector: indexed :: Data Size -> (Data Ix -> a) -> (Par n :>> a)
+ Feldspar.Vector: indexed :: Data Length -> (Data Ix -> a) -> Vector a
- Feldspar.Vector: init :: (t n :>> a) -> (t n :>> a)
+ Feldspar.Vector: init :: Vector a -> Vector a
- Feldspar.Vector: inits :: (AccessPattern u) => (t n :>> a) -> (u n :>> (t n :>> a))
+ Feldspar.Vector: inits :: Vector a -> Vector (Vector a)
- Feldspar.Vector: last :: (t n :>> a) -> a
+ Feldspar.Vector: last :: Vector a -> a
- Feldspar.Vector: length :: (t n :>> a) -> Data Size
+ Feldspar.Vector: length :: Vector a -> Data Length
- Feldspar.Vector: map :: (a -> b) -> ((t n :>> a) -> (t n :>> b))
+ Feldspar.Vector: map :: (a -> b) -> Vector a -> Vector b
- Feldspar.Vector: maximum :: (Storable a) => (t n :>> Data a) -> Data a
+ Feldspar.Vector: maximum :: (Storable a) => Vector (Data a) -> Data a
- Feldspar.Vector: minimum :: (Storable a) => (t n :>> Data a) -> Data a
+ Feldspar.Vector: minimum :: (Storable a) => Vector (Data a) -> Data a
- Feldspar.Vector: permute :: (Data Size -> Data Ix -> Data Ix) -> ((Par n :>> a) -> (Par n :>> a))
+ Feldspar.Vector: permute :: (Data Length -> Data Ix -> Data Ix) -> (Vector a -> Vector a)
- Feldspar.Vector: replicate :: (AccessPattern t) => Data Int -> a -> (t n :>> a)
+ Feldspar.Vector: replicate :: Data Int -> a -> Vector a
- Feldspar.Vector: reverse :: (Par n :>> a) -> (Par n :>> a)
+ Feldspar.Vector: reverse :: Vector a -> Vector a
- Feldspar.Vector: scalarProd :: (Primitive a, Num a) => (t n :>> Data a) -> (t n :>> Data a) -> Data a
+ Feldspar.Vector: scalarProd :: (Numeric a) => Vector (Data a) -> Vector (Data a) -> Data a
- Feldspar.Vector: scan :: (Computable a) => (a -> b -> a) -> a -> (t n :>> b) -> (Seq n :>> a)
+ Feldspar.Vector: scan :: (Storable a, Computable b) => (Data a -> b -> Data a) -> Data a -> Vector b -> Vector (Data a)
- Feldspar.Vector: splitAt :: Data Int -> (t n :>> a) -> (t n :>> a, t n :>> a)
+ Feldspar.Vector: splitAt :: Data Int -> Vector a -> (Vector a, Vector a)
- Feldspar.Vector: sum :: (Num a, Computable a) => (t n :>> a) -> a
+ Feldspar.Vector: sum :: (Num a, Computable a) => Vector a -> a
- Feldspar.Vector: tail :: (t n :>> a) -> (t n :>> a)
+ Feldspar.Vector: tail :: Vector a -> Vector a
- Feldspar.Vector: tails :: (AccessPattern u) => (t n :>> a) -> (u n :>> (t n :>> a))
+ Feldspar.Vector: tails :: Vector a -> Vector (Vector a)
- Feldspar.Vector: take :: Data Int -> (t n :>> a) -> (t n :>> a)
+ Feldspar.Vector: take :: Data Int -> Vector a -> Vector a
- Feldspar.Vector: unfold :: (Computable s) => Data Size -> (s -> (a, s)) -> s -> (Seq n :>> a)
+ Feldspar.Vector: unfold :: (Computable state, Storable a) => Data Length -> state -> (state -> (Data a, state)) -> Vector (Data a)
- Feldspar.Vector: unfreezeVector :: (NaturalT n, Storable a, AccessPattern t) => Data Size -> Data (n :> a) -> (t n :>> Data a)
+ Feldspar.Vector: unfreezeVector :: (Storable a) => Data Length -> Data [a] -> Vector (Data a)
- Feldspar.Vector: unzip :: (t n :>> (a, b)) -> (t n :>> a, t n :>> b)
+ Feldspar.Vector: unzip :: Vector (a, b) -> (Vector a, Vector b)
- Feldspar.Vector: vector :: (NaturalT n, Storable a, AccessPattern t, (ListBased a) ~ a) => [a] -> (t n :>> Data a)
+ Feldspar.Vector: vector :: (Storable a) => [a] -> Vector (Data a)
- Feldspar.Vector: zip :: (t n :>> a) -> (t n :>> b) -> (t n :>> (a, b))
+ Feldspar.Vector: zip :: Vector a -> Vector b -> Vector (a, b)
- Feldspar.Vector: zipWith :: (a -> b -> c) -> (t n :>> a) -> (t n :>> b) -> (t n :>> c)
+ Feldspar.Vector: zipWith :: (a -> b -> c) -> Vector a -> Vector b -> Vector c
Files
- Feldspar.hs +6/−2
- Feldspar/Core.hs +16/−9
- Feldspar/Core/Expr.hs +388/−489
- Feldspar/Core/Functions.hs +187/−24
- Feldspar/Core/Graph.hs +6/−4
- Feldspar/Core/Haskell.hs +0/−77
- Feldspar/Core/Ref.hs +1/−3
- Feldspar/Core/Reify.hs +316/−0
- Feldspar/Core/Show.hs +42/−23
- Feldspar/Core/Types.hs +189/−243
- Feldspar/Haskell.hs +99/−0
- Feldspar/Matrix.hs +29/−32
- Feldspar/Prelude.hs +4/−3
- Feldspar/Range.hs +403/−0
- Feldspar/Utils.hs +8/−2
- Feldspar/Vector.hs +191/−333
- LICENSE +1/−1
- feldspar-language.cabal +12/−9
Feldspar.hs view
@@ -1,4 +1,4 @@--- Copyright (c) 2009, ERICSSON AB+-- Copyright (c) 2009-2010, ERICSSON AB -- All rights reserved. -- -- Redistribution and use in source and binary forms, with or without@@ -24,7 +24,7 @@ -- 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. --- | Exports everything necessary for ordinary use of the Feldspar language.+-- | Interface to the Feldspar language. module Feldspar ( module Feldspar.Prelude@@ -34,6 +34,10 @@ ) where ++import qualified Prelude+ -- In order to be able to play with the Feldspar module in GHCi without+ -- getting name clashes. import Feldspar.Prelude import Feldspar.Core
Feldspar/Core.hs view
@@ -1,4 +1,4 @@--- Copyright (c) 2009, ERICSSON AB+-- Copyright (c) 2009-2010, ERICSSON AB -- All rights reserved. -- -- Redistribution and use in source and binary forms, with or without@@ -24,42 +24,49 @@ -- 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 to the core language+-- | The user interface of the core language module Feldspar.Core- ( module Types.Data.Num- , Primitive- , (:>)+ ( Range (..)+ , (:>) (..)+ , Set (..)+ , Length , Storable- , ListBased+ , Size , Data+ , dataSize , Computable , Internal , eval , value+ , array+ , arrayLen , unit , true , false- , array , size+ , cap , getIx , setIx , RandomAccess (..)+ , Numeric , noInline , ifThenElse , while , parallel , Program , showCore+ , showCoreWithSize , printCore+ , printCoreWithSize , module Feldspar.Core.Functions ) where -import Types.Data.Num-+import Feldspar.Range import Feldspar.Core.Types import Feldspar.Core.Expr+import Feldspar.Core.Reify import Feldspar.Core.Functions
Feldspar/Core/Expr.hs view
@@ -1,4 +1,4 @@--- Copyright (c) 2009, ERICSSON AB+-- Copyright (c) 2009-2010, ERICSSON AB -- All rights reserved. -- -- Redistribution and use in source and binary forms, with or without@@ -24,120 +24,182 @@ -- 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 IncoherentInstances #-}+{-# LANGUAGE UndecidableInstances #-} --- | This module represents core programs as typed expressions (see 'Expr' /--- 'Data'). The idea is for programmers to use an interface based on 'Data',--- while back-end tools use the 'Graph' representation. The function 'toGraph'--- is used to convert between the two representations.+-- | This module gives a representation core programs as typed expressions (see+-- 'Expr' / 'Data'). module Feldspar.Core.Expr where -import Control.Monad.State-import Control.Monad.Writer-import Data.Map (Map)-import qualified Data.Map as Map-import Data.Maybe+import Data.Monoid import Data.Unique -import Types.Data.Num--import Feldspar.Core.Ref (Ref)-import qualified Feldspar.Core.Ref as Ref+import Feldspar.Range import Feldspar.Core.Types-import Feldspar.Core.Graph hiding (function, Function (..))-import qualified Feldspar.Core.Graph as Graph-import Feldspar.Core.Show+import Feldspar.Core.Ref --- * Expressions+-- | 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+ Input :: Size a -> Expr a+ -- XXX Risky to rely on observable sharing? + Value :: Storable a => Size a -> a -> Expr a++ Tuple2 :: Data a -> Data b -> Expr (a,b)+ Tuple3 :: Data a -> Data b -> Data c -> Expr (a,b,c)+ Tuple4 :: Data a -> Data b -> Data c -> Data d -> Expr (a,b,c,d)+ -- XXX Tuple construction should be generalized.++ Get21 :: Data (a,b) -> Expr a+ Get22 :: Data (a,b) -> Expr b++ Get31 :: Data (a,b,c) -> Expr a+ Get32 :: Data (a,b,c) -> Expr b+ Get33 :: Data (a,b,c) -> Expr c++ Get41 :: Data (a,b,c,d) -> Expr a+ Get42 :: Data (a,b,c,d) -> Expr b+ Get43 :: Data (a,b,c,d) -> Expr c+ Get44 :: Data (a,b,c,d) -> Expr d+ -- XXX Tuple projection should be generalized.++ Function :: String -> Size b -> (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++++data a :-> b = SubFunction (Data a -> Data b) (Data a) (Data b)+++ -- | A wrapper around 'Expr' to allow observable sharing (see--- "Feldspar.Core.Ref").-data Data a = Typeable a => Data (Ref (Expr a))+-- "Feldspar.Core.Ref") and for memoizing size information.+data Data a = Typeable a => Data (Size a) (Ref (Expr a)) instance Eq (Data a) where- Data a == Data b = a==b+ Data _ a == Data _ b = a==b+ -- Reference equality instance Ord (Data a) where- Data a `compare` Data b = a `compare` b+ Data _ a `compare` Data _ b = a `compare` b+ -- Reference comparison -ref :: Typeable a => Expr a -> Data a-ref = Data . Ref.ref+dataSize :: Data a -> Size a+dataSize (Data sz _) = sz -refId :: Data a -> Unique-refId (Data r) = Ref.refId r+dataType :: forall a . Data a -> Tuple StorableType+dataType a@(Data _ _) = typeOf (dataSize a) (T::T a) -deref :: Data a -> Expr a-deref (Data r) = Ref.deref r+dataId :: Data a -> Unique+dataId (Data _ r) = refId r -typeOfData :: forall a . Typeable a => Data a -> Tuple StorableType-typeOfData _ = typeOf (T::T a)+dataToExpr :: Data a -> Expr a+dataToExpr (Data _ r) = deref r +subFunSize :: (a :-> b) -> Size b+subFunSize (SubFunction _ _ outp) = dataSize outp +subAp :: (a :-> b) -> (Data a -> Data b)+subAp (SubFunction f _ _) = f --- | Typed core language expressions. A value of type @Expr a@ can be thought of--- as a representation of a program that computes a value of type @a@.-data Expr a+exprToData :: Typeable a => Expr a -> Data a+exprToData a = Data (exprSize a) (ref a)++++exprSize :: forall a . Typeable a => Expr a -> Size a++exprSize (Input sz) = sz+exprSize (Value sz _) = sz++exprSize (Tuple2 a b) = (dataSize a, dataSize b)+exprSize (Tuple3 a b c) = (dataSize a, dataSize b, dataSize c)+exprSize (Tuple4 a b c d) = (dataSize a, dataSize b, dataSize c, dataSize d)++exprSize (Get21 ab) = da where- Input :: Expr a -- XXX Risky to rely on observable sharing?- Value :: Storable a => a -> Expr a+ (da,db) = dataSize ab - Tuple2 :: Data a -> Data b -> Expr (a,b)- Tuple3 :: Data a -> Data b -> Data c -> Expr (a,b,c)- Tuple4 :: Data a -> Data b -> Data c -> Data d -> Expr (a,b,c,d)- GetTuple :: GetTuple n a => T n -> Data a -> Expr (Part n a)+exprSize (Get22 ab) = db+ where+ (da,db) = dataSize ab - Function :: String -> (a -> b) -> (Data a -> Expr b)+exprSize (Get31 abc) = da+ where+ (da,db,dc) = dataSize abc - NoInline- :: (Typeable a, Typeable b)- => String -> Ref.Ref (Data a -> Data b) -> (Data a -> Expr b)+exprSize (Get32 abc) = db+ where+ (da,db,dc) = dataSize abc - IfThenElse- :: (Typeable a, Typeable b)- => Data Bool -- Condition- -> (Data a -> Data b) -- If branch- -> (Data a -> Data b) -- Else branch- -> (Data a -> Expr b)+exprSize (Get33 abc) = dc+ where+ (da,db,dc) = dataSize abc - While- :: Typeable a- => (Data a -> Data Bool) -- Continue?- -> (Data a -> Data a) -- Body- -> Data a -- Initial state- -> Expr a -- Final state+exprSize (Get41 abcd) = da+ where+ (da,db,dc,dd) = dataSize abcd - Parallel- :: (NaturalT n, Storable a)- => Data Int -- Dynamic size (must be <= array size)- -> (Data Int -> Data a) -- Index mapping- -> Expr (n :> a) -- Result vector+exprSize (Get42 abcd) = db+ where+ (da,db,dc,dd) = dataSize abcd - -- XXX Some Typeable constraints are needed because the sub-functions need to- -- be applied to input. Perhaps it's better to scrap the hidden context in- -- Data and put Typeable context on all Expr constructors instead?+exprSize (Get43 abcd) = dc+ where+ (da,db,dc,dd) = dataSize abcd +exprSize (Get44 abcd) = dd+ where+ (da,db,dc,dd) = dataSize abcd +exprSize (Function _ sz _ _) = sz+exprSize (NoInline _ f a) = subFunSize (deref f)+exprSize (IfThenElse _ t e a) = subFunSize t `mappend` subFunSize e+exprSize (While _ b i) = dataSize i `mappend` subFunSize b+exprSize (Parallel l ixf) = mapMonotonic fromIntegral (dataSize l)+ :> subFunSize ixf ++ -- | Computable types. A computable value completely represents a core program,--- in such a way that @internalize . externalize@ preserves semantics, but not--- necessarily syntax.+-- 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 core API as the \"external core--- language\".+-- the \"internal\" core language and the "Feldspar.Core" API as the+-- \"external\" core language. class Typeable (Internal a) => Computable a where- -- | The internal representation of the type @a@ (without the 'Data'- -- constructor).+ -- | @`Data` (`Internal` a)@ is the internal representation of the type @a@. type Internal a -- | Convert to internal representation@@ -157,26 +219,26 @@ where type Internal (a,b) = (Internal a, Internal b) - internalize (a,b) = ref $ Tuple2 (internalize a) (internalize b)+ internalize (a,b) = exprToData $ Tuple2 (internalize a) (internalize b) externalize ab =- ( externalize $ ref $ GetTuple (T::T D0) ab- , externalize $ ref $ GetTuple (T::T D1) ab+ ( externalizeE $ Get21 ab+ , externalizeE $ 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) = ref $ Tuple3+ internalize (a,b,c) = exprToData $ Tuple3 (internalize a) (internalize b) (internalize c) externalize abc =- ( externalize $ ref $ GetTuple (T::T D0) abc- , externalize $ ref $ GetTuple (T::T D1) abc- , externalize $ ref $ GetTuple (T::T D2) abc+ ( externalizeE $ Get31 abc+ , externalizeE $ Get32 abc+ , externalizeE $ Get33 abc ) instance@@ -189,102 +251,139 @@ where type Internal (a,b,c,d) = (Internal a, Internal b, Internal c, Internal d) - internalize (a,b,c,d) = ref $ Tuple4+ internalize (a,b,c,d) = exprToData $ Tuple4 (internalize a) (internalize b) (internalize c) (internalize d) externalize abcd =- ( externalize $ ref $ GetTuple (T::T D0) abcd- , externalize $ ref $ GetTuple (T::T D1) abcd- , externalize $ ref $ GetTuple (T::T D2) abcd- , externalize $ ref $ GetTuple (T::T D3) abcd+ ( externalizeE $ Get41 abcd+ , externalizeE $ Get42 abcd+ , externalizeE $ Get43 abcd+ , externalizeE $ Get44 abcd ) -wrap :: (Computable a, Computable b) =>+externalizeE :: Computable a => Expr (Internal a) -> a+externalizeE = externalize . exprToData++-- | Lower a function to operate on internal representation.+lowerFun :: (Computable a, Computable b) => (a -> b) -> (Data (Internal a) -> Data (Internal b))-wrap f = internalize . f . externalize+lowerFun f = internalize . f . externalize -unwrap :: (Computable a, Computable b) =>+-- | Lift a function to operate on external representation.+liftFun :: (Computable a, Computable b) => (Data (Internal a) -> Data (Internal b)) -> (a -> b)-unwrap f = externalize . f . internalize+liftFun f = externalize . f . internalize -- | The semantics of expressions evalE :: Expr a -> a -evalE Input = error "evaluating Input"-evalE (Value a) = a+evalE (Input _) = error "evaluating Input"+evalE (Value _ a) = a evalE (Tuple2 a b) = (evalD a, evalD b) evalE (Tuple3 a b c) = (evalD a, evalD b, evalD c) evalE (Tuple4 a b c d) = (evalD a, evalD b, evalD c, evalD d)-evalE (GetTuple n a) = getTup n (evalD a) -evalE (Function _ f a) = f (evalD a)-evalE (NoInline _ f a) = evalD (Ref.deref f a)-evalE (IfThenElse c t e a) = if evalD c then evalD (t a) else evalD (e a)+evalE (Get21 ab) = a+ where+ (a,b) = evalD ab -evalE (While continue body init) = loop init+evalE (Get22 ab) = b where- loop s- | done = evalD s- | otherwise = loop (body s)- where- done = not $ evalD $ continue s+ (a,b) = evalD ab -evalE (Parallel sz ixf) =- mapArray (evalD . ixf . value) $ fromList [(0::Int) .. n-1]+evalE (Get31 abc) = a where- n = evalD sz+ (a,b,c) = evalD abc +evalE (Get32 abc) = b+ where+ (a,b,c) = evalD abc +evalE (Get33 abc) = c+ where+ (a,b,c) = evalD abc --- | Evaluation of 'Data'-evalD :: Data a -> a-evalD = evalE . deref+evalE (Get41 abcd) = a+ where+ (a,b,c,d) = evalD abcd --- | Evaluation of any 'Computable' type-eval :: Computable a => a -> Internal a-eval = evalD . internalize+evalE (Get42 abcd) = b+ where+ (a,b,c,d) = evalD abcd +evalE (Get43 abcd) = c+ where+ (a,b,c,d) = evalD abcd +evalE (Get44 abcd) = d+ where+ (a,b,c,d) = evalD abcd -instance Primitive a => Show (Data a)+evalE (Function _ _ f a) = f (evalD a)+evalE (NoInline _ f a) = evalD $ subAp (deref f) a+evalE (IfThenElse c t e a) = if evalD c+ then evalD (subAp t a)+ else evalD (subAp e a)++evalE (While continue body init) = loop init where- show a = "... :: Data a"- -- Needed for the @Num@ instance.+ loop s = if done+ then evalD s+ else loop (subAp body s)+ where+ done = not $ evalD $ subAp continue s -instance (Num n, Primitive n) => Num (Data n)+evalE (Parallel l ixf) = map (evalD . subAp ixf . value) [0 .. n-1] where- fromInteger = value . fromInteger- abs = functionFold "abs" abs- signum = functionFold "signum" signum- (+) = functionFold2 "(+)" (+)- (-) = functionFold2 "(-)" (-)- (*) = functionFold2 "(*)" (*)+ n = evalD l -instance Fractional (Data Float)- where- fromRational = value . fromRational- (/) = functionFold2 "(/)" (/)+-- | The semantics of 'Data'+evalD :: Data a -> a+evalD = evalE . dataToExpr +-- | The semantics of any 'Computable' type+eval :: Computable a => a -> Internal a+eval = evalD . internalize --- | Internal function for constructing storable values.-value_ :: Storable a => a -> Data a-value_ = ref . Value --- | A primitive value (a program that computes a constant value)-value :: Primitive a => a -> Data a-value = value_+-- | A program that computes a constant value+value :: Storable a => a -> Data a+value a = exprToData (Value (storableSize a) 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 $ Value (sz `mappend` storableSize a) 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 () @@ -294,58 +393,82 @@ false :: Data Bool false = value False --- | For example,------ > array [[1,2,3],[4,5]] :: Data (D2 :> D4 :> Int)------ is a 2x4-element array of @Int@s, with the first row initialized to @[1,2,3]@--- and the second row to @[4,5]@.-array :: (NaturalT n, Storable a) => ListBased (n :> a) -> Data (n :> a)-array = value_ . fromList- -- | Returns the size of each level of a multi-dimensional array, starting with -- the outermost level.-size :: (NaturalT n, Storable a) => Data (n :> a) -> [Int]-size arr = szs- where- One (StorableType szs _) = typeOfData arr+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 --- | A one-argument primitive function. The first argument is the name of the--- function, and the second argument gives its evaluation semantics.-function :: (Storable a, Storable b) => String -> (a -> b) -> (Data a -> Data b)-function fun f = ref . Function fun f +-- | 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' -> Data s (ref $ Value s $ f a')+ _ -> exprToData $ Function fun s f a+ where+ s = sizeProp (dataSize a) --- | A two-argument function+++-- | A two-argument primitive function function2 :: ( Storable a , Storable b , Storable c )- => String -> (a -> b -> c) -> (Data a -> Data b -> Data c)+ => String+ -> (Size a -> Size b -> Size c)+ -> (a -> b -> c)+ -> (Data a -> Data b -> Data c) -function2 fun f a b = ref $ Function fun (\(a,b) -> f a b) (ref $ Tuple2 a b)+function2 fun sizeProp f a b = case (dataToExpr a, dataToExpr b) of+ (Value _ a', Value _ b') -> Data s (ref $ Value s $ f a' b')+ _ -> exprToData $ Function fun s f' $ exprToData $ Tuple2 a b+ where+ s = sizeProp (dataSize a) (dataSize b)+ f' (a,b) = f a b --- | A three-argument function+-- | A three-argument primitive function function3 :: ( Storable a , Storable b , Storable c , Storable d )- => String -> (a -> b -> c -> d) -> (Data a -> Data b -> Data c -> Data d)+ => String+ -> (Size a -> Size b -> Size c -> Size d)+ -> (a -> b -> c -> d)+ -> (Data a -> Data b -> Data c -> Data d) -function3 fun f a b c =- ref $ Function fun (\(a,b,c) -> f a b c) (ref $ Tuple3 a b c)+function3 fun sizeProp f a b c = case (d2e a, d2e b, d2e c) of+ (Value _ a', Value _ b', Value _ c') -> Data s (ref $ Value s $ f a' b' c')+ _ -> exprToData $ Function fun s f' $ exprToData $ Tuple3 a b c+ where+ d2e = dataToExpr+ s = sizeProp (dataSize a) (dataSize b) (dataSize c)+ f' (a,b,c) = f a b c --- | A four-argument function+-- | A four-argument primitive function function4 :: ( Storable a , Storable b@@ -354,119 +477,98 @@ , 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 f a b c d =- ref $ Function fun (\(a,b,c,d) -> f a b c d) (ref $ Tuple4 a b c d)------ | A one-argument function with constant folding-functionFold- :: (Storable a, Storable b) => String -> (a -> b) -> (Data a -> Data b)--functionFold fun f a = case deref a of- Value a' -> value_ (f a')- _ -> function fun f a------ | A two-argument function with constant folding-functionFold2- :: ( Storable a- , Storable b- , Storable c- )- => String -> (a -> b -> c) -> (Data a -> Data b -> Data c)--functionFold2 fun f a b = case (deref a, deref b) of- (Value a', Value b') -> value_ (f a' b')- _ -> function2 fun f a b+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') -> Data s (ref $ Value s $ f a' b' c' d')+ _ -> exprToData $ Function fun s f' $ exprToData $ Tuple4 a b c d+ where+ d2e = dataToExpr+ s = sizeProp (dataSize a) (dataSize b) (dataSize c) (dataSize d)+ f' (a,b,c,d) = f a b c d --- | A three-argument function with constant folding-functionFold3- :: ( Storable a- , Storable b- , Storable c- , Storable d- )- => String -> (a -> b -> c -> d) -> (Data a -> Data b -> Data c -> Data d)--functionFold3 fun f a b c = case (deref a, deref b, deref c) of- (Value a', Value b', Value c') -> value_ (f a' b' c')- _ -> function3 fun f a b c--+instance Show (Data a)+ where+ show _ = "... :: Data a"+ -- Needed for the 'Num' instance. --- | A four-argument function with constant folding-functionFold4- :: ( Storable a- , Storable b- , Storable c- , Storable d- , Storable e- )- => String -> (a -> b -> c -> d -> e)- -> (Data a -> Data b -> Data c -> Data d -> Data e)+instance Numeric a => Num (Data a)+ where+ fromInteger = value . fromInteger+ abs = function "abs" abs abs+ signum = function "signum" signum signum+ (+) = function2 "(+)" (+) (+)+ (-) = function2 "(-)" (-) (-)+ (*) = function2 "(*)" (*) (*) -functionFold4 fun f a b c d = case (deref a, deref b, deref c, deref d) of- (Value a', Value b', Value c', Value d') -> value_ (f a' b' c' d')- _ -> function4 fun f a b c d+instance Fractional (Data Float)+ where+ fromRational = value . fromRational+ (/) = function2 "(/)" (\_ _ -> fullRange) (/) -- XXX Improve range --- | Look up an index in an array-getIx :: forall n a . (NaturalT n, Storable a) =>- Data (n :> a) -> Data Int -> Data a--getIx = functionFold2 "(!)" f+-- | 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- f (ArrayList as) i- | i >= n || i < 0 = error "getIx: index out of bounds"- | i >= l = error "getIx: reading garbage"- | otherwise = as !! i+ 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- n = fromIntegerT (undefined :: n)- l = length as+ l :> _ = dataSize arr+ r = rangeByRange 0 (l-1)+ la = length as --- | @setIx arr i a@:+-- | @`setIx` arr i a@: -- -- Replaces the value at index @i@ in the array @arr@ with the value @a@.-setIx :: forall n a . (NaturalT n, Storable a) =>- Data (n :> a) -> Data Int -> Data a -> Data (n :> a)--setIx = functionFold3 "setIx" f+setIx :: Storable a => Data [a] -> Data Int -> Data a -> Data [a]+setIx arr = function3 "setIx" sizeProp f arr where- f :: (n :> a) -> Int -> a -> (n :> a)- f (ArrayList as) i a- | i >= n || i < 0 = error "setIx: index out of bounds"- | i > l = error "setIx: writing past initialized area"- | otherwise = ArrayList $ take i as ++ [a] ++ drop (i+1) as- where- n = fromIntegerT (undefined :: n)- l = length as+ 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- type Elem a+ -- | The type of elements in a random access structure+ type Element a - -- | Index lookup in random access structures- (!) :: a -> Data Int -> Elem a+ -- | Index lookup in a random access structure+ (!) :: a -> Data Int -> Element a -instance (NaturalT n, Storable a) => RandomAccess (Data (n :> a))+instance Storable a => RandomAccess (Data [a]) where- type Elem (Data (n :> a)) = Data a+ type Element (Data [a]) = Data a (!) = getIx +mkSubFun :: Typeable a => Size a -> (Data a -> Data b) -> (a :-> b)+mkSubFun sz f = SubFunction f inp (f inp)+ where+ inp = exprToData $ Input sz++ -- | Constructs a non-primitive, non-inlined function. -- -- The normal way to make a non-primitive function is to use an ordinary Haskell@@ -482,11 +584,13 @@ -- 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 = unwrap . (ref .) . NoInline fun . Ref.ref . wrap+noInline fun f a = liftFun (exprToData . NoInline fun (ref subFun)) a+ where+ subFun = mkSubFun (dataSize $ internalize a) (lowerFun f) --- | @ifThenElse cond thenFunc elseFunc@:+-- | @`ifThenElse` cond thenFunc elseFunc@: -- -- Selects between the two functions @thenFunc@ and @elseFunc@ depending on -- whether the condition @cond@ is true or false.@@ -494,273 +598,68 @@ :: (Computable a, Computable b) => Data Bool -> (a -> b) -> (a -> b) -> (a -> b) -ifThenElse cond t e = case deref cond of- Value True -> t- Value False -> e+ifThenElse cond t e a = case dataToExpr cond of+ Value _ True -> t a+ Value _ False -> e a -- Function "not" _ c -> ifThenElse c e t -- XXX Not possible...- _ -> unwrap $ (ref .) $ IfThenElse cond (wrap t) (wrap e)------ | @while cont body@:------ A while-loop. The condition @cont@ determines whether the loop should--- continue one more iteration. @body@ computes the next state. The result is a--- function from initial state to final state.-while- :: Computable a- => (a -> Data Bool)- -> (a -> a)- -> (a -> a)--while cont = unwrap . (ref .) . While (cont . externalize) . wrap------ | @parallel sz ixf@:------ Parallel tiling. Computes the elements of a vector. @sz@ is the dynamic size,--- i.e. how many of the allocated elements that should be computed. The function--- @ixf@ maps each index to its value.------ Since there are no dependencies between the elements, the compiler is free to--- compute the elements in parallel (or any other order).-parallel :: (NaturalT n, Storable a) =>- Data Int -> (Data Int -> Data a) -> Data (n :> a)-parallel sz = ref . Parallel sz------ * Graph conversion--data Info = Info- { -- | Next id- index :: NodeId- -- | Visited references mapped to their id- , visited :: Map Unique NodeId- }---- | Monad for making graph building easier-type GraphBuilder a = WriterT [Node] (State Info) a--startInfo :: Info-startInfo = Info 0 Map.empty--runGraph :: GraphBuilder a -> Info -> (a, ([Node], Info))-runGraph graph info = (a, (nodes, info'))+ _ -> liftFun (exprToData . IfThenElse cond thenSub elseSub) a where- ((a,nodes),info') = runState (runWriterT graph) info--newIndex :: GraphBuilder NodeId-newIndex = do- info <- get- put (info {index = succ (index info)})- return (index info)--remember :: Data a -> NodeId -> GraphBuilder ()-remember dat i = modify $ \info ->- info {visited = Map.insert (refId dat) i (visited info)}--checkNode :: Data a -> GraphBuilder (Maybe NodeId)-checkNode dat = gets ((Map.lookup (refId dat)) . visited)--tupleBind :: Typeable a => NodeId -> T a -> Tuple Variable-tupleBind i = fmap (\path -> (i,path)) . tuplePath . typeOf------ | Declare a node-node- :: forall a . Typeable a- => Data a- -> Graph.Function- -> Tuple Source- -> Tuple StorableType- -> GraphBuilder ()--node dat fun inTup inType = do- i <- newIndex- remember dat i- let outType = typeOf (T::T a)- tell [Node i fun inTup inType outType]------ | Declare a source node (one with no inputs)-sourceNode :: Data a -> Graph.Function -> GraphBuilder ()-sourceNode dat@(Data _) fun = node dat fun (Tup []) (Tup [])------ Creates a source. The node must have been visited.-source :: forall a . [Int] -> Data a -> GraphBuilder Source-source path a = case deref a of-- GetTuple n tup -> source (numberT n : path) tup-- Value a | isPrimitive (T::T a) ->- let PrimitiveData a' = toData a- in return $ Constant a'-- _ -> do- Just i <- checkNode a- return $ Variable (i,path)+ sz = dataSize $ internalize a+ thenSub = mkSubFun sz $ lowerFun t+ elseSub = mkSubFun sz $ lowerFun e -traceTuple :: Data a -> GraphBuilder (Tuple Source)-traceTuple a = case deref a of-- Tuple2 b c -> do- b' <- traceTuple b- c' <- traceTuple c- return (Tup [b',c'])-- Tuple3 b c d -> do- b' <- traceTuple b- c' <- traceTuple c- d' <- traceTuple d- return (Tup [b',c',d'])-- Tuple4 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)--+whileSized+ :: Computable state+ => Size (Internal state)+ -> (state -> Data Bool)+ -> (state -> state)+ -> (state -> state) -buildGraph :: forall a . Data a -> GraphBuilder ()-buildGraph dat@(Data _) = do- idat <- checkNode dat- unless (isJust idat) $ list (deref dat)+whileSized sz cont body init = liftFun (exprToData . While contSub bodySub) init where- funcNode fun inp@(Data _) = do- buildGraph inp- inTup <- traceTuple inp- node dat fun inTup (typeOfData inp)-- list :: Expr a -> GraphBuilder ()-- list Input = sourceNode dat Graph.Input-- list (Value a)- | isPrimitive (T::T a) = return ()- | otherwise = sourceNode dat $ Graph.Array $ toData a-- list (Tuple2 a b) = buildGraph a >> buildGraph b- list (Tuple3 a b c) = buildGraph a >> buildGraph b >> buildGraph c- list (Tuple4 a b c d) =- buildGraph a >> buildGraph b >> buildGraph c >> buildGraph d-- list (GetTuple _ a) = buildGraph a-- list (Function fun _ a) = funcNode (Graph.Function fun) a-- list (NoInline fun f a) = do- iface <- buildSubFun (Ref.deref f)- funcNode (Graph.NoInline fun iface) a- -- XXX Sub-graph is not shared at the moment.-- list (IfThenElse cond t e a) = do- ifaceThen <- buildSubFun t- ifaceElse <- buildSubFun e- funcNode (Graph.IfThenElse ifaceThen ifaceElse) (ref $ Tuple2 cond a)-- list (While cont body a) = do- ifaceCont <- buildSubFun cont- ifaceBody <- buildSubFun body- funcNode (Graph.While ifaceCont ifaceBody) a-- list (Parallel sz ixf) = do- iface <- buildSubFun ixf- funcNode (Graph.Parallel n iface) sz- where- One (StorableType (n:_) _) = typeOfData dat+ contSub = mkSubFun sz $ lowerFun cont+ bodySub = mkSubFun sz $ lowerFun body -buildSubFun :: forall a b . (Typeable a, Typeable b) =>- (Data a -> Data b) -> GraphBuilder Interface--buildSubFun f = do- let inp = ref Input :: Data a- outp = f inp- buildGraph inp -- Needed in case input is not used- buildGraph outp- outTup <- traceTuple outp- info <- get- let inId = visited info Map.! refId inp- inType = typeOf (T::T a)- outType = typeOf (T::T b)- return (Interface inId outTup inType outType)--+-- | 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) -toGraphD :: (Typeable a, Typeable b) => (Data a -> Data b) -> Graph-toGraphD f = Graph nodes iface- where- (iface,(nodes,_)) = runGraph (buildSubFun f) startInfo+while = whileSized universal --- | Types that represents core language programs-class Program a- where- -- | Converts a program to a Graph- toGraph :: 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.- hasArg :: T a -> Bool--instance Computable a => Program a- where- toGraph a = toGraphD (const (internalize a) :: Data () -> Data (Internal a))- hasArg = const False--instance (Computable a, Computable b) => Program (a -> b)- where- toGraph = toGraphD . wrap- hasArg = const True--instance (Computable a, Computable b, Computable c)- => Program (a -> b -> c)- where- toGraph = toGraph . uncurry- hasArg = const True--instance (Computable a, Computable b, Computable c, Computable d)- => Program (a -> b -> c -> d)- where- toGraph f = toGraph (\(a,b,c) -> f a b c)- hasArg = const True--instance- ( Computable a- , Computable b- , Computable c- , Computable d- , Computable e- ) =>- Program (a -> b -> c -> d -> e)+-- | 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 $ Parallel l ixfSub where- toGraph f = toGraph (\(a,b,c,d) -> f a b c d)- hasArg = const True------ | Shows the core code generated by program.-showCore :: forall a . Program a => a -> String-showCore = showGraph "program" (hasArg (T::T a)) . toGraph---- | @printCore = putStrLn . showCore@-printCore :: Program a => a -> IO ()-printCore = putStrLn . showCore+ szl = dataSize l+ ixfSub = mkSubFun (rangeByRange 0 (szl-1)) ixf
Feldspar/Core/Functions.hs view
@@ -1,4 +1,4 @@--- Copyright (c) 2009, ERICSSON AB+-- Copyright (c) 2009-2010, ERICSSON AB -- All rights reserved. -- -- Redistribution and use in source and binary forms, with or without@@ -32,11 +32,12 @@ import qualified Prelude -import Feldspar.Prelude+import Feldspar.Range import Feldspar.Core.Types import Feldspar.Core.Expr-+import Feldspar.Prelude +import qualified Data.Bits as B infix 4 == infix 4 /=@@ -48,70 +49,232 @@ +-- * Misc.++noSizeProp :: a -> ()+noSizeProp _ = ()++noSizeProp2 :: a -> b -> ()+noSizeProp2 _ _ = ()+++ (==) :: Storable a => Data a -> Data a -> Data Bool-(==) = functionFold2 "(==)" (Prelude.==)+a == b+ | a Prelude.== b = true+ | otherwise = function2 "(==)" noSizeProp2 (Prelude.==) a b+ -- XXX Partial evaluation (/=) :: Storable a => Data a -> Data a -> Data Bool-(/=) = functionFold2 "(/=)" (Prelude./=)+a /= b+ | a Prelude.== b = false+ | otherwise = function2 "(/=)" noSizeProp2 (Prelude./=) a b+ -- XXX Partial evaluation (<) :: Storable a => Data a -> Data a -> Data Bool-(<) = functionFold2 "(<)" (Prelude.<)+a < b+ | a Prelude.== b = false+ | otherwise = function2 "(<)" noSizeProp2 (Prelude.<) a b (>) :: Storable a => Data a -> Data a -> Data Bool-(>) = functionFold2 "(>)" (Prelude.>)+a > b+ | a Prelude.== b = false+ | otherwise = function2 "(>)" noSizeProp2 (Prelude.>) a b +(<<<) :: Data Int -> Data Int -> Data Bool+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+ -- XXX Enables more partial evaluation than (<). This function should be+ -- generalized and then replace (<).++(>>>) :: Data Int -> Data Int -> Data Bool+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+ -- XXX Enables more partial evaluation than (>). This function should be+ -- generalized and then replace (>).+ (<=) :: Storable a => Data a -> Data a -> Data Bool-(<=) = functionFold2 "(<=)" (Prelude.<=)+a <= b+ | a Prelude.== b = true+ | otherwise = function2 "(<=)" noSizeProp2 (Prelude.<=) a b+ -- XXX Partial evaluation (>=) :: Storable a => Data a -> Data a -> Data Bool-(>=) = functionFold2 "(>=)" (Prelude.>=)+a >= b+ | a Prelude.== b = true+ | otherwise = function2 "(>=)" noSizeProp2 (Prelude.>=) a b+ -- XXX Partial evaluation not :: Data Bool -> Data Bool-not = functionFold "not" Prelude.not+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-(&&) = functionFold2 "(&&)" (Prelude.&&)+(&&) = function2 "(&&)" noSizeProp2 (Prelude.&&) (||) :: Data Bool -> Data Bool -> Data Bool-(||) = functionFold2 "(||)" (Prelude.||)+(||) = function2 "(||)" noSizeProp2 (Prelude.||) -- | Lazy conjunction, second argument only run if necessary (&&*) :: Computable a => (a -> Data Bool) -> (a -> Data Bool) -> (a -> Data Bool)-(f &&* g) a = let fa = f a in ifThenElse fa g (const false) a+(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 = let fa = f a in ifThenElse fa (const true) g a+(f ||* g) a = ifThenElse (f a) (const true) g a min :: Storable a => Data a -> Data a -> Data a-min a b = a<=b ? (a,b)+min a b = a<b ? (a,b) max :: Storable a => Data a -> Data a -> Data a-max a b = a>=b ? (a,b)+max a b = a>b ? (a,b) +minX :: Data Int -> Data Int -> Data Int+minX a b = case dataToExpr cond1 of+ Value _ _ -> cond1 ? (a,b)+ _ -> cond2 ? (b,a)+ where+ cond1 = a<<<b+ cond2 = b<<<a+ -- XXX Enables more partial evaluation than min. This function should be+ -- generalized and then replace min.++maxX :: Data Int -> Data Int -> Data Int+maxX a b = case dataToExpr cond1 of+ Value _ _ -> cond1 ? (a,b)+ _ -> cond2 ? (b,a)+ where+ cond1 = a>>>b+ cond2 = b>>>a+ -- XXX Enables more partial evaluation than max. This function should be+ -- generalized and then replace max.+ div :: Data Int -> Data Int -> Data Int-div = functionFold2 "div" (Prelude.div)+div = function2 "div" (\_ _ -> fullRange) Prelude.div -- XXX Improve size propagation mod :: Data Int -> Data Int -> Data Int-mod = functionFold2 "mod" (Prelude.mod)+mod = function2 "mod" (\_ _ -> fullRange) Prelude.mod -- XXX Improve size propagation (^) :: Data Int -> Data Int -> Data Int-(^) = functionFold2 "(^)" (Prelude.^)+(^) = function2 "(^)" (\_ _ -> fullRange) (Prelude.^) -- XXX Improve size propagation --- | @for start end init body@:+++-- * Loops++-- | For-loop ----- A for-loop ranging over @[start .. end]@. @init@ is the starting state. The--- @body@ computes the next state given the current state and the current loop--- index.+-- @`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 $ while cont body' (start,init)+for start end init body = snd $ whileSized sz cont body' (start,init) where+ szi = rangeByRange (dataSize start) (dataSize end)+ sz = (szi,universal)+ cont (i,s) = i <= end body' (i,s) = (i+1, body i s) +++-- | 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) []+++-- * 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+ (.&.) = function2 "(.&.)" (\_ _ -> universal) (B..&.)+ (.|.) :: Data a -> Data a -> Data a+ (.|.) = function2 "(.|.)" (\_ _ -> universal) (B..|.)+ xor :: Data a -> Data a -> Data a+ xor = function2 "xor" (\_ _ -> universal) B.xor+ (⊕) :: 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 = function2 "shiftL" (\_ _ -> universal) B.shiftL+ (<<) :: Data a -> Data Int -> Data a+ (<<) = shiftL+ shiftR :: Data a -> Data Int -> Data a+ shiftR = function2 "shiftR" (\_ _ -> universal) B.shiftR+ (>>) :: Data a -> Data Int -> Data a+ (>>) = shiftR+ rotateL :: Data a -> Data Int -> Data a+ rotateL = function2 "rotateL" (\_ _ -> universal) B.rotateL+ rotateR :: Data a -> Data Int -> Data a+ rotateR = function2 "rotateR" (\_ _ -> universal) B.rotateR++ -- 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++instance Bits Int
Feldspar/Core/Graph.hs view
@@ -1,4 +1,4 @@--- Copyright (c) 2009, ERICSSON AB+-- Copyright (c) 2009-2010, ERICSSON AB -- All rights reserved. -- -- Redistribution and use in source and binary forms, with or without@@ -93,6 +93,8 @@ -- > 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@@ -290,7 +292,7 @@ -- | While-loop | While Interface Interface -- | Parallel tiling- | Parallel Int Interface+ | Parallel Interface deriving (Eq, Show) -- | A graph is a list of unique nodes with an interface.@@ -381,7 +383,7 @@ 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 i (Parallel ixf) = [sub i 0 ixf] subFun _ _ = [] @@ -471,7 +473,7 @@ 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 (Node i (Parallel _) _ _ _) = map (subFunHier i) [0] subHierarchies _ = [] topLevel :: [Node]
− Feldspar/Core/Haskell.hs
@@ -1,77 +0,0 @@--- Copyright (c) 2009, 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.Core.Haskell where----import Data.List--import Feldspar.Core.Types------ | No trailing @\'\\n\'@.-unlinesNoTrail :: [String] -> String-unlinesNoTrail = intercalate "\n"---- | Indents a string the given amount 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/Core/Ref.hs view
@@ -1,4 +1,4 @@--- Copyright (c) 2009, ERICSSON AB+-- Copyright (c) 2009-2010, ERICSSON AB, Koen Claessen -- All rights reserved. -- -- Redistribution and use in source and binary forms, with or without@@ -27,8 +27,6 @@ {-# OPTIONS_GHC -O0 #-} -- |--- Copyright : Copyright (c) 2009, Koen Claessen--- -- A simple implementation of \"observable sharing\". See -- -- * Koen Claessen, David Sands,
+ Feldspar/Core/Reify.hs view
@@ -0,0 +1,316 @@+-- 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+ ) 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 (..), SubFunction)+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++ Get21 tup -> source (0:path) tup+ Get22 tup -> source (1:path) tup+ Get31 tup -> source (0:path) tup+ Get32 tup -> source (1:path) tup+ Get33 tup -> source (2:path) tup+ Get41 tup -> source (0:path) tup+ Get42 tup -> source (1:path) tup+ Get43 tup -> source (2:path) tup+ Get44 tup -> source (3:path) tup++ Value _ b | isPrimitive a ->+ let PrimitiveData b' = storableData b+ in return $ Constant b'++ _ -> do+ Just i <- checkNode a+ return $ Variable (i,path)++++traceTuple :: Data a -> Reify (Tuple Source)+traceTuple a = case dataToExpr a of++ Tuple2 b c -> do+ b' <- traceTuple b+ c' <- traceTuple c+ return (Tup [b',c'])++ Tuple3 b c d -> do+ b' <- traceTuple b+ c' <- traceTuple c+ d' <- traceTuple d+ return (Tup [b',c',d'])++ Tuple4 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 (Input _) = sourceNode a Graph.Input++ list (Value _ b)+ | isPrimitive a = return ()+ | otherwise = sourceNode a $ Graph.Array $ storableData b++ list (Tuple2 b c) = buildGraph b >> buildGraph c+ list (Tuple3 b c d) = buildGraph b >> buildGraph c >> buildGraph d+ list (Tuple4 b c d e) =+ buildGraph b >> buildGraph c >> buildGraph d >> buildGraph e++ list (Get21 b) = buildGraph b+ list (Get22 b) = buildGraph b+ list (Get31 b) = buildGraph b+ list (Get32 b) = buildGraph b+ list (Get33 b) = buildGraph b+ list (Get41 b) = buildGraph b+ list (Get42 b) = buildGraph b+ list (Get43 b) = buildGraph b+ list (Get44 b) = buildGraph b++ list (Function fun _ _ b) = funcNode (Graph.Function fun) b++ 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) (exprToData $ Tuple2 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 (SubFunction _ 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 = mkSubFun 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+
Feldspar/Core/Show.hs view
@@ -1,4 +1,4 @@--- Copyright (c) 2009, ERICSSON AB+-- Copyright (c) 2009-2010, ERICSSON AB -- All rights reserved. -- -- Redistribution and use in source and binary forms, with or without@@ -34,8 +34,9 @@ import Control.Monad import Data.List +import Feldspar.Utils+import Feldspar.Haskell import Feldspar.Core.Types-import Feldspar.Core.Haskell import Feldspar.Core.Graph @@ -65,14 +66,28 @@ --- | Shows a single node. The first argument associates each sub-function with--- the nodes it owns.-showNode :: Node -> [Hierarchy] -> String+sizeComment :: Tuple StorableType -> String+sizeComment typ = case size of+ "" -> ""+ _ -> " -- Size: " ++ size+ where+ size = showTuple (fmap showStorableSize typ) -showNode (Node i fun inp inType outType) subHiers = showNd fun+++-- | 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 @@ -86,7 +101,7 @@ showNd (NoInline fun iface) = outp -=- fun -$- inp `local`- showSF (head subHiers) fun subInp subOutp+ showSF' (head subHiers) fun subInp subOutp where subInp = tupPatt inType $ interfaceInput iface subOutp = interfaceOutput iface@@ -109,8 +124,8 @@ subOutpThen = interfaceOutput ifaceThen subOutpElse = interfaceOutput ifaceElse - thenBranch = showSF thenHier "thenBranch" subInpThen subOutpThen- elseBranch = showSF elseHier "elseBranch" subInpElse subOutpElse+ thenBranch = showSF' thenHier "thenBranch" subInpThen subOutpThen+ elseBranch = showSF' elseHier "elseBranch" subInpElse subOutpElse showNd (While ifaceCont ifaceBody) = outp -=- "while" -$- "cont" -$- "body" -$- inp@@ -124,51 +139,54 @@ subOutpCont = interfaceOutput ifaceCont subOutpBody = interfaceOutput ifaceBody - contBranch = showSF contHier "cont" subInpCont subOutpCont- bodyBranch = showSF bodyHier "body" subInpBody subOutpBody+ contBranch = showSF' contHier "cont" subInpCont subOutpCont+ bodyBranch = showSF' bodyHier "body" subInpBody subOutpBody - showNd (Parallel szs iface) =- outp -=- "parallel" -$- szs -$- inp -$- "ixf"+ showNd (Parallel iface) =+ outp -=- "parallel" -$- inp -$- "ixf" `local`- showSF (head subHiers) "ixf" subInp subOutp+ showSF' (head subHiers) "ixf" subInp subOutp where subInp = tupPatt inType $ interfaceInput iface subOutp = interfaceOutput iface --- | @showSubFun hier name inp outp@:+-- | @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)- => Hierarchy+ => Bool+ -> Hierarchy -> String -> Maybe inp -> outp -> String -showSubFun (Hierarchy nodes) name inp outp =+showSubFun showSize (Hierarchy nodes) name inp outp = funHead inp -=- outp `local`- unlinesNoTrail (filter (not.null) $ map (uncurry showNode) nodes)+ unlinesNoTrail (filter (not.null) $ map (uncurry (showNode showSize)) nodes) where funHead Nothing = name funHead (Just inp) = name -$- inp --- | @showSF hier name inp = showSubFun hier name (Just inp)@+-- | @showSF showSize hier name inp = showSubFun showSize hier name (Just inp)@ showSF :: (HaskellValue inp, HaskellValue outp)- => Hierarchy+ => Bool+ -> Hierarchy -> String -> inp -> outp -> String -showSF hier name inp = showSubFun hier name (Just inp)+showSF showSize hier name inp = showSubFun showSize hier name (Just inp) @@ -176,8 +194,9 @@ -- 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 :: String -> Bool -> Graph -> String-showGraph name hasArg graph@(Graph nodes iface) = showSubFun hier name inp' outp+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)
Feldspar/Core/Types.hs view
@@ -1,4 +1,4 @@--- Copyright (c) 2009, ERICSSON AB+-- Copyright (c) 2009-2010, ERICSSON AB -- All rights reserved. -- -- Redistribution and use in source and binary forms, with or without@@ -24,6 +24,8 @@ -- 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@@ -31,117 +33,80 @@ import Control.Applicative-import Control.Monad import Data.Char import Data.Foldable (Foldable) import qualified Data.Foldable as Fold-import Data.Maybe+import Data.Monoid import Data.Traversable (Traversable, traverse) -import Types.Data.Num+import Data.Int+import Data.Word+import Data.Bits import Feldspar.Utils+import Feldspar.Haskell+import Feldspar.Range --- * Types as arguments+-- * Misc. -- | Used to pass a type to a function without using 'undefined'. data T a = T -numberT :: forall n . IntegerT n => T n -> Int-numberT _ = fromIntegerT (undefined :: n)+mkT :: a -> T a+mkT _ = T --- * Haskell source code+-- | Heterogeneous list+data a :> b = a :> b+ deriving (Eq, Ord, Show) --- | 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+infixr 5 :> -instance HaskellType a => HaskellType (Tuple a)+instance (Monoid a, Monoid b) => Monoid (a :> b) where- haskellType = showTuple . fmap haskellType+ mempty = mempty :> mempty + (a1:>b1) `mappend` (a2:>b2) = (a1 `mappend` a2) :> (b1 `mappend` b2) --- | 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+class Set a where- haskellValue = id+ universal :: a -instance HaskellValue Int+instance Set () where- haskellValue = show+ universal = () -instance HaskellValue a => HaskellValue (Tuple a)+instance Ord a => Set (Range a) where- haskellValue = showTuple . fmap haskellValue------ * Tuples+ universal = fullRange --- | General tuple projection-class NaturalT n => GetTuple n a+instance (Set a, Set b) => Set (a :> b) where- type Part n a- getTup :: T n -> a -> Part n a+ universal = universal :> universal -instance GetTuple D0 (a,b)+instance (Set a, Set b) => Set (a,b) where- type Part D0 (a,b) = a- getTup _ (a,b) = a+ universal = (universal,universal) -instance GetTuple D1 (a,b)+instance (Set a, Set b, Set c) => Set (a,b,c) where- type Part D1 (a,b) = b- getTup _ (a,b) = b+ universal = (universal,universal,universal) -instance GetTuple D0 (a,b,c)+instance (Set a, Set b, Set c, Set d) => Set (a,b,c,d) where- type Part D0 (a,b,c) = a- getTup _ (a,b,c) = a+ universal = (universal,universal,universal,universal) -instance GetTuple D1 (a,b,c)- where- type Part D1 (a,b,c) = b- getTup _ (a,b,c) = b -instance GetTuple D2 (a,b,c)- where- type Part D2 (a,b,c) = c- getTup _ (a,b,c) = c -instance GetTuple D0 (a,b,c,d)- where- type Part D0 (a,b,c,d) = a- getTup _ (a,b,c,d) = a--instance GetTuple D1 (a,b,c,d)- where- type Part D1 (a,b,c,d) = b- getTup _ (a,b,c,d) = b--instance GetTuple D2 (a,b,c,d)- where- type Part D2 (a,b,c,d) = c- getTup _ (a,b,c,d) = c--instance GetTuple D3 (a,b,c,d)- where- type Part D3 (a,b,c,d) = d- getTup _ (a,b,c,d) = d+type Length = Int +-- * Tuples -- | Untyped representation of nested tuples data Tuple a@@ -153,20 +118,31 @@ 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 instance Foldable Tuple 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 instance Traversable Tuple 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 +instance HaskellType a => HaskellType (Tuple a)+ where+ haskellType = showTuple . fmap haskellType +instance HaskellValue a => HaskellValue (Tuple a)+ where+ haskellValue = showTuple . fmap haskellValue --- | Shows a nested tuple in Haskell's tuple syntax (e.g @\"(a,(b,c))\"@)+++-- | 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) ")"@@ -186,267 +162,237 @@ -- * Data --- | Representation of primitive types-data PrimitiveType- = UnitType- | BoolType- | IntType- | FloatType- deriving (Eq, Show)- -- | Untyped representation of primitive data data PrimitiveData- = UnitData+ = UnitData () | BoolData Bool- | IntData Int+ | IntData Integer | FloatData Float deriving (Eq, Show) --- | Representation of storable types (arrays of primitive data). Array--- dimensions are given as a list of integers, starting with outermost array--- level. Primitive types are treated as zero-dimensional arrays.-data StorableType = StorableType [Int] PrimitiveType- deriving (Eq, Show)---- | Untyped representation of storable data. Arrays have a length argument that--- gives the number of elements on the outermost array level. If the data list--- is shorter than this length, the missing elements are taken to have--- undefined value. If the data list is longer, the excessive elements are just--- ignored.+-- | Untyped representation of storable data (arrays of primitive data) data StorableData = PrimitiveData PrimitiveData- | StorableData Int [StorableData]+ | StorableData [StorableData] deriving (Eq, Show) -instance HaskellType PrimitiveType- where- haskellType UnitType = "()"- haskellType BoolType = "Bool"- haskellType IntType = "Int"- haskellType FloatType = "Float"- instance HaskellValue PrimitiveData where- haskellValue UnitData = "()"+ haskellValue (UnitData a) = show a haskellValue (BoolData a) = map toLower (show a) haskellValue (IntData a) = show a haskellValue (FloatData a) = show a -instance HaskellType StorableType- where- haskellType (StorableType dim t) = arrType ++ dimComment- where- l = length dim- arrType = replicate l '[' ++ haskellType t ++ replicate l ']'- dimComment- | [] <- dim = ""- | otherwise = showSeq "{-" (map haskellValue dim) "-}"- instance HaskellValue StorableData where- haskellValue (PrimitiveData a) = haskellValue a- haskellValue (StorableData _ as) = showSeq "[" (map haskellValue as) "]"+ haskellValue (PrimitiveData a) = haskellValue a+ haskellValue (StorableData as) = showSeq "[" (map haskellValue as) "]" --- | Primitive types-class Storable a => Primitive a+-- * Types -instance Primitive ()-instance Primitive Bool-instance Primitive Int-instance Primitive Float+-- | Representation of primitive types+data PrimitiveType+ = UnitType+ | BoolType+ | IntType { signed :: Bool, bitSize :: Int, valueSet :: (Range Integer) }+ | FloatType (Range Float)+ deriving (Eq, Show) +-- | 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) +instance HaskellType PrimitiveType+ where+ haskellType UnitType = "()"+ haskellType BoolType = "Bool"+ haskellType (IntType _ _ _) = "Int"+ haskellType (FloatType _) = "Float" --- | Array represented as (nested) list. If @a@ is a storable type and @n@ is a--- type-level natural number, @n :> a@ represents an array of @n@ elements of--- type @a@. For example, @D3:>D10:>Int@ is a 3 by 10 array of integers. Arrays--- constructed using 'fromList' are guaranteed not to contain too many elements--- in any dimension. If there are too few elements in any dimension, the missing--- ones are taken to have undefined value.-data n :> a = (NaturalT n, Storable a) => ArrayList [a]+instance HaskellType StorableType+ where+ haskellType (StorableType ls t) = arrType+ where+ d = length ls+ arrType = replicate d '[' ++ haskellType t ++ replicate d ']' -infixr 5 :>+showPrimitiveRange UnitType = ""+showPrimitiveRange BoolType = ""+showPrimitiveRange (IntType _ _ r) = showRange r+showPrimitiveRange (FloatType r) = showRange r -instance (NaturalT n, Storable a, Eq a) => Eq (n :> a)- where- ArrayList a == ArrayList b = a == b+-- | Shows the size of a storable type.+showStorableSize :: StorableType -> String+showStorableSize (StorableType ls t) =+ showSeq "" (map (showBound . upperBound) ls) "" ++ showPrimitiveRange t -instance (NaturalT n, Storable a, Show (ListBased a)) => Show (n :> a)- where- show = show . toList -instance (NaturalT n, Storable a, Ord a) => Ord (n :> a)++-- | Primitive types+class Storable a => Primitive a where- ArrayList a `compare` ArrayList b = a `compare` b+ -- | Converts a primitive value to its untyped representation.+ primitiveData :: a -> PrimitiveData + -- | Gives the type representation of a primitive value.+ primitiveType :: Size a -> T a -> PrimitiveType +instance Primitive ()+ where+ primitiveData = UnitData+ primitiveType _ _ = UnitType -mapArray ::- (NaturalT n, Storable a, Storable b) => (a -> b) -> (n :> a) -> (n :> b)+instance Primitive Bool+ where+ primitiveData = BoolData+ primitiveType _ _ = BoolType -mapArray f (ArrayList as) = ArrayList $ map f as- -- Couldn't use Functor because of the extra class constraints.+-- Assumes 32 bits which is not necessarily correct+instance Primitive Int+ where+ primitiveData = IntData . toInteger+ primitiveType s _ = IntType True 32 s +instance Primitive Float+ where+ primitiveData = FloatData+ primitiveType s _ = FloatType s --- | Storable types (zero- or higher-level arrays of primitive data). Should be--- the same set of types as 'Storable', but this class has no 'Typeable'--- context, so it doesn't cause a cycle.------ Example:------ > *Feldspar.Core.Types> toList (replicateArray 3 :: D4 :> D2 :> Int)--- > [[3,3],[3,3],[3,3],[3,3]]++-- | Storable types (zero- or higher-level arrays of primitive data). class Typeable a => Storable a where- -- | List-based representation of a storable type- type ListBased a :: *- -- | The innermost element of a storable type- type Element a :: *-- -- | Constructs an array filled with the given element. For primitive types,- -- this is just the identity function.- replicateArray :: Element a -> a+ -- | Converts a storable value to its untyped representation.+ storableData :: a -> StorableData - -- | Converts a storable type to a (zero- or higher-level) nested list.- toList :: a -> ListBased a+ -- | Gives the type representation of a storable value.+ storableType :: Size a -> T a -> StorableType - -- | Constructs a storable type from a (zero- or higher-level) nested list.- -- The resulting value is guaranteed not to have too many elements in any- -- dimension. Excessive elements are simply cut away.- fromList :: ListBased a -> a+ -- | Gives the size of a storable value.+ storableSize :: a -> Size a - -- | Converts a storable value to its untyped representation.- toData :: a -> StorableData+ listSize :: T a -> Size a -> [Range Length]+ -- XXX Could be put in a separate class without the (T a). instance Storable () where- type ListBased () = ()- type Element () = ()-- replicateArray = id- toList = id- fromList = id-- toData a = PrimitiveData $ case a of- () -> UnitData+ storableData = PrimitiveData . primitiveData+ storableType s = StorableType [] . primitiveType s+ storableSize _ = ()+ listSize _ _ = [] instance Storable Bool where- type ListBased Bool = Bool- type Element Bool = Bool-- replicateArray = id- toList = id- fromList = id- toData = PrimitiveData . BoolData+ storableData = PrimitiveData . primitiveData+ storableType s = StorableType [] . primitiveType s+ storableSize _ = ()+ listSize _ _ = [] instance Storable Int where- type ListBased Int = Int- type Element Int = Int-- replicateArray = id- toList = id- fromList = id- toData = PrimitiveData . IntData+ storableData = PrimitiveData . primitiveData+ storableType s = StorableType [] . primitiveType s+ storableSize a = singletonRange $ toInteger a+ listSize _ _ = [] instance Storable Float where- type ListBased Float = Float- type Element Float = Float-- replicateArray = id- toList = id- fromList = id- toData = PrimitiveData . FloatData+ storableData = PrimitiveData . primitiveData+ storableType s = StorableType [] . primitiveType s+ storableSize a = singletonRange a+ listSize _ _ = [] -instance (NaturalT n, Storable a) => Storable (n :> a)+instance Storable a => Storable [a] where- type ListBased (n :> a) = [ListBased a]- type Element (n :> a) = Element a+ storableData = StorableData . map storableData - replicateArray = ArrayList . replicate n . replicateArray+ storableType (l:>ls) _ = StorableType (l:ls') t where- n = fromIntegerT (undefined :: n)-- toList (ArrayList as) = map toList as+ StorableType ls' t = storableType ls (T::T a) - fromList as = ArrayList $ take n $ map fromList as- where- n = fromIntegerT (undefined :: n)+ storableSize as =+ singletonRange (length as) :> mconcat (map storableSize as) - toData (ArrayList a) = StorableData n $ map toData a- where- n = fromIntegerT (undefined :: n)+ listSize _ (l:>ls) = l : listSize (T::T a) ls -isRectangular :: Storable a => a -> Bool-isRectangular = isJust . checkRect . toData+class (Eq a, Ord a, Monoid (Size a), Set (Size a)) => Typeable a where- checkRect (PrimitiveData _) = return []- checkRect (StorableData _ []) = return []- checkRect (StorableData _ as) = do- dims <- mapM checkRect as- guard $ allEqual dims- return (length as : head dims)--+ -- | 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 --- | All supported types of data (nested tuples of storable data)-class (Eq a, Ord a) => Typeable a- where- -- | Gives the representation of the indexing type.- typeOf :: T a -> Tuple StorableType+ -- | Gives the type representation of a storable value.+ typeOf :: Size a -> T a -> Tuple StorableType instance Typeable () where- typeOf = const $ One $ StorableType [] UnitType+ type Size () = ()+ typeOf = typeOfStorable instance Typeable Bool where- typeOf = const $ One $ StorableType [] BoolType+ type Size Bool = ()+ typeOf = typeOfStorable instance Typeable Int where- typeOf = const $ One $ StorableType [] IntType+ type Size Int = Range Integer+ typeOf = typeOfStorable instance Typeable Float where- typeOf = const $ One $ StorableType [] FloatType+ type Size Float = Range Float+ typeOf = typeOfStorable -instance (NaturalT n, Storable a) => Typeable (n :> a)+instance Storable a => Typeable [a] where- typeOf = const $ One $ StorableType (n:dim) t- where- n = fromIntegerT (undefined :: n)- One (StorableType dim t) = typeOf (T::T a)+ type Size [a] = Range Length :> Size a+ typeOf = typeOfStorable instance (Typeable a, Typeable b) => Typeable (a,b) where- typeOf = const $ Tup [typeOf (T::T a), typeOf (T::T b)]+ type Size (a,b) = (Size a, Size b) + typeOf (sa,sb) _ = Tup [typeOf sa (T::T a), typeOf sb (T::T b)]+ instance (Typeable a, Typeable b, Typeable c) => Typeable (a,b,c) where- typeOf = const $ Tup [typeOf (T::T a), typeOf (T::T b), typeOf (T::T c)]+ 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)+ ]+ instance (Typeable a, Typeable b, Typeable c, Typeable d) => Typeable (a,b,c,d) where- typeOf = const $ Tup- [ typeOf (T::T a)- , typeOf (T::T b)- , typeOf (T::T c)- , typeOf (T::T d)- ]+ 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)+ ] --- | Checks if the given type is primitive.-isPrimitive :: Typeable a => T a -> Bool-isPrimitive a = case typeOf a of- One (StorableType [] _) -> True- _ -> False +-- | Default implementation of 'typeOf' for 'Storable' types.+typeOfStorable :: Storable a => Size a -> T a -> Tuple StorableType+typeOfStorable sz = One . storableType sz++class (Num a, Primitive a, Num (Size a)) => Numeric a++instance Numeric Int++instance Numeric Float
+ Feldspar/Haskell.hs view
@@ -0,0 +1,99 @@+-- 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,4 +1,4 @@--- Copyright (c) 2009, ERICSSON AB+-- Copyright (c) 2009-2010, ERICSSON AB -- All rights reserved. -- -- Redistribution and use in source and binary forms, with or without@@ -24,8 +24,8 @@ -- 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. --- | Operations on matrices (nested parallel vectors). All operations in this--- module assume rectangular matrices.+-- | Operations on matrices (doubly-nested parallel vectors). All operations in+-- this module assume rectangular matrices. module Feldspar.Matrix where @@ -33,58 +33,54 @@ import qualified Prelude as P -import Types.Data.Ord- import Feldspar.Prelude import Feldspar.Utils-import Feldspar.Core.Types import Feldspar.Core import Feldspar.Vector -type Matrix m n a = Par m :>> Par n :>> Data a+type Matrix a = Vector (Vector (Data a)) -- | Converts a matrix to a core array.-freezeMatrix :: (NaturalT m, NaturalT n, Storable a) =>- Matrix m n a -> Data (m :> n :> a)-+freezeMatrix :: Storable a => Matrix a -> Data [[a]] freezeMatrix = freezeVector . map freezeVector ----- | Converts a core array to a matrix.-unfreezeMatrix :: (NaturalT m, NaturalT n, Storable a) =>- Data Int -> Data Int -> Data (m :> n :> a) -> Matrix m n a-+-- | 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) ----- | Constructs a matrix.-matrix :: (NaturalT m, NaturalT n, Storable a, ListBased a ~ a) =>- [[a]] -> Matrix m n a-+-- | Constructs a matrix. The elements are stored in a core array.+matrix :: Storable a => [[a]] -> Matrix a matrix as- | allEqual xs = unfreezeMatrix y x $ array as+ | allEqual xs = unfreezeMatrix y x (value as) | otherwise = error "matrix: Not rectangular" where- y = value $ P.length as xs = P.map P.length as+ y = value $ P.length as x = value $ P.head (xs P.++ [0]) -- | Transpose of a matrix-transpose :: Matrix m n a -> Matrix n m a+transpose :: Matrix a -> Matrix a transpose a = Indexed (length $ head a) ixf where- ixf y = Indexed (length a) (\x -> a ! x ! y)+ ixf y = Indexed (length a) $ \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'. + -- XXX Should be written using indexMat.+++ -- | Matrix multiplication-mul :: (Primitive a, Num a) => Matrix m n a -> Matrix n p a -> Matrix m p a+mul :: Numeric a => Matrix a -> Matrix a -> Matrix a mul a b = map (\aRow -> map (scalarProd aRow) b') a where b' = transpose b@@ -92,7 +88,7 @@ -- | Concatenates the rows of a matrix.-flatten :: Matrix m n a -> VectorP (m :* n) a+flatten :: Matrix a -> Vector (Data a) flatten matr = Indexed (m*n) ixf where m = length matr@@ -100,14 +96,15 @@ ixf i = matr ! y ! x where- y = i `div` m- x = i `mod` m+ y = i `div` n+ x = i `mod` n+ -- XXX 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 n n a -> VectorP n a-diagonal m = map (uncurry (!)) $ zip m $ enumFromTo 0 (length m - 1)+diagonal :: Matrix a -> Vector (Data a)+diagonal m = zipWith (!) m (0 ... (length m - 1))
Feldspar/Prelude.hs view
@@ -1,4 +1,4 @@--- Copyright (c) 2009, ERICSSON AB+-- Copyright (c) 2009-2010, ERICSSON AB -- All rights reserved. -- -- Redistribution and use in source and binary forms, with or without@@ -38,6 +38,9 @@ , (<), (>), (<=), (>=) , not, (&&), (||) , min, max+ , (^)+ , div, mod+ , (>>) , maximum, minimum , length , (++)@@ -52,7 +55,5 @@ , map , zipWith , sum- , (^)- , div, mod )
+ Feldspar/Range.hs view
@@ -0,0 +1,403 @@+-- 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 Test.QuickCheck++++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' (Range l u) =+ 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++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+ coarbitrary = error "coarbitrary not defined for (Range a)"++ 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)]++++prop_arith1 :: (forall a . Num a => a -> a) -> Int -> Range Int -> Property+prop_arith1 op x r = (x `inRange` r) ==> (op x `inRange` op r)++++prop_arith2+ :: (forall a . Num a => a -> a -> a)+ -> Int -> Int -> Range Int -> Range Int -> Property++prop_arith2 op x y r1 r2 =+ (inRange x r1 && inRange y r2) ==> (op x y `inRange` 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_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_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 x y (r1::Range Int) (r2::Range Int) =+ (rangeLess r1 r2 && inRange x r1 && inRange y r2) ==> x < y++prop_rangeLessEq x y (r1::Range Int) (r2::Range Int) =+ (rangeLessEq r1 r2 && inRange x r1 && inRange y r2) ==> x <= y++++testAll = do+ myCheck prop_neg+ myCheck prop_add+ myCheck prop_sub+ myCheck prop_mul+ myCheck prop_abs+ myCheck prop_sign+ myCheck prop_abs2+ myCheck prop_fromInteger+ myCheck prop_empty+ myCheck prop_full+ myCheck prop_isEmpty1+ myCheck prop_isEmpty2+ myCheck prop_isFull+ myCheck prop_fullRange+ myCheck prop_range+ -- myCheck prop_rangeByRange+ -- XXX "Arguments exhausted after 0 test"+ -- Something must be wrong with generator...+ myCheck prop_singletonRange1+ myCheck prop_singletonRange2+ myCheck prop_singletonSize+ myCheck prop_subRange+ myCheck prop_emptySubRange1+ myCheck prop_emptySubRange2+ myCheck prop_isNegative+ myCheck prop_rangeGap+ myCheck prop_union1+ myCheck prop_union2+ myCheck prop_union3+ myCheck prop_union4+ myCheck prop_intersect1+ myCheck prop_intersect2+ myCheck prop_intersect3+ myCheck prop_intersect4+ myCheck prop_disjoint+ myCheck prop_rangeLess1+ myCheck prop_rangeLess2+ myCheck prop_rangeLessEq+ where+ myCheck = check defaultConfig {configMaxFail = 100000}+
Feldspar/Utils.hs view
@@ -1,4 +1,4 @@--- Copyright (c) 2009, ERICSSON AB+-- Copyright (c) 2009-2010, ERICSSON AB -- All rights reserved. -- -- Redistribution and use in source and binary forms, with or without@@ -42,12 +42,18 @@ allEqual [] = True allEqual (a:as) = all (==a) as --- | @showSeq open strs close@:+-- | @`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
Feldspar/Vector.hs view
@@ -1,4 +1,4 @@--- Copyright (c) 2009, ERICSSON AB+-- Copyright (c) 2009-2010, ERICSSON AB -- All rights reserved. -- -- Redistribution and use in source and binary forms, with or without@@ -28,198 +28,144 @@ -- ("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".+--+-- Note that the only operations in this module that introduce storage (through+-- core arrays) are+--+-- * 'freezeVector'+--+-- * 'memorize'+--+-- * 'vector'+--+-- * 'unfoldVec'+--+-- * 'unfold'+--+-- * 'scan'+--+-- * 'mapAccum'+--+-- This means that vector operations not involving these operations will be+-- completely \"fused\" without using any intermediate storage.+--+-- Note also that most operations only introduce a small constant overhead on+-- the vector. The exceptions are+--+-- * 'dropWhile'+--+-- * 'fold'+--+-- * 'fold1'+--+-- * Functions that introduce storage (see above)+--+-- * \"Folding\" functions: 'sum', 'maximum', etc.+--+-- These functions introduce overhead that is linear in the length of the+-- 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@. module Feldspar.Vector where import qualified Prelude-import Control.Arrow ((***),(&&&))-import Data.List (unfoldr)+import Control.Arrow ((&&&))+import qualified Data.List -- Only for documentation of 'unfold' import Feldspar.Prelude-import Feldspar.Core.Types-import Feldspar.Core.Expr hiding (index)+import Feldspar.Range+import Feldspar.Core.Expr import Feldspar.Core -- * Types --- | Dynamic size of a vector-type Size = Int- -- | Vector index type Ix = Int --- | Empty type denoting a parallel (random) access pattern for elements in a--- vector. The argument denotes the static size of the vector.-data Par n---- | Empty type denoting a sequential access pattern for elements in a vector.--- The argument denotes the static size of the vector.-data Seq n---- | Symbolic vector. For example,------ > Seq D10 :>> Par D5 :>> Data Int------ is a sequential (symbolic) vector of parallel vectors of integers. The type--- numbers @D10@ and @D5@ denote the /static size/ of the vector, i.e. the--- allocated size of the array used if and when the vector gets written to--- memory (e.g. by 'toPar').------ If it is known that the vector will never be written to memory, it is--- not needed to specify a static size. In that case, it is possible to use @()@--- as the static size type. This way, attempting to write to memory will--- result in a type error.------ The 'Size' argument to the 'Indexed' and 'Unfold' constructors is called the--- /dynamic/ size, since it can vary freely during execution.-data n :>> a- where- Indexed -- Constructor for parallel vectors- :: Data Size- -> (Data Ix -> a) -- A mapping from indexes to elements- -> (Par n :>> a)-- Unfold -- Constructor for sequential vectors- :: Computable s- => Data Size- -> (s -> (a,s)) -- "Step function"- -> s -- Initial state- -> (Seq n :>> a)--infixr 5 :>>---- | Non-nested parallel vector-type VectorP n a = Par n :>> Data a---- | Non-nested sequential vector-type VectorS n a = Seq n :>> Data a------ | Addition for static vector size-type family (:+) a b--type instance (:+) (Dec a) (Dec b) = Dec a :+: Dec b-type instance (:+) () () = ()------ | Multiplication for static vector size-type family (:*) a b+-- | Symbolic vector+data Vector a = Indexed+ { length :: Data Length+ , index :: Data Ix -> a+ } -type instance (:*) (Dec a) (Dec b) = Dec a :*: Dec b-type instance (:*) () () = ()+-- | Short-hand for non-nested parallel vector+type DVector a = Vector (Data a) -- * Construction/conversion --- | A class for generalizing over parallel and sequential vectors.-class AccessPattern t- where- genericVector :: (Par n :>> a) -> (Seq n :>> a) -> (t n :>> a)--instance AccessPattern Par- where- genericVector vecP _ = vecP--instance AccessPattern Seq- where- genericVector _ vecS = vecS---- | Constructs a parallel vector from an index function. The function is--- assumed to be defined for the domain @[0 .. n-1]@, were @n@ is the dynamic--- size.-indexed :: Data Size -> (Data Ix -> a) -> (Par n :>> a)-indexed = Indexed---- | Constructs a sequential vector from a \"step\" function and an initial--- state.-unfold :: Computable s => Data Size -> (s -> (a,s)) -> s -> (Seq n :>> a)-unfold = Unfold--- -- | Converts a non-nested vector to a core vector.-freezeVector :: forall t n a . (NaturalT n, Storable a) =>- (t n :>> Data a) -> Data (n :> a)--freezeVector (Indexed sz ixf) = parallel sz ixf--freezeVector (Unfold sz step s) = snd $ for 0 end (s,arr) body- where- end = value $ fromIntegerT (undefined :: n) - 1- arr = array [] :: Data (n :> a)-- body i (s, arr :: Data (n :> a)) = (s', setIx arr i a)- where- (a,s') = step s+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) +-- | 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. --- | Converts a non-nested core vector to a parallel vector.-unfreezeVector :: (NaturalT n, Storable a, AccessPattern t) =>- Data Size -> Data (n :> a) -> (t n :>> Data a)+indexed :: Data Length -> (Data Ix -> a) -> Vector a+indexed = Indexed -unfreezeVector sz arr = genericVector vec (toSeq 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) where- vec = Indexed sz (getIx arr)-+ l = value $ Prelude.length as+ -- XXX Should be generalized to arbitrary dimensions. +modifyLength :: (Data Length -> Data Length) -> Vector a -> Vector a+modifyLength f vec = vec {length = f (length vec)} --- | Constructs a non-nested vector.-vector :: (NaturalT n, Storable a, AccessPattern t, ListBased a ~ a) =>- [a] -> (t n :>> Data a)- -- (ListBased a ~ a) means no nesting.+setLength :: Data Length -> Vector a -> Vector a+setLength = modifyLength . const -vector as = unfreezeVector sz $ array as+boundVector :: Int -> Vector a -> Vector a+boundVector maxLen = modifyLength (cap r) where- sz = value $ Prelude.length as+ r = negativeRange + singletonRange (fromIntegral maxLen) + 1+ -- XXX fromIntegral might not be needed in future. --- instance (NaturalT n, Storable (Internal a), Computable a) =>--- Computable (Par n :>> a)--- where--- type Internal (Par n :>> a) = (Int, n :> Internal a)---- internalize vec =--- internalize (length vec, freezeVector $ map internalize vec)---- externalize sz_a = map externalize $ unfreezeVector sz a--- where--- sz = externalize $ ref $ GetTuple (T::T D0) sz_a--- a = externalize $ ref $ GetTuple (T::T D1) sz_a- -- XXX This would require first class tuples.--instance (NaturalT n, Storable a, AccessPattern t)- => Computable (t n :>> Data a)+instance Storable a => Computable (Vector (Data a)) where- type Internal (t n :>> Data a) = (Int, n :> Internal (Data a))+ type Internal (Vector (Data a)) = (Length, [Internal (Data a)]) internalize vec = internalize (length vec, freezeVector $ map internalize vec) - externalize sz_a = map externalize $ unfreezeVector sz a+ externalize l_a = map externalize $ unfreezeVector l a where- sz = externalize $ ref $ GetTuple (T::T D0) sz_a- a = externalize $ ref $ GetTuple (T::T D1) sz_a+ l = externalize $ exprToData $ Get21 l_a+ a = externalize $ exprToData $ Get22 l_a -instance- ( NaturalT n1- , NaturalT n2- , Storable a- , AccessPattern t1- , AccessPattern t2- ) =>- Computable (t1 n1 :>> t2 n2 :>> Data a)+instance Storable a => Computable (Vector (Vector (Data a))) where- type Internal (t1 n1 :>> t2 n2 :>> Data a) =- (Int, n1 :> Int, n1 :> n2 :> Internal (Data a))+ type Internal (Vector (Vector (Data a))) =+ (Length, [Length], [[Internal (Data a)]]) internalize vec = internalize ( length vec@@ -229,257 +175,169 @@ externalize inp = map (map externalize . uncurry unfreezeVector)- $ zip sz2sV (unfreezeVector sz1 a)+ $ zip l2sV (unfreezeVector l1 a) where- sz1 = externalize $ ref $ GetTuple (T::T D0) inp- sz2s = externalize $ ref $ GetTuple (T::T D1) inp- a = externalize $ ref $ GetTuple (T::T D2) inp- sz2sV = unfreezeVector sz1 sz2s :: t1 n1 :>> Data Int------ | Convert any vector to a sequential one. This operation is always \"cheap\".-toSeq :: (t n :>> a) -> (Seq n :>> a)-toSeq (Indexed sz ixf) = Unfold sz (\i -> (ixf i, i+1)) 0-toSeq (Unfold sz step s) = Unfold sz step s---- | Changes the static size of a vector.-resize :: NaturalT n => (t m :>> a) -> (t n :>> a)-resize (Indexed sz ixf) = Indexed sz ixf-resize (Unfold sz step s) = Unfold sz step s- -- The NaturalT constraint is needed because otherwise it would be possible to- -- make an existing NaturalT constraint disappear. That would ruin the- -- property that vectors with fully polymorphic sizes do not represent their- -- elements in memory.---- | Convert any non-nested vector to a parallel one with cheap lookups.--- Internally, this is done by writing the vector to memory.-toPar :: (NaturalT n, Storable a) => (t n :>> Data a) -> VectorP n a-toPar vec = unfreezeVector (length vec) $ freezeVector vec+ l1 = externalize $ exprToData $ Get31 inp+ l2s = externalize $ exprToData $ Get32 inp+ a = externalize $ exprToData $ Get33 inp+ l2sV = unfreezeVector l1 l2s -- * Operations --- | Look up an index in a vector. This operation takes linear time for--- sequential vectors.-index :: (t :>> a) -> Data Ix -> a-index (Indexed _ ixf) i = ixf i-index (Unfold _ step s) i = fst $ step $ fst $ while cont body (s,0)- where- cont = (<i) . snd- body = ((snd . step) *** (+1))--instance RandomAccess (Par n :>> a)+instance RandomAccess (Vector a) where- type Elem (Par n :>> a) = a+ type Element (Vector a) = a (!) = index --- | The dynamic size of a vector-length :: (t n :>> a) -> Data Size-length (Indexed sz _) = sz-length (Unfold sz _ _) = sz----(++) :: Computable a => (t m :>> a) -> (t n :>> a) -> (t (m :+ n) :>> a)--Indexed sz1 ixf1 ++ Indexed sz2 ixf2 = Indexed (sz1+sz2) ixf- where- ixf i = ifThenElse (i < sz1) ixf1 (ixf2 . subtract sz1) i--Unfold sz1 step1 s1 ++ Unfold sz2 step2 s2 = Unfold (sz1+sz2) step (0, (s1,s2))+-- | 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- step (n, (s1',s2')) = n<sz1 ?- ( let (a,s1'') = step1 s1' in (a, (n+1, (s1'', s2')))- , let (a,s2'') = step2 s2' in (a, (n+1, (s1', s2'')))- )+ ixf i = ifThenElse (i < l1) ixf1 (ixf2 . subtract l1) i infixr 5 ++ ---take :: Data Int -> (t n :>> a) -> (t n :>> a)--take n (Indexed sz ixf) = Indexed sz' ixf- where- sz' = min sz n--take n (Unfold sz step s) = Unfold sz' step s- where- sz' = min sz n----drop :: Data Int -> (t n :>> a) -> (t n :>> a)--drop n (Indexed sz ixf) = Indexed sz' (\x -> ixf (x+n))- where- sz' = max 0 (sz-n)--drop n (Unfold sz step s) = Unfold sz' step s'- where- sz' = max 0 (sz-n)- s' = for 0 (n-1) s (\_ -> snd . step)--+take :: Data Int -> Vector a -> Vector a+take n (Indexed l ixf) = Indexed (minX n l) ixf -dropWhile :: (a -> Data Bool) -> (t n :>> a) -> (t n :>> a)+drop :: Data Int -> Vector a -> Vector a+drop n (Indexed l ixf) = Indexed (maxX 0 (l-n)) (\x -> ixf (x+n)) -dropWhile cont vec@(Indexed _ _) = drop i vec+dropWhile :: (a -> Data Bool) -> Vector a -> Vector a+dropWhile cont vec = drop i vec where i = while ((< length vec) &&* (cont . (vec !))) (+1) 0 -dropWhile cont vec@(Unfold sz step s) = Unfold (sz-i) step s'- where- (s',i) = while condition (\(s,i) -> (snd $ step s, i+1)) (s,0)- where- condition = ((\(s,i) -> i <= length vec) &&* (cont.fst.step.fst))----splitAt :: Data Int -> (t n :>> a) -> (t n :>> a, t n :>> a)+splitAt :: Data Int -> Vector a -> (Vector a, Vector a) splitAt n vec = (take n vec, drop n vec) -head :: (t n :>> a) -> a-head = flip index 0+head :: Vector a -> a+head = (!0) -last :: (t n :>> a) -> a-last vec = index vec (length vec - 1)+last :: Vector a -> a+last vec = vec ! (length vec - 1) -tail :: (t n :>> a) -> (t n :>> a)+tail :: Vector a -> Vector a tail = drop 1 -init :: (t n :>> a) -> (t n :>> a)+init :: Vector a -> Vector a init vec = take (length vec - 1) vec --- | Like Haskell's 'tails', but does not include the empty vector. This is--- actually just to make the types simpler (the result is square).-tails :: AccessPattern u => (t n :>> a) -> (u n :>> t n :>> a)-tails vec = genericVector vecP vecS- where- sz = length vec- vecP = Indexed sz (\n -> drop n vec)- vecS = Unfold sz (\n -> (drop n vec, n+1)) 0+tails :: Vector a -> Vector (Vector a)+tails vec = Indexed (length vec + 1) (\n -> drop n vec) --- | Like Haskell's 'inits', but does not include the empty vector. This is--- actually just to make the types simpler (the result is square).-inits :: AccessPattern u => (t n :>> a) -> (u n :>> t n :>> a)-inits vec = genericVector vecP vecS- where- sz = length vec- vecP = Indexed sz (\n -> take n vec)- vecS = Unfold sz (\n -> (take n vec, n+1)) 0+inits :: Vector a -> Vector (Vector a)+inits vec = Indexed (length vec + 1) (\n -> take n vec) -permute :: (Data Size -> Data Ix -> Data Ix) -> ((Par n :>> a) -> (Par n :>> a))-permute perm (Indexed sz ixf) = Indexed sz (ixf . perm sz)+inits1 :: Vector a -> Vector (Vector a)+inits1 = tail . inits -reverse :: (Par n :>> a) -> (Par n :>> a)-reverse = permute $ \sz i -> sz-1-i+permute :: (Data Length -> Data Ix -> Data Ix) -> (Vector a -> Vector a)+permute perm (Indexed l ixf) = Indexed l (ixf . perm l) -replicate :: AccessPattern t => Data Int -> a -> (t n :>> a)-replicate n a = genericVector vecP vecS- where- vecP = Indexed n (const a)- vecS = Unfold n (const (a, unit)) unit+reverse :: Vector a -> Vector a+reverse = permute $ \l i -> l-1-i -enumFromTo :: AccessPattern t => Data Int -> Data Int -> (t n :>> Data Int)-enumFromTo m n = genericVector vecP vecS- where- sz = n-m+1- vecP = indexed sz (+m)- vecS = unfold sz (\x -> (x,x+1)) m+replicate :: Data Int -> a -> Vector a+replicate n a = Indexed n (const a) +enumFromTo :: Data Int -> Data Int -> Vector (Data Int)+enumFromTo m n = Indexed (n-m+1) (+m)+ -- XXX Type should be generalized. +(...) :: Data Int -> Data Int -> Vector (Data Int)+(...) = enumFromTo -zip :: (t n :>> a) -> (t n :>> b) -> (t n :>> (a,b))+zip :: Vector a -> Vector b -> Vector (a,b)+zip (Indexed l1 ixf1) (Indexed l2 ixf2) = Indexed (min l1 l2) (ixf1 &&& ixf2) -zip (Indexed sz1 ixf1) (Indexed sz2 ixf2) =- Indexed (min sz1 sz2) (ixf1 &&& ixf2)+unzip :: Vector (a,b) -> (Vector a, Vector b)+unzip (Indexed l ixf) = (Indexed l (fst.ixf), Indexed l (snd.ixf)) -zip (Unfold sz1 step1 s1) (Unfold sz2 step2 s2) = Unfold sz step (s1, s2)- where- sz = min sz1 sz2- step (s1,s2) = ((a,b), (s1',s2'))- where- (a,s1') = step1 s1- (b,s2') = step2 s2+map :: (a -> b) -> Vector a -> Vector b+map f (Indexed l ixf) = Indexed l (f . ixf) +zipWith :: (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)) -unzip :: (t n :>> (a,b)) -> (t n :>> a, t n :>> b)+-- | Corresponds to 'foldl1'.+fold1 :: Computable a => (a -> a -> a) -> Vector a -> a+fold1 f a = fold f (head a) a -unzip (Indexed sz ixf) = (Indexed sz (fst.ixf), Indexed sz (snd.ixf)) -unzip (Unfold sz step s) =- (Unfold sz ((fst***id).step) s, Unfold sz ((snd***id).step) s) +-- | Like 'unfoldCore', but for symbolic vectors. The output elements are stored+-- in a core vector.+unfoldVec+ :: (Computable state, Storable a)+ => Data Length+ -> state+ -> (Data Int -> state -> (Data a, state))+ -> (Vector (Data a), state) +unfoldVec l init step = (unfreezeVector l arr, final)+ where+ (arr,final) = unfoldCore l init step -map :: (a -> b) -> ((t n :>> a) -> (t n :>> b))-map f (Indexed sz ixf) = Indexed sz (f . ixf)-map f (Unfold sz step s) = Unfold sz ((f *** id) . step) s -zipWith :: (a -> b -> c) -> (t n :>> a) -> (t n :>> b) -> (t n :>> c)-zipWith f aVec bVec = map (uncurry f) $ zip aVec bVec +-- | Somewhat similar to Haskell's 'Data.List.unfoldr'. The output elements are+-- stored in a core vector.+--+-- @`unfold` 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 state.+unfold :: (Computable state, Storable a) =>+ Data Length -> state -> (state -> (Data a, state)) -> Vector (Data a) +unfold l init = fst . unfoldVec l init . const --- | Corresponds to Haskell's @foldl@.-fold :: Computable a => (a -> b -> a) -> a -> (t n :>> b) -> a -fold f x (Unfold sz step s) = fst $ for 0 (sz-1) (x,s) body- where- body i (m,n) = (f m m', n')- where- (m',n') = step n -fold f x (Indexed sz ixf) = for 0 (sz-1) x (\i s -> f s (ixf i))--+-- | Corresponds to 'scanl'. The output elements are stored in a core vector.+scan :: (Storable a, Computable b) =>+ (Data a -> b -> Data a) -> Data a -> Vector b -> Vector (Data a) --- | Corresponds to Haskell's @foldl1@.-fold1 :: Computable a => (a -> a -> a) -> (t n :>> a) -> a-fold1 f a = fold f (head a) a+scan f a vec = fst $ unfoldVec (length vec + 1) a $ \i a -> (a, f a (vec!i)) --- | Corresponds to Haskell's @scanl@.-scan :: Computable a => (a -> b -> a) -> a -> (t n :>> b) -> (Seq n :>> a)--scan f a (Indexed sz ixf) = Unfold sz step (0,a)- where- step (i,a) = let a' = f a (ixf i) in (a', (i+1, a'))+-- | Corresponds to 'Data.List.mapAccumL'. The output elements are stored in a+-- core vector.+mapAccum :: (Storable a, Computable acc, Storable b)+ => (acc -> Data a -> (acc, Data b))+ -> acc -> Vector (Data a) -> (acc, Vector (Data b)) -scan f a (Unfold sz step s) = Unfold sz step' (s,a)+mapAccum f init vecA = (final,vecB) where- step' (s,a) = (a', (s',a'))- where- (b,s') = step s- a' = f a b+ (vecB,final) = unfoldVec (length vecA) init $ \i acc ->+ let (acc',b) = f acc (vecA!i) in (b,acc') --- | Corresponds to Haskell's @scanl1@.-scan1 :: Computable a => (a -> a -> a) -> (t n :>> a) -> (Seq n :>> a)-scan1 f vec = scan f (head vec) (tail vec)--sum :: (Num a, Computable a) => (t n :>> a) -> a+sum :: (Num a, Computable a) => Vector a -> a sum = fold (+) 0 -maximum :: Storable a => (t n :>> Data a) -> Data a+maximum :: Storable a => Vector (Data a) -> Data a maximum = fold1 max -minimum :: Storable a => (t n :>> Data a) -> Data a+minimum :: Storable a => Vector (Data a) -> Data a minimum = fold1 min -- -- | Scalar product of two vectors-scalarProd :: (Primitive a, Num a) =>- (t n :>> Data a) -> (t n :>> Data a) -> Data a-+scalarProd :: Numeric a => Vector (Data a) -> Vector (Data a) -> Data a scalarProd a b = sum (zipWith (*) a b)
LICENSE view
@@ -1,4 +1,4 @@-Copyright (c) 2009, ERICSSON AB+Copyright (c) 2009-2010, ERICSSON AB All rights reserved. Redistribution and use in source and binary forms, with or without
feldspar-language.cabal view
@@ -1,12 +1,12 @@ name: feldspar-language-version: 0.1+version: 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, ERICSSON AB+copyright: Copyright (c) 2009-2010, ERICSSON AB author: Functional programming group at Chalmers University of Technology maintainer: Emil Axelsson <emax@chalmers.se> license: BSD3@@ -21,32 +21,35 @@ exposed-modules: Feldspar.Prelude Feldspar.Utils+ Feldspar.Haskell+ Feldspar.Range Feldspar.Core.Types- Feldspar.Core.Haskell- Feldspar.Core.Graph- Feldspar.Core.Show Feldspar.Core.Ref Feldspar.Core.Expr+ Feldspar.Core.Graph+ Feldspar.Core.Show+ Feldspar.Core.Reify Feldspar.Core.Functions Feldspar.Core Feldspar.Vector Feldspar.Matrix Feldspar - build-depends: base >= 3 && < 4, containers, directory, mtl, process, tfp+ build-depends:+ base >= 3 && < 4,+ containers,+ mtl,+ QuickCheck >= 1.2 && < 2 extensions:- EmptyDataDecls FlexibleInstances FlexibleContexts GADTs- MultiParamTypeClasses NoMonomorphismRestriction OverlappingInstances PatternGuards Rank2Types ScopedTypeVariables- StandaloneDeriving TypeFamilies TypeOperators TypeSynonymInstances