lines 8-249 of file: include/cppad/core/atomic/two/forward.hpp {xrst_begin atomic_two_forward app} {xrst_spell atx aty superscripts tx vx } Atomic Forward Mode ################### Syntax ****** Base ==== *ok* = *afun* . ``forward`` ( *p* , *q* , *vx* , *vy* , *tx* , *ty* ) This syntax is used by *f* . ``Forward`` where *f* has prototype ``ADFun`` < *Base* > *f* and *afun* is used in *f* . AD ======== *ok* = *afun* . ``forward`` ( *p* , *q* , *vx* , *vy* , *atx* , *aty* ) This syntax is used by *af* . ``Forward`` where *af* has prototype ``ADFun< AD<`` *Base* > , *Base* > *af* and *afun* is used in *af* (see :ref:`base2ad-name` ). Purpose ******* This virtual function is used by :ref:`atomic_two_afun-name` to evaluate function values. It is also used buy :ref:`f.Forward` (and *af* . ``Forward`` ) to compute function vales and derivatives. Implementation ************** This virtual function must be defined by the :ref:`atomic_two_ctor@atomic_user` class. It can just return *ok* == ``false`` (and not compute anything) for values of *q* > 0 that are greater than those used by your :ref:`Forward-name` mode calculations. p * The argument *p* has prototype ``size_t`` *p* It specifies the lowest order Taylor coefficient that we are evaluating. During calls to :ref:`atomic_two_afun-name` , *p* == 0 . q * The argument *q* has prototype ``size_t`` *q* It specifies the highest order Taylor coefficient that we are evaluating. During calls to :ref:`atomic_two_afun-name` , *q* == 0 . vx ** The ``forward`` argument *vx* has prototype ``const CppAD::vector&`` *vx* The case *vx* . ``size`` () > 0 only occurs while evaluating a call to :ref:`atomic_two_afun-name` . In this case, *p* == *q* == 0 , *vx* . ``size`` () == *n* , and for :math:`j = 0 , \ldots , n-1`, *vx* [ *j* ] is true if and only if *ax* [ *j* ] is a :ref:`glossary@Variable` or :ref:`dynamic parameter` in the corresponding call to *afun* ( *ax* , *ay* ) If *vx* . ``size`` () == 0 , then *vy* . ``size`` () == 0 and neither of these vectors should be used. vy ** The ``forward`` argument *vy* has prototype ``CppAD::vector&`` *vy* If *vy* . ``size`` () == 0 , it should not be used. Otherwise, *q* == 0 and *vy* . ``size`` () == *m* . The input values of the elements of *vy* are not specified (must not matter). Upon return, for :math:`j = 0 , \ldots , m-1`, *vy* [ *i* ] is true if and only if *ay* [ *i* ] is a variable or dynamic parameter (CppAD uses *vy* to reduce the necessary computations). tx ** The argument *tx* has prototype ``const CppAD::vector<`` *Base* >& *tx* and *tx* . ``size`` () == ( *q* +1)* *n* . It is used by *f* . ``Forward`` where *f* has type ``ADFun`` < *Base* > *f* and *afun* is used in *f* . For :math:`j = 0 , \ldots , n-1` and :math:`k = 0 , \ldots , q`, we use the Taylor coefficient notation .. math:: :nowrap: \begin{eqnarray} x_j^k & = & tx [ j * ( q + 1 ) + k ] \\ X_j (t) & = & x_j^0 + x_j^1 t^1 + \cdots + x_j^q t^q \end{eqnarray} Note that superscripts represent an index for :math:`x_j^k` and an exponent for :math:`t^k`. Also note that the Taylor coefficients for :math:`X(t)` correspond to the derivatives of :math:`X(t)` at :math:`t = 0` in the following way: .. math:: x_j^k = \frac{1}{ k ! } X_j^{(k)} (0) atx *** The argument *atx* has prototype ``const CppAD::vector< AD<`` *Base* > >& *atx* Otherwise, *atx* specifications are the same as for *tx* . ty ** The argument *ty* has prototype ``CppAD::vector<`` *Base* >& *ty* and *tx* . ``size`` () == ( *q* +1)* *m* . It is set by *f* . ``Forward`` where *f* has type ``ADFun`` < *Base* > *f* and *afun* is used in *f* . Upon return, For :math:`i = 0 , \ldots , m-1` and :math:`k = 0 , \ldots , q`, .. math:: :nowrap: \begin{eqnarray} Y_i (t) & = & f_i [ X(t) ] \\ Y_i (t) & = & y_i^0 + y_i^1 t^1 + \cdots + y_i^q t^q + o ( t^q ) \\ ty [ i * ( q + 1 ) + k ] & = & y_i^k \end{eqnarray} where :math:`o( t^q ) / t^q \rightarrow 0` as :math:`t \rightarrow 0`. Note that superscripts represent an index for :math:`y_j^k` and an exponent for :math:`t^k`. Also note that the Taylor coefficients for :math:`Y(t)` correspond to the derivatives of :math:`Y(t)` at :math:`t = 0` in the following way: .. math:: y_j^k = \frac{1}{ k ! } Y_j^{(k)} (0) If :math:`p > 0`, for :math:`i = 0 , \ldots , m-1` and :math:`k = 0 , \ldots , p-1`, the input of *ty* satisfies .. math:: ty [ i * ( q + 1 ) + k ] = y_i^k and hence the corresponding elements need not be recalculated. aty *** The argument *aty* has prototype ``const CppAD::vector< AD<`` *Base* > >& *aty* Otherwise, *aty* specifications are the same as for *ty* . ok ** If the required results are calculated, *ok* should be true. Otherwise, it should be false. Discussion ********** For example, suppose that *q* == 2 , and you know how to compute the function :math:`f(x)`, its first derivative :math:`f^{(1)} (x)`, and it component wise Hessian :math:`f_i^{(2)} (x)`. Then you can compute *ty* using the following formulas: .. math:: :nowrap: \begin{eqnarray} y_i^0 & = & Y(0) = f_i ( x^0 ) \\ y_i^1 & = & Y^{(1)} ( 0 ) = f_i^{(1)} ( x^0 ) X^{(1)} ( 0 ) = f_i^{(1)} ( x^0 ) x^1 \\ y_i^2 & = & \frac{1}{2 !} Y^{(2)} (0) \\ & = & \frac{1}{2} X^{(1)} (0)^\R{T} f_i^{(2)} ( x^0 ) X^{(1)} ( 0 ) + \frac{1}{2} f_i^{(1)} ( x^0 ) X^{(2)} ( 0 ) \\ & = & \frac{1}{2} (x^1)^\R{T} f_i^{(2)} ( x^0 ) x^1 + f_i^{(1)} ( x^0 ) x^2 \end{eqnarray} For :math:`i = 0 , \ldots , m-1`, and :math:`k = 0 , 1 , 2`, .. math:: ty [ i * (q + 1) + k ] = y_i^k {xrst_end atomic_two_forward}