feldspar-language-0.2: A functional embedded language for DSP and parallelism




A high-level interface to the operations in the core language (Feldspar.Core). Many of the functions defined here are imitations of Haskell's list operations, and to a first approximation they behave accordingly.

A symbolic vector (Vector) can be thought of as a representation of a parallel core array. This view is made precise by the function freezeVector, which converts a symbolic vector to a core vector using parallel.

Vector is instantiated under the Computable class, which means that symbolic vectors can be used quite seamlessly with the interface in Feldspar.Core.

Note that the only operations in this module that introduce storage (through core arrays) are

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

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.



type Ix = IntSource

Vector index

data Vector a Source

Symbolic vector




length :: Data Length
index :: Data Ix -> a

type DVector a = Vector (Data a)Source

Short-hand for non-nested parallel vector


freezeVector :: Storable a => Vector (Data a) -> Data [a]Source

Converts a non-nested vector to a core vector.

unfreezeVector :: Storable a => Data Length -> Data [a] -> Vector (Data a)Source

Converts a non-nested core vector to a parallel vector.

memorize :: Storable a => Vector (Data a) -> Vector (Data a)Source

Optimizes vector lookup by computing all elements and storing them in a core array.

vector :: Storable a => [a] -> Vector (Data a)Source

Constructs a non-nested vector. The elements are stored in a core vector.


(++) :: Computable a => Vector a -> Vector a -> Vector aSource

Introduces an ifThenElse for each element; use with care!

dropWhile :: (a -> Data Bool) -> Vector a -> Vector aSource

head :: Vector a -> aSource

last :: Vector a -> aSource

zip :: Vector a -> Vector b -> Vector (a, b)Source

unzip :: Vector (a, b) -> (Vector a, Vector b)Source

map :: (a -> b) -> Vector a -> Vector bSource

zipWith :: (a -> b -> c) -> Vector a -> Vector b -> Vector cSource

fold :: Computable a => (a -> b -> a) -> a -> Vector b -> aSource

Corresponds to foldl.

fold1 :: Computable a => (a -> a -> a) -> Vector a -> aSource

Corresponds to foldl1.

unfoldVec :: (Computable state, Storable a) => Data Length -> state -> (Data Int -> state -> (Data a, state)) -> (Vector (Data a), state)Source

Like unfoldCore, but for symbolic vectors. The output elements are stored in a core vector.

unfold :: (Computable state, Storable a) => Data Length -> state -> (state -> (Data a, state)) -> Vector (Data a)Source

Somewhat similar to Haskell's 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.

scan :: (Storable a, Computable b) => (Data a -> b -> Data a) -> Data a -> Vector b -> Vector (Data a)Source

Corresponds to scanl. 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))Source

Corresponds to mapAccumL. The output elements are stored in a core vector.

sum :: (Num a, Computable a) => Vector a -> aSource

scalarProd :: Numeric a => Vector (Data a) -> Vector (Data a) -> Data aSource

Scalar product of two vectors