MArray Expression Template Internals
[The Class MArray]

Classes

Defines

Functions


Detailed Description

This documentation explains the internal expression template mechanism. It should not be necessary to understand all this to use the LTL.

The anatomy of expression templates:

Expressions like the right-hand side of

     A = A + B*C;
(with A, B, and C being of type ltl::MArray<float,1>) are represented by nested templated data types that capture the parse tree of the expression.

In this example, the expression A + B*C is represented by the type (simplified for readability)

     ltl::ExprBinopNode<ltl::MArrayIterConst<float, 1>,
                        ltl::ExprNode<ltl::ExprBinopNode<ltl::MArrayIterConst<float, 1>,
                                                         ltl::MArrayIterConst<float, 1>,
                                                         ltl::__ltl_TMul<float, float>,
                                                         1>,
                                      1>,
                        ltl::__ltl_TAdd<float, float>,
                        1>
In real code, we'd want all possible parse tree nodes to be of one single type so that any expression argument can be caught by a single templated type. Therefore, each of the parse tree nodes is wrapped in a template class ExprNode<>, which forwards all calls to the parse tree node it wraps.

The class ExprNode<> defines an iterator-like interface that all parse tree nodes (and ultimately the iterators that parse tree nodes hold) implement. This way, a whole expression, and every sub-expression presents an iterator interface to the outside world.

For this to function we define

Ultimately, the expression is evaluated by
    template<typename E>
    ltl::MArray<float,1>::operator=( ExprNode<E,1> ).
which uses the iterator-like interface of the expression to loop over each element of the underlying (multidimensional) array structure.

Define Documentation

#define BINOP_AA ( operator,
op   ) 

Define the global binary functions/operators for ltl::MArray expressions, version for 2 MArray operands, overloaded versions below.

Each binary function/operator takes MArrays, expressions, or literals as arguments and returns a parse tree node for the operation it represents:

    ExprNode <ExprBinopNode <A, B, Operation, NDim> > function( A& RHS, B& LHS )
where LHS and RHS are of type ltl::MArray, ltl::ExprNode, or scalar literals.

There are 8 combination of argument types for binary ops, namely:

array op array,
expr op array,
array op expr,
expr op expr,

array op literal,
expr op literal,
literal op array, and
literal op expr.

An overloaded template function/operator is generated by these macros for each of these cases.

#define BINOP_EA ( operator,
op   ) 

Expression MArray.

#define BINOP_AE ( operator,
op   ) 

MArray - Expression.

#define BINOP_EE ( operator,
op   ) 

Expression - Expression.

#define BINOP_AL ( operator,
op,
lit_type   ) 

MArray - Literal.

#define BINOP_EL ( operator,
op,
lit_type   ) 

Expression - Literal.

#define BINOP_LA ( operator,
op,
lit_type   ) 

Literal - MArray.

#define BINOP_LE ( operator,
op,
lit_type   ) 

Literal - Expression.

#define UNOP_A ( operator,
op   ) 

Define the global unary operators, overloaded versions for marray operand.

Each binary function/operator takes MArrays, expressions, or literals as arguments and returns a parse tree node for the operation it represents:

    ExprNode <ExprUnopNode <A, Operation, NDim> > function( A& operand )
where operand is of type ltl::MArray, ltl::ExprNode.

There are 2 combination of argument types for unary operations, namely:

op array, and
op expr.

An overloaded template function/operator is generated by these macros for each of these cases.

#define UNOP_E ( operator,
op   ) 

Define the global unary operators, overloaded versions for marray operand.

Overloaded version for expression operands.

#define DECLARE_BINOP ( operation,
opname   ) 

Make a binary (built-in) operator available to expression templates.

This macro declares all necessary overloaded operators to build the parse tree for a given binary operator operation. The return type is the standard C type-promoted result of the operation on built in scalar types.

It is assumed that the name of the applicative template for the same operator is called ltl::__ltl_opname and that this template is defined elsewhere (misc/applicopsh for built-in operators).

#define DECLARE_BINOP_RET ( operation,
ret_type,
opname   ) 

Make a binary (built-in) operator available to expression templates.

This macro declares all necessary overloaded operators to build the parse tree for a given binary operator operation. The return type may be different than the operand type, e.g. as necessary for bool-valued operators.

It is assumed that the name of the applicative template for the same operator is called ltl::__ltl_opname and that this template is defined elsewhere (misc/applicopsh for built-in operators).

#define DECLARE_UNOP ( operation,
opname   ) 

Make a unary (built-in) operator available to expression templates.

This macro declares all necessary overloaded operators to build the parse tree for a given unary operator operation. The return type is the standard C type-promoted result of the operation on built in scalar types.

It is assumed that the name of the applicative template for the same operator is called ltl::__ltl_opname and that this template is defined elsewhere (misc/applicopsh for built-in operators).

#define DECLARE_BINARY_FUNC_ ( function,
ret_type   ) 

Make any binary function available to expression templates.

This macro declares all necessary overloaded operators to build the parse tree for a given binary function function. The return type may be different than the operand type.

It is assumed that the name of the applicative template for the same function is called ltl::__ltl_function and that this template is defined elsewhere. (misc/applicopsh for standard functions).

The function itself has to be implemented with the signature

    template <typename T>
    ret_type function( const T& a, const T& b );

#define DECLARE_UNARY_FUNC_ ( function,
ret_type   ) 

Make any unary function available to expression templates.

This macro declares all necessary overloaded operators to build the parse tree for a given unary function function. The return type may be different than the operand type.

It is assumed that the name of the applicative template for the same function is called ltl::__ltl_function and that this template is defined elsewhere (misc/applicopsh for standard functions).

The function itself has to be implemented with the signature

    template <typename T>
    ret_type function( const T& a );

#define DECLARE_BINARY_FUNC ( function,
ret_type   ) 

Value:

MAKE_BINAP_FUNC( __ltl_##function, ret_type, function );      \
DECLARE_BINARY_FUNC_(function, ret_type)
Make any user-defined binary function available to expression templates.

This macro declares all necessary overloaded operators to build the parse tree for a given binary function function. The return type may be different than the operand type.

This macro also declares and defines the applicative templates for this function. It is the only macro that needs to be called by users to make user-defined functions available to expression templates.

Assume you have a function like this:

    template <typename T>
    ret_type function( const T& a, const T& b );
Then using
    DECLARE_BINARY_FUNC(function, ret_type);
This function will be usable in expression templates.

#define DECLARE_UNARY_FUNC ( function,
ret_type   ) 

Value:

MAKE_UNAP_FUNC( __ltl_##function, ret_type, function );       \
DECLARE_UNARY_FUNC_(function, ret_type)
Make any user-defined unary function available to expression templates.

This macro declares all necessary overloaded operators to build the parse tree for a given unary function function. The return type may be different than the operand type.

This macro also declares and defines the applicative templates for this function. It is the only macro that needs to be called by users to make user-defined functions available to expression templates.

Assume you have a function like this:

    template <typename T>
    ret_type function( const T& a );
Then using
    DECLARE_BINARY_FUNC(function, ret_type);
This function will be usable in expression templates.


Function Documentation

template<class A, class B>
const Shape<A::dims>* ltl::_expr_getshape ( const A &  a,
const B &  b 
) [inline]

Determine the shape of an expression by returning the ltl::Shape objects on one of the ltl::MArray operatnds.

Determine the shape of an expression

When determining the shape of an expression it is sufficient to return any one shape object from any one of the MArrays in the expression since we know they will all be the conformable. However, we must make sure that we do not ask e.g. a literal constant for a shape ...

In the general case, just use the LHS Shape ... We will provide partial specializations for the cases where one of the operands does not have a shape and return the other instead.

template<class A, class B>
int ltl::_expr_getalign ( const A &  a,
const B &  b 
) [inline]

Determine the alignment (w.r.t. natural vector boundaries) of the operands in an expression.

When determining the alignment of an expression it is sufficient to return any one of the alignments from any one of the MArrays in the expression since we only vectorize if we know the alignments are the same. However, we must make sure that we do not ask e.g. a literal constant for a it's alignment ...

In the general case, just use the LHS's alignment ... We will provide partial specializations for the cases where one of the operands does not have an alignment and return the other's instead.


Generated on Wed Mar 11 17:44:35 2009 for LTL by  doxygen 1.5.3