Difference between revisions of "Working notes - Expression evaluator"

From Eigen
Jump to: navigation, search
(start an evaluator working page)
 
Line 1: Line 1:
 
[[Category:Developer]]
 
[[Category:Developer]]
  
= Goals
+
= Goals =
 
The goal here is to refactor our expression template mechanism such that the construction of the expression tree and its evaluation is 100% decoupled. Basically, at construction time, we should only assemble stupid *Expression* objects that only brings the proper API. Then, at evaluation time, via partial specialization, we would recursively create *Evaluator* objects reflecting how the considered sub expressions can and have to be evaluated. In between we could then implement *TreeOptimizer* objects that would reorganize and optimize the expression tree through partial specialization.
 
The goal here is to refactor our expression template mechanism such that the construction of the expression tree and its evaluation is 100% decoupled. Basically, at construction time, we should only assemble stupid *Expression* objects that only brings the proper API. Then, at evaluation time, via partial specialization, we would recursively create *Evaluator* objects reflecting how the considered sub expressions can and have to be evaluated. In between we could then implement *TreeOptimizer* objects that would reorganize and optimize the expression tree through partial specialization.
  
= Expression
+
= Expression =
  
= Evaluator
+
An expression as to be as simple as possible. Here is a list of elements to take into account for the new design:
  
= TreeOptimizer
+
=== One unique expression class for one high level semantic  ===
 +
For instance, this means that the expression type of the linear product of two abstract expressions A and B will always be Product<A,B>.
 +
 
 +
=== Bring the correct API ===
 +
In practice this means that the expression as to know about both its StorageKind (Dense, Sparse, Band, etc.) and XprKind (Matrix versus Array) such that it can inherit from the right base class (MatrixBase, ArrayBase, SparseMatrixBase, etc.). This is already achieved via a per expression intermediate FooImpl class, e.g.:
 +
 
 +
  Transpose<Xpr> <- TransposeImpl<Transpose<Xpr>,Xpr::StorageKind>
 +
  TransposeImpl<TransposeXpr,Dense> <- dense_xpr_base<Transpose<TransposeXpr> >::type
 +
  TransposeImpl<TransposeXpr,Sparse> <- SparseMatrixBase<TransposeXpr>
 +
 
 +
After this evaluator refactoring, these FooImpl classes should not bring any implementation details anymore, and so they could be renamed, and maybe even factorized into a unique dispatcher helper class. Note that the way we select whether the expression itself is, e.g., Sparse or Dense, it still specific to the expression semantic and is not always trivial (e.g., for binary operations), nevertheless, it still seems cleaner and simpler to me to decouple this bit of logic from the dispatcher mechanism such that later one can be implemented once for all per storage/xpr kinds.
 +
 
 +
 
 +
 
 +
 
 +
= Evaluator =
 +
 
 +
= TreeOptimizer =

Revision as of 06:59, 20 March 2011


Goals

The goal here is to refactor our expression template mechanism such that the construction of the expression tree and its evaluation is 100% decoupled. Basically, at construction time, we should only assemble stupid *Expression* objects that only brings the proper API. Then, at evaluation time, via partial specialization, we would recursively create *Evaluator* objects reflecting how the considered sub expressions can and have to be evaluated. In between we could then implement *TreeOptimizer* objects that would reorganize and optimize the expression tree through partial specialization.

Expression

An expression as to be as simple as possible. Here is a list of elements to take into account for the new design:

One unique expression class for one high level semantic

For instance, this means that the expression type of the linear product of two abstract expressions A and B will always be Product<A,B>.

Bring the correct API

In practice this means that the expression as to know about both its StorageKind (Dense, Sparse, Band, etc.) and XprKind (Matrix versus Array) such that it can inherit from the right base class (MatrixBase, ArrayBase, SparseMatrixBase, etc.). This is already achieved via a per expression intermediate FooImpl class, e.g.:

  Transpose<Xpr> <- TransposeImpl<Transpose<Xpr>,Xpr::StorageKind>
  TransposeImpl<TransposeXpr,Dense> <- dense_xpr_base<Transpose<TransposeXpr> >::type
  TransposeImpl<TransposeXpr,Sparse> <- SparseMatrixBase<TransposeXpr>

After this evaluator refactoring, these FooImpl classes should not bring any implementation details anymore, and so they could be renamed, and maybe even factorized into a unique dispatcher helper class. Note that the way we select whether the expression itself is, e.g., Sparse or Dense, it still specific to the expression semantic and is not always trivial (e.g., for binary operations), nevertheless, it still seems cleaner and simpler to me to decouple this bit of logic from the dispatcher mechanism such that later one can be implemented once for all per storage/xpr kinds.



Evaluator

TreeOptimizer