raw-feldspar-0.1: Resource-Aware Feldspar

Feldspar.Data.Vector

Description

This module gives a library of different vector types.

# Basic use

A typical 1-dimensional vector computation goes as follows:

1. Start with a Manifest vector (one that is refers directly to an array in memory).
2. Apply operations overloaded by Pully (e.g. take, drop, map, reverse). The result is one or more Pull vectors.
3. If the previous step resulted in several parts, assemble them using operations overloaded by Pushy (e.g. ++). The result is a Push vector.
4. Write the vector to memory using manifest or manifestFresh.

(Of course, there are many variations on this general scheme.)

Note that it's possible to skip step #2 or #3 above. For example, it's possible to directly concatenate two Manifest vectors using ++, and manifest can be applied directly to a Pull vector (or even to a Manifest, in which case it becomes a no-op).

# Efficiency and fusion

The library has been designed so that all operations fuse together without creating any intermediate structures in memory. The only exception is the operations that produce Manifest or Manifest2 vectors (manifest, manifest2, etc.).

For example, the following function only creates a single structure in memory even though it seemingly generates several intermediate vectors:

f :: (Num a, Syntax a, MonadComp m) => Pull a -> m (Manifest a)
f = manifestFresh . reverse . map (*2) . take 10


Furthermore, the operations associated with each type of vector are restricted to operations that can be carried out efficiently for that type. For example, although it would be possible to implement append for Pull vectors, doing so results in unnecessary conditionals in the generated code. Therefore, the ++ operator returns a Push vector, which ensures efficient generated code.

In many cases, the cycle Manifest -> Pull -> Push -> Manifest is guided by the types of the operations involved. However, there are cases when it's preferable to shortcut the cycle even when it's not demanded by the types. The reason is that fusion can lead to duplicated computations.

Here is an example where fusion leads to redundant computations:

bad = do
v :: DManifest Int32 <- readStd  -- Read from stdin
let v'  = map heavy v
v'' = v' ++ reverse v'
writeStd v''                     -- Write to stdout


Since v' is used twice in defining v'', the mapping of the heavy computation will be done twice when writing v'' to the output. One way to prevent this is to perform the heavy mapping once, store the result in memory, and define v'' from the stored vector:

good = do
v :: DManifest Int32 <- readStd  -- Read from stdin
v' <- manifestFresh $map heavy v let v'' = v' ++ reverse v' writeStd v'' -- Write to stdout  Even though the examples are called bad and good, there's not a clear-cut answer to which version is best. It could depend on whether time or memory is the most scarce resource. This library leaves the decision in the hands of the programmer. # Working with matrices 2-dimensional matrix computations can follow a scheme similar to the above by using the types Manifest2, Pull2 and Push2 and the corresponding operations. A quite common situation is the need to apply an operation on each row or column of a matrix. Operating on the rows can be done by a combination of exposeRows and hideRows. For example, this function reverses each row in a matrix: revEachRow :: MonadComp m => Pull2 a -> Push2 m a revEachRow mat = hideRows (numCols mat)$ map reverse $exposeRows mat  exposeRows takes a Pully2 matrix and turns it into Pull (Pull a) i.e. a vector of row vectors. map is used to apply reverse to each row. Finally, hideRows turns the nested vector it back into a matrix, of type Push2. Note that hideRows generally cannot know the length of the rows, so this number has to be provided as its first argument. When compiling with assertions, it will be checked at runtime that the length of each row is equal to the given length. In order to operate on the columns instead of the rows, just apply transpose on the original matrix. This operation will fuse with the rest of the computation. It gets a bit more complicated when the operation applied to each row is effectful. For example, the operation may have to use manifest internally giving it a monadic result type. In such situations, the function sequens is helpful. It is a bit similar to the standard function sequence for lists, execept that it converts Push m (m a) into Push m a; i.e. it embeds the effect into the resulting Push vector. Here is a version of the previous example where the row operation is effectful (due to manifestFresh) and sequens is inserted to embed the effects: revEachRowM :: (Syntax a, MonadComp m) => Pull2 a -> Push2 m a revEachRowM mat = hideRows (numCols mat)$ sequens
$map (manifestFresh . reverse)$ exposeRows mat



Note that sequens is generally a dangerous function due to the hiding of effects inside the resulting vector. These effects may be (seemingly) randomly interleaved with other effects when the vector is used. However, the above example is fine, since manifestFresh allocates a fresh array for the storage, so its effects cannot be observed from the outside.

The comments to Push elaborate more on the semantics of push vectors with interleaved effects.

Synopsis

# 1-dimensional manifest vectors

type Manifest = IArr Source #

A 1-dimensional vector with a concrete representation in memory

There are two main reasons to use Manifest when possible instead of Pull:

• The operations of the Manifestable class are more efficient for Manifest. They either result in a no-op or an efficient memory-copy (instead of a copying loop).
• Manifest can be freely converted to/from a 2-dimensional structure using nest and unnest. Note that the representation of Manifest2 is Nest (Manifest a).

type DManifest a = DIArr a Source #

Manifest vector specialized to Data elements

listManifest :: (Syntax a, MonadComp m) => [a] -> m (Manifest a) Source #

Make a Manifest vector from a list of values

# 2-dimensional manifest vectors

type Manifest2 a = Nest (Manifest a) Source #

A 2-dimensional vector with a concrete representation in memory

type DManifest2 a = Manifest2 (Data a) Source #

Manifest2 vector specialized to Data elements

# 1-dimensional pull vectors

data Pull a where Source #

1-dimensional pull vector: a vector representation that supports random access and fusion of operations

Constructors

 Pull :: Data Length -> (Data Index -> a) -> Pull a

Instances

 Source # Methodsfmap :: (a -> b) -> Pull a -> Pull b #(<$) :: a -> Pull b -> Pull a # MonadComp m => Manifestable m (Pull a) a Source # Methodsmanifest :: Arr a -> Pull a -> m (Manifest a) Source #manifestFresh :: Pull a -> m (Manifest a) Source #manifestStore :: Arr a -> Pull a -> m () Source # MonadComp m => Pushy2 m (Pull a) a Source # MethodstoPush2 :: Pull a -> Push2 m a Source # MonadComp m => Pushy m (Pull a) a Source # MethodstoPush :: Pull a -> Push m a Source # Slicable (Pull a) Source # Methodsslice :: Data Index -> Data Length -> Pull a -> Pull a Source # Finite (Pull a) Source # Methods Indexed (Pull a) Source # Associated Typestype IndexedElem (Pull a) :: * Source # Methods(!) :: Pull a -> Data Index -> IndexedElem (Pull a) Source # (Syntax a, BulkTransferable a, (~) * (ContainerType a) (Arr a)) => Transferable (Pull a) Source # Associated Typestype SizeSpec (Pull a) :: * Source # MethodscalcChanSize :: proxy (Pull a) -> SizeSpec (Pull a) -> ChanSize * Data PrimType' Length Source #newChan :: SizeSpec (Pull a) -> Run (Chan * * Uncloseable (Pull a)) Source #readChan :: Chan * * t (Pull a) -> Run (Pull a) Source #untypedReadChan :: Chan * * t c -> Run (Pull a) Source #writeChan :: Chan * * t (Pull a) -> Pull a -> Run (Data Bool) Source #untypedWriteChan :: Chan * * t c -> Pull a -> Run (Data Bool) Source # (Syntax a, MarshalHaskell (Internal a), MarshalFeld a) => MarshalFeld (Pull a) Source # Associated Typestype HaskellRep (Pull a) :: * Source # Methodsfwrite :: Handle -> Pull a -> Run () Source #fread :: Handle -> Run (Pull a) Source # Finite2 (Pull a) Source # Treated as a row vector Methodsextent2 :: Pull a -> (Data Length, Data Length) Source # Syntax a => Storable (Pull a) Source # Associated Typestype StoreRep (Pull a) :: * Source #type StoreSize (Pull a) :: * Source # MethodsnewStoreRep :: MonadComp m => proxy (Pull a) -> StoreSize (Pull a) -> m (StoreRep (Pull a)) Source #initStoreRep :: MonadComp m => Pull a -> m (StoreRep (Pull a)) Source #readStoreRep :: MonadComp m => StoreRep (Pull a) -> m (Pull a) Source #unsafeFreezeStoreRep :: MonadComp m => StoreRep (Pull a) -> m (Pull a) Source #writeStoreRep :: MonadComp m => StoreRep (Pull a) -> Pull a -> m () Source # ViewManifest (Pull a) a Source # MethodsviewManifest :: Pull a -> Maybe (Manifest a) Source # Pully2 (Pull a) a Source # Convert to a Pull2 with a single row MethodstoPull2 :: Pull a -> Pull2 a Source # type IndexedElem (Pull a) Source # type IndexedElem (Pull a) = a type SizeSpec (Pull a) Source # type SizeSpec (Pull a) = VecChanSizeSpec (SizeSpec a) type HaskellRep (Pull a) Source # type HaskellRep (Pull a) = HaskellRep (Manifest a) type StoreRep (Pull a) Source # type StoreRep (Pull a) = (DRef Length, Arr a) type StoreSize (Pull a) Source # type StoreSize (Pull a) = Data Length type DPull a = Pull (Data a) Source # Pull vector specialized to Data elements data VecChanSizeSpec lenSpec Source # Constructors  VecChanSizeSpec (Data Length) lenSpec ofLength :: Data Length -> lenSpec -> VecChanSizeSpec lenSpec Source # class (Indexed vec, Finite vec, IndexedElem vec ~ a) => Pully vec a Source # Data structures that are Pull-like (i.e. support ! and length) Instances  (Indexed vec, Finite vec, (~) * (IndexedElem vec) a) => Pully vec a Source # toPull :: Pully vec a => vec -> Pull a Source # Convert a vector to Pull ## Operations head :: Pully vec a => vec -> a Source # Take the head of a non-empty vector tail :: Pully vec a => vec -> Pull a Source # take :: Pully vec a => Data Length -> vec -> Pull a Source # drop :: Pully vec a => Data Length -> vec -> Pull a Source # tails :: Pully vec a => vec -> Pull (Pull a) Source # inits :: Pully vec a => vec -> Pull (Pull a) Source # inits1 :: Pully vec a => vec -> Pull (Pull a) Source # map :: Pully vec a => (a -> b) -> vec -> Pull b Source # zip :: (Pully vec1 a, Pully vec2 b) => vec1 -> vec2 -> Pull (a, b) Source # backPermute :: Pully vec a => (Data Length -> Data Index -> Data Index) -> vec -> Pull a Source # Back-permute a Pull vector using an index mapping. The supplied mapping must be a bijection when restricted to the domain of the vector. This property is not checked, so use with care. reverse :: Pully vec a => vec -> Pull a Source # zipWith :: (Pully vec1 a, Pully vec2 b) => (a -> b -> c) -> vec1 -> vec2 -> Pull c Source # fold :: (Syntax a, Pully vec a) => (a -> a -> a) -> a -> vec -> a Source # Left fold of a vector fold1 :: (Syntax a, Pully vec a) => (a -> a -> a) -> vec -> a Source # Left fold of a non-empty vector sum :: (Pully vec a, Syntax a, Num a) => vec -> a Source # scProd :: (Num a, Syntax a, Pully vec1 a, Pully vec2 a) => vec1 -> vec2 -> a Source # Scalar product # 2-dimensional pull vectors data Pull2 a where Source # 2-dimensional pull vector: a vector representation that supports random access and fusion of operations Constructors  Pull2 :: Data Length -> Data Length -> (Data Index -> Data Index -> a) -> Pull2 a Instances  Source # Methodsfmap :: (a -> b) -> Pull2 a -> Pull2 b #(<$) :: a -> Pull2 b -> Pull2 a # MonadComp m => Manifestable2 m (Pull2 a) a Source # Methodsmanifest2 :: Arr a -> Pull2 a -> m (Manifest2 a) Source #manifestFresh2 :: Pull2 a -> m (Manifest2 a) Source #manifestStore2 :: Arr a -> Pull2 a -> m () Source # MonadComp m => Pushy2 m (Pull2 a) a Source # MethodstoPush2 :: Pull2 a -> Push2 m a Source # Source # Take a slice of the rows Methodsslice :: Data Index -> Data Length -> Pull2 a -> Pull2 a Source # Finite (Pull2 a) Source # length gives number of rows Methods Indexed (Pull2 a) Source # Indexing the rows Associated Typestype IndexedElem (Pull2 a) :: * Source # Methods(!) :: Pull2 a -> Data Index -> IndexedElem (Pull2 a) Source # (Syntax a, MarshalHaskell (Internal a), MarshalFeld a) => MarshalFeld (Pull2 a) Source # Associated Typestype HaskellRep (Pull2 a) :: * Source # Methodsfwrite :: Handle -> Pull2 a -> Run () Source #fread :: Handle -> Run (Pull2 a) Source # Finite2 (Pull2 a) Source # Methodsextent2 :: Pull2 a -> (Data Length, Data Length) Source # ViewManifest2 (Pull2 a) a Source # Methods Pully2 (Pull2 a) a Source # MethodstoPull2 :: Pull2 a -> Pull2 a Source # type IndexedElem (Pull2 a) Source # type IndexedElem (Pull2 a) = Pull a type HaskellRep (Pull2 a) Source # type HaskellRep (Pull2 a) = HaskellRep (Manifest2 a)

type DPull2 a = Pull2 (Data a) Source #

Pull2 vector specialized to Data elements

class Pully2 vec a | vec -> a where Source #

Vectors that can be converted to Pull2

Minimal complete definition

toPull2

Methods

toPull2 :: vec -> Pull2 a Source #

Convert a vector to Pull2

Instances

 (Indexed vec, Slicable vec, (~) * (IndexedElem vec) a, Syntax a) => Pully2 (Nest vec) a Source # MethodstoPull2 :: Nest vec -> Pull2 a Source # Pully2 (Pull2 a) a Source # MethodstoPull2 :: Pull2 a -> Pull2 a Source # Pully2 (Pull a) a Source # Convert to a Pull2 with a single row MethodstoPull2 :: Pull a -> Pull2 a Source # Syntax a => Pully2 (Manifest a) a Source # Convert to a Pull2 with a single row MethodstoPull2 :: Manifest a -> Pull2 a Source #

## Operations

toPull2' :: Pully2 vec a => vec -> Pull2 a Source #

Transposed version of toPull. Can be used to e.g. turn a Pull into a column of a matrix

Arguments

 :: (Pully vec1 vec2, Pully vec2 a) => Data Length Length of inner vectors -> vec1 -> Pull2 a

Turn a vector of rows into a 2-dimensional vector. All inner vectors are assumed to have the given length, and this assumption is not checked by assertions. If types permit, it is preferable to use hideRows, which does check the lengths.

exposeRows :: Pully2 vec a => vec -> Pull (Pull a) Source #

Expose the rows in a Pull2 by turning it into a vector of rows

transpose :: Pully2 vec a => vec -> Pull2 a Source #

Transpose of a matrix

toRowVec :: Pully vec a => vec -> Pull2 a Source #

fromRowVec :: Pully2 vec a => vec -> Pull a Source #

toColVec :: Pully vec a => vec -> Pull2 a Source #

fromColVec :: Pully2 vec a => vec -> Pull a Source #

matMul :: (Pully2 vec1 a, Pully2 vec2 a, Num a, Syntax a) => vec1 -> vec2 -> Pull2 a Source #

Matrix multiplication

# 1-dimensional push vectors

data Push m a where Source #

1-dimensional push vector: a vector representation that supports nested write patterns (e.g. resulting from concatenation) and fusion of operations

If it is the case that dumpPush v (\_ _ -> return ()) has the same behavior as return (), i.e., the vector does not have any embedded side effects, we can regard Push as a pure data structure with the denotation of a finite list.

However, Push is commonly used to assemble data after splitting it up and performing some operations on the parts. We want to be able to use Push even if the operation involved has side effects. The function sequens can be used to embed effects into a Push vector.

Push vectors with embedded effects can often be considered to be denoted by M [a], where M is some suitable monad. That is, the vector performs some effects and produces a finite list of values as a result. This denotation is enough to explain e.g. why

return (v ++ v)


is different from

do v' <- manifestFresh v
return (v' ++ v')


(The former duplicates the embedded effects while the latter only performs the effects once.)

However, this denotation is not enough to model dumpPush, which allows a write method to be interleaved with the embedded effects. Even a function such as manifest can to some extent be used observe the order of effects (if the array argument to manifest is also updated by the internal effects).

Conclusion:

• You can normally think of Push a as denoting M [a] (finite list)
• Make sure to pass a free array as argument to manifest
• Avoid using dumpPush unless you know that it's safe

Constructors

 Push :: Data Length -> ((Data Index -> a -> m ()) -> m ()) -> Push m a

Instances

 (MonadComp m1, (~) (* -> *) m1 m2) => Manifestable m1 (Push m2 a) a Source # Methodsmanifest :: Arr a -> Push m2 a -> m1 (Manifest a) Source #manifestFresh :: Push m2 a -> m1 (Manifest a) Source #manifestStore :: Arr a -> Push m2 a -> m1 () Source # (~) (* -> *) m1 m2 => Pushy m1 (Push m2 a) a Source # MethodstoPush :: Push m2 a -> Push m1 a Source # Functor (Push m) Source # Methodsfmap :: (a -> b) -> Push m a -> Push m b #(<$) :: a -> Push m b -> Push m a # Source # This instance behaves like the list instance:pure x = [x] fs <*> xs = [f x | f <- fs, x <- xs] Methodspure :: a -> Push m a #(<*>) :: Push m (a -> b) -> Push m a -> Push m b #(*>) :: Push m a -> Push m b -> Push m b #(<*) :: Push m a -> Push m b -> Push m a # Finite (Push m a) Source # Methodslength :: Push m a -> Data Length Source # (Syntax a, MarshalHaskell (Internal a), MarshalFeld a, (~) (* -> *) m Run) => MarshalFeld (Push m a) Source # Associated Typestype HaskellRep (Push m a) :: * Source # Methodsfwrite :: Handle -> Push m a -> Run () Source #fread :: Handle -> Run (Push m a) Source # Finite2 (Push m a) Source # Treated as a row vector Methodsextent2 :: Push m a -> (Data Length, Data Length) Source # Syntax a => Storable (Push Comp a) Source # Associated Typestype StoreRep (Push Comp a) :: * Source #type StoreSize (Push Comp a) :: * Source # MethodsnewStoreRep :: MonadComp m => proxy (Push Comp a) -> StoreSize (Push Comp a) -> m (StoreRep (Push Comp a)) Source #initStoreRep :: MonadComp m => Push Comp a -> m (StoreRep (Push Comp a)) Source #readStoreRep :: MonadComp m => StoreRep (Push Comp a) -> m (Push Comp a) Source #unsafeFreezeStoreRep :: MonadComp m => StoreRep (Push Comp a) -> m (Push Comp a) Source #writeStoreRep :: MonadComp m => StoreRep (Push Comp a) -> Push Comp a -> m () Source # ViewManifest (Push m a) a Source # MethodsviewManifest :: Push m a -> Maybe (Manifest a) Source # type HaskellRep (Push m a) Source # type HaskellRep (Push m a) = HaskellRep (Manifest a) type StoreRep (Push Comp a) Source # type StoreRep (Push Comp a) = (DRef Length, Arr a) type StoreSize (Push Comp a) Source # type StoreSize (Push Comp a) = Data Length type DPush m a = Push m (Data a) Source # Push vector specialized to Data elements class Pushy m vec a | vec -> a where Source # Vectors that can be converted to Push Minimal complete definition toPush Methods toPush :: vec -> Push m a Source # Convert a vector to Push Instances  MonadComp m => Pushy m (Pull a) a Source # MethodstoPush :: Pull a -> Push m a Source # (Syntax a, MonadComp m) => Pushy m (Manifest a) a Source # MethodstoPush :: Manifest a -> Push m a Source # (~) (* -> *) m1 m2 => Pushy m1 (Push m2 a) a Source # MethodstoPush :: Push m2 a -> Push m1 a Source # toPushM :: (Pushy m vec a, Monad m) => vec -> m (Push m a) Source # A version of toPush that constrains the m argument of Push to that of the monad in which the result is returned. This can be a convenient way to avoid unresolved overloading. Arguments  :: Push m a Vector to dump -> (Data Index -> a -> m ()) Function that writes one element -> m () Dump the contents of a Push vector ## Operations listPush :: Monad m => [a] -> Push m a Source # Create a Push vector from a list of elements (++) :: (Pushy m vec1 a, Pushy m vec2 a, Monad m) => vec1 -> vec2 -> Push m a Source # Append two vectors to make a Push vector Arguments  :: (Pushy m vec1 vec2, Pushy m vec2 a, MonadComp m) => Data Length Length of inner vectors -> vec1 -> Push m a flatten :: Pushy2 m vec a => vec -> Push m a Source # sequens :: (Pushy m vec (m a), Monad m) => vec -> Push m a Source # Embed the effects in the elements into the internal effects of a Push vector WARNING: This function should be used with care, since it allows hiding effects inside a vector. These effects may be (seemingly) randomly interleaved with other effects when the vector is used. The name sequens has to do with the similarity to the standard function sequence. forwardPermute :: Pushy m vec a => (Data Length -> Data Index -> Data Index) -> vec -> Push m a Source # Forward-permute a Push vector using an index mapping. The supplied mapping must be a bijection when restricted to the domain of the vector. This property is not checked, so use with care. # 2-dimensional push vectors data Push2 m a where Source # 2-dimensional push vector: a vector representation that supports nested write patterns (e.g. resulting from concatenation) and fusion of operations See the comments to Push regarding the semantics of push vectors with interleaved effects. Constructors  Push2 :: Data Length -> Data Length -> ((Data Index -> Data Index -> a -> m ()) -> m ()) -> Push2 m a Instances  (MonadComp m1, (~) (* -> *) m1 m2) => Manifestable2 m1 (Push2 m2 a) a Source # Methodsmanifest2 :: Arr a -> Push2 m2 a -> m1 (Manifest2 a) Source #manifestFresh2 :: Push2 m2 a -> m1 (Manifest2 a) Source #manifestStore2 :: Arr a -> Push2 m2 a -> m1 () Source # (~) (* -> *) m1 m2 => Pushy2 m1 (Push2 m2 a) a Source # MethodstoPush2 :: Push2 m2 a -> Push2 m1 a Source # Functor (Push2 m) Source # Methodsfmap :: (a -> b) -> Push2 m a -> Push2 m b #(<$) :: a -> Push2 m b -> Push2 m a # Finite (Push2 m a) Source # length gives number of rows Methodslength :: Push2 m a -> Data Length Source # (Syntax a, MarshalHaskell (Internal a), MarshalFeld a, (~) (* -> *) m Run) => MarshalFeld (Push2 m a) Source # Associated Typestype HaskellRep (Push2 m a) :: * Source # Methodsfwrite :: Handle -> Push2 m a -> Run () Source #fread :: Handle -> Run (Push2 m a) Source # Finite2 (Push2 m a) Source # Methodsextent2 :: Push2 m a -> (Data Length, Data Length) Source # ViewManifest2 (Push2 m a) a Source # MethodsviewManifest2 :: Push2 m a -> Maybe (Manifest2 a) Source # type HaskellRep (Push2 m a) Source # type HaskellRep (Push2 m a) = HaskellRep (Manifest2 a)

type DPush2 m a = Push2 m (Data a) Source #

Push2 vector specialized to Data elements

class Pushy2 m vec a | vec -> a where Source #

Vectors that can be converted to Push2

Minimal complete definition

toPush2

Methods

toPush2 :: vec -> Push2 m a Source #

Convert a vector to Push2

Instances

 MonadComp m => Pushy2 m (Pull2 a) a Source # MethodstoPush2 :: Pull2 a -> Push2 m a Source # MonadComp m => Pushy2 m (Pull a) a Source # MethodstoPush2 :: Pull a -> Push2 m a Source # (Syntax a, MonadComp m) => Pushy2 m (Manifest2 a) a Source # MethodstoPush2 :: Manifest2 a -> Push2 m a Source # (Syntax a, MonadComp m) => Pushy2 m (Manifest a) a Source # Convert to a Push2 with a single row MethodstoPush2 :: Manifest a -> Push2 m a Source # (~) (* -> *) m1 m2 => Pushy2 m1 (Push2 m2 a) a Source # MethodstoPush2 :: Push2 m2 a -> Push2 m1 a Source #

toPushM2 :: (Pushy2 m vec a, Monad m) => vec -> m (Push2 m a) Source #

A version of toPush2 that constrains the m argument of Push2 to that of the monad in which the result is returned. This can be a convenient way to avoid unresolved overloading.

Arguments

 :: Push2 m a Vector to dump -> (Data Index -> Data Index -> a -> m ()) Function that writes one element -> m ()

Dump the contents of a Push2 vector

## Operations

Arguments

 :: (Pushy m vec1 vec2, Pushy m vec2 a, MonadComp m) => Data Length Length of inner vectors -> vec1 -> Push2 m a

Turn a vector of rows into a 2-dimensional vector. All inner vectors are assumed to have the given length.

sequens2 :: (Pushy2 m vec (m a), Monad m) => vec -> Push2 m a Source #

Convert a 2-dimensional vector with effectful elements to Push2

WARNING: This function should be used with care, since is allows hiding effects inside a vector. These effects may be (seemingly) randomly interleaved with other effects when the vector is used.

The name sequens2 has to do with the similarity to the standard function sequence.

forwardPermute2 :: Pushy2 m vec a => (Data Length -> Data Length -> (Data Index, Data Index) -> (Data Index, Data Index)) -> vec -> Push2 m a Source #

Forward-permute a Push vector using an index mapping. The supplied mapping must be a bijection when restricted to the domain of the vector. This property is not checked, so use with care.

transposePush :: Pushy2 m vec a => vec -> Push2 m a Source #

# Writing to memory

class ViewManifest vec a | vec -> a where Source #

Methods

viewManifest :: vec -> Maybe (Manifest a) Source #

Try to cast a vector to Manifest directly

Instances

 ViewManifest (Pull a) a Source # MethodsviewManifest :: Pull a -> Maybe (Manifest a) Source # ViewManifest (Manifest a) a Source # Methods ViewManifest (Push m a) a Source # MethodsviewManifest :: Push m a -> Maybe (Manifest a) Source #

class ViewManifest vec a => Manifestable m vec a | vec -> a where Source #

Methods

manifest :: Syntax a => Arr a -> vec -> m (Manifest a) Source #

Write the contents of a vector to memory and get it back as a Manifest vector. The supplied array may or may not be used for storage.

manifest :: (Pushy m vec a, Finite vec, Syntax a, MonadComp m) => Arr a -> vec -> m (Manifest a) Source #

Write the contents of a vector to memory and get it back as a Manifest vector. The supplied array may or may not be used for storage.

manifestFresh :: Syntax a => vec -> m (Manifest a) Source #

A version of manifest that allocates a fresh array for the result

manifestFresh :: (Pushy m vec a, Syntax a, MonadComp m) => vec -> m (Manifest a) Source #

A version of manifest that allocates a fresh array for the result

manifestStore :: Syntax a => Arr a -> vec -> m () Source #

A version of manifest that only stores the vector to the given array (manifest is not guaranteed to use the array)

manifestStore :: (Pushy m vec a, Syntax a, MonadComp m) => Arr a -> vec -> m () Source #

A version of manifest that only stores the vector to the given array (manifest is not guaranteed to use the array)

Instances

 MonadComp m => Manifestable m (Pull a) a Source # Methodsmanifest :: Arr a -> Pull a -> m (Manifest a) Source #manifestFresh :: Pull a -> m (Manifest a) Source #manifestStore :: Arr a -> Pull a -> m () Source # MonadComp m => Manifestable m (Manifest a) a Source # manifest and manifestFresh are no-ops. manifestStore does a proper arrCopy. Methodsmanifest :: Arr a -> Manifest a -> m (Manifest a) Source #manifestFresh :: Manifest a -> m (Manifest a) Source #manifestStore :: Arr a -> Manifest a -> m () Source # (MonadComp m1, (~) (* -> *) m1 m2) => Manifestable m1 (Push m2 a) a Source # Methodsmanifest :: Arr a -> Push m2 a -> m1 (Manifest a) Source #manifestFresh :: Push m2 a -> m1 (Manifest a) Source #manifestStore :: Arr a -> Push m2 a -> m1 () Source #

class ViewManifest2 vec a | vec -> a where Source #

Methods

viewManifest2 :: vec -> Maybe (Manifest2 a) Source #

Try to cast a vector to Manifest2 directly

Instances

 ViewManifest2 (Pull2 a) a Source # Methods Source # Methods ViewManifest2 (Push2 m a) a Source # MethodsviewManifest2 :: Push2 m a -> Maybe (Manifest2 a) Source #

class ViewManifest2 vec a => Manifestable2 m vec a | vec -> a where Source #

Methods

manifest2 :: Syntax a => Arr a -> vec -> m (Manifest2 a) Source #

Write the contents of a vector to memory and get it back as a Manifest2 vector

manifest2 :: (Pushy2 m vec a, Syntax a, MonadComp m) => Arr a -> vec -> m (Manifest2 a) Source #

Write the contents of a vector to memory and get it back as a Manifest2 vector

manifestFresh2 :: Syntax a => vec -> m (Manifest2 a) Source #

A version of manifest2 that allocates a fresh array for the result

manifestFresh2 :: (Pushy2 m vec a, Syntax a, MonadComp m) => vec -> m (Manifest2 a) Source #

A version of manifest2 that allocates a fresh array for the result

manifestStore2 :: Syntax a => Arr a -> vec -> m () Source #

A version of manifest2 that only stores the vector to the given array (manifest2 is not guaranteed to use the array)

manifestStore2 :: (Pushy2 m vec a, Syntax a, MonadComp m) => Arr a -> vec -> m () Source #

A version of manifest2 that only stores the vector to the given array (manifest2 is not guaranteed to use the array)

Instances

 MonadComp m => Manifestable2 m (Pull2 a) a Source # Methodsmanifest2 :: Arr a -> Pull2 a -> m (Manifest2 a) Source #manifestFresh2 :: Pull2 a -> m (Manifest2 a) Source #manifestStore2 :: Arr a -> Pull2 a -> m () Source # MonadComp m => Manifestable2 m (Manifest2 a) a Source # manifest2 and manifestFresh2 are no-ops. manifestStore2 does a proper arrCopy. Methodsmanifest2 :: Arr a -> Manifest2 a -> m (Manifest2 a) Source #manifestFresh2 :: Manifest2 a -> m (Manifest2 a) Source #manifestStore2 :: Arr a -> Manifest2 a -> m () Source # (MonadComp m1, (~) (* -> *) m1 m2) => Manifestable2 m1 (Push2 m2 a) a Source # Methodsmanifest2 :: Arr a -> Push2 m2 a -> m1 (Manifest2 a) Source #manifestFresh2 :: Push2 m2 a -> m1 (Manifest2 a) Source #manifestStore2 :: Arr a -> Push2 m2 a -> m1 () Source #

# Orphan instances

 Source # Treated as a row vector Methods