| namespace Eigen { |
| |
| /** \page TopicEigenExpressionTemplates Expression templates in Eigen |
| |
| Arithmetic operators and most methods in %Eigen do not compute anything by themselves. Instead they |
| return a small \em expression \em object that merely describes the computation to be performed and |
| stores references to the operands. The actual computation happens later, typically when the whole |
| expression is assigned to a destination. This technique is known as <i>expression templates</i>, |
| and understanding its user-visible consequences helps to write both correct and fast %Eigen code. |
| |
| \eigenAutoToc |
| |
| \section TopicETHow How it works |
| |
| Consider: |
| \code |
| VectorXf a(50), b(50), c(50), d(50); |
| a = 3*b + 4*c + 5*d; |
| \endcode |
| |
| The right-hand side does not create any temporary vector. The subexpression \c 3*b is an object of |
| type <tt>CwiseBinaryOp<scalar_product_op, ..., ...></tt> that just stores the scalar and a reference |
| to \c b; the additions nest similar objects around it. The complete type of the right-hand side |
| encodes the whole expression tree at compile time. Only when this expression is assigned to \c a |
| does %Eigen generate a single evaluation loop, morally equivalent to: |
| \code |
| for (int i = 0; i < 50; ++i) |
| a[i] = 3*b[i] + 4*c[i] + 5*d[i]; |
| \endcode |
| |
| The benefits are that the arrays are traversed only once, no temporary objects are created, and the |
| single fused loop can be unrolled and vectorized (see \ref TopicVectorization). Consequently, you |
| should not be afraid of writing large expressions: doing so gives %Eigen more opportunities for |
| optimization. A step-by-step tour of the machinery behind this example is given in |
| \ref TopicInsideEigenExample, and the involved class hierarchy is described in |
| \ref TopicClassHierarchy. |
| |
| Not every subexpression is evaluated lazily: matrix products, for instance, are evaluated into |
| temporaries in most contexts, both for performance and for correctness in the face of aliasing. |
| The rules governing which subexpressions are evaluated where are documented in |
| \ref TopicLazyEvaluation. |
| |
| \section TopicETConsequences What it means in practice |
| |
| Because an "expression" is not a matrix, a few things deserve attention: |
| |
| - <b>Do not use \c auto to capture an expression</b> unless you know exactly what you are doing: |
| the deduced type is the expression type, not a plain matrix, so the computation re-runs every |
| time the variable is used, and the expression may hold dangling references to destroyed |
| temporaries. See \ref TopicPitfalls_auto_keyword. |
| - <b>Assignment evaluates coefficient-wise into the destination</b>, so if the destination also |
| appears on the right-hand side, coefficients may be read after they have been overwritten. This |
| is the aliasing problem, explained in \ref TopicAliasing. Use .eval(), an xxxInPlace() method, |
| or \link MatrixBase::noalias() noalias()\endlink as appropriate. |
| - <b>Functions should accept expressions, not just matrices.</b> Take parameters of type |
| <tt>const MatrixBase<Derived>&</tt> (or ArrayBase, DenseBase, EigenBase, or Ref) so that |
| arbitrary expressions can be passed without evaluating them into a temporary; see |
| \ref TopicFunctionTakingEigenTypes. |
| - <b>Materializing an expression</b> is done with \link DenseBase::eval() .eval()\endlink, which |
| returns a plain matrix or array (and is a no-op when the expression already is one), or by |
| assigning the expression to a plain object. |
| - <b>The two branches of the ternary operator <tt>?:</tt></b> must have a common type, which two |
| different expression types usually do not; use \c if/\c else or evaluate the branches. See |
| \ref TopicPitfalls_ternary_operator. |
| |
| \section TopicETExtending Extending the expression system |
| |
| Coefficient-wise custom operations rarely need a new expression type: a functor passed to |
| unaryExpr(), binaryExpr(), or NullaryExpr() is usually enough (see \ref TopicCustomizing_Functors |
| and \ref TopicCustomizing_NullaryExpr). When a genuinely new expression type is required, |
| \ref TopicNewExpressionType walks through a complete example. |
| |
| */ |
| |
| } |