---------------------------------------------------------------- lines 8-292 of file: include/cppad/core/atomic/three/forward.hpp ---------------------------------------------------------------- {xrst_begin atomic_three_forward} {xrst_spell aparameter ataylor } Atomic Function Forward Mode ############################ Base **** This syntax and prototype are used by :ref:`afun(ax, ay)` ; see :ref:`atomic_three_afun@Base` . They are also used by *f* . ``Forward`` and *f* . ``new_dynamic`` where *f* has prototype ``ADFun`` < *Base* > *f* and *afun* is used during the recording of *f* . Syntax ====== | *ok* = *afun* . ``forward`` ( | |tab| *parameter_x* , *type_x* , | |tab| *need_y* , *order_low* , *order_up* , *type_x* , *taylor_x* , *taylor_y* | ) Prototype ========= {xrst_literal // BEGIN_PROTOTYPE_BASE // END_PROTOTYPE_BASE } AD ******** This syntax and prototype are used by *af* . ``Forward`` and *af* . ``new_dynamic`` where *af* has prototype ``ADFun< AD<`` *Base* > , *Base* > *af* and *afun* is used in *af* (see :ref:`base2ad-name` ). Syntax ====== | *ok* = *afun* . ``forward`` ( | |tab| *parameter_x* , *type_x* , | |tab| *need_y* , *order_low* , *order_up* , *type_x* , *ataylor_x* , *ataylor_y* | ) Prototype ========= {xrst_literal // BEGIN_PROTOTYPE_AD_BASE // END_PROTOTYPE_AD_BASE } Implementation ************** The *taylor_x* , *taylor_y* version of this function must be defined by the :ref:`atomic_three_ctor@atomic_user` class. It can just return *ok* == ``false`` (and not compute anything) for values of *order_up* that are greater than those used by your :ref:`Forward-name` mode calculations (order zero must be implemented). parameter_x *********** See :ref:`atomic_three_define@parameter_x` . aparameter_x ************ The specifications for *aparameter_x* is the same as for :ref:`atomic_three_define@parameter_x` (only the type of *ataylor_x* is different). type_x ****** See :ref:`atomic_three_define@type_x` . need_y ****** One can ignore this argument and compute all the *taylor_y* Taylor coefficient. Often, this is not necessary and *need_y* is used to specify this. The value :ref:`atomic_three_for_type@type_y` is used to determine which coefficients are necessary as follows: Constant Parameters =================== If *need_y* == ``size_t`` ( ``constant_enum`` ) , then only the taylor coefficients for :math:`Y_i (t)` where *type_y* [ *i* ] == ``constant_enum`` are necessary. This is the case during a :ref:`from_json-name` operation. Dynamic Parameters ================== If *need_y* == ``size_t`` ( ``dynamic_enum`` ) , then only the taylor coefficients for :math:`Y_i (t)` where *type_y* [ *i* ] == ``dynamic_enum`` are necessary. This is the case during an :ref:`new_dynamic-name` operation. Variables ========= If *need_y* == ``size_t`` ( ``variable_enum`` ) , If ``ad_type_enum`` ( *need_y* ) == *variable_enum* , then only the taylor coefficients for :math:`Y_i (t)` where *type_y* [ *i* ] == ``variable_enum`` are necessary. This is the case during a :ref:`f.Forward` operation. T All === If *need_y > size_t* ( *variable_enum* ) , then the taylor coefficients for all :math:`Y_i (t)` are necessary. This is the case during an *afun* ( *ax* , *ay* ) operation. order_low ********* This argument specifies the lowest order Taylor coefficient that we are computing. p = We sometimes use the notation *p* = *order_low* below. order_up ******** This argument specifies the highest order Taylor coefficient that we are computing ( *order_low* <= *order_up* ). q = We sometimes use the notation *q* = *order_up* below. taylor_x ******** The size of *taylor_x* is ( *q* +1)* *n* . 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 & = & \R{taylor\_x} [ 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) parameters ========== If the *j*-th component of *x* corresponds to a parameter, *type_x* [ *j* ] < ``CppAD::variable_enum`` In this case, the *j*-th component of *parameter_x* is equal to :math:`x_j^0`; i.e., *parameter_x* [ *j* ] == *taylor_x* [ *j* * ( *q* + 1 ) + 0 ] Furthermore, for *k* > 0 , *taylor_x* [ *j* * ( *q* + 1 ) + *k* ] == 0 ataylor_x ********* The specifications for *ataylor_x* is the same as for *taylor_x* (only the type of *ataylor_x* is different). taylor_y ******** The size of *taylor_y* is ( *q* +1)* *m* . Upon return, For :math:`i = 0 , \ldots , m-1` and :math:`k = 0 , \ldots , q`, .. math:: :nowrap: \begin{eqnarray} Y_i (t) & = & g_i [ X(t) ] \\ Y_i (t) & = & y_i^0 + y_i^1 t^1 + \cdots + y_i^q t^q + o ( t^q ) \\ \R{taylor\_y} [ 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 *taylor_y* satisfies .. math:: \R{taylor\_y} [ i * ( q + 1 ) + k ] = y_i^k These values do not need to be recalculated and can be used during the computation of the higher order coefficients. ataylor_y ********* The specifications for *ataylor_y* is the same as for *taylor_y* (only the type of *ataylor_y* is different). ok ** If this calculation succeeded, *ok* is true. Otherwise, it is false. Discussion ********** For example, suppose that *order_up* == 2 , and you know how to compute the function :math:`g(x)`, its first derivative :math:`g^{(1)} (x)`, and it component wise Hessian :math:`g_i^{(2)} (x)`. Then you can compute *taylor_x* using the following formulas: .. math:: :nowrap: \begin{eqnarray} y_i^0 & = & Y(0) = g_i ( x^0 ) \\ y_i^1 & = & Y^{(1)} ( 0 ) = g_i^{(1)} ( x^0 ) X^{(1)} ( 0 ) = g_i^{(1)} ( x^0 ) x^1 \\ y_i^2 & = & \frac{1}{2 !} Y^{(2)} (0) \\ & = & \frac{1}{2} X^{(1)} (0)^\R{T} g_i^{(2)} ( x^0 ) X^{(1)} ( 0 ) + \frac{1}{2} g_i^{(1)} ( x^0 ) X^{(2)} ( 0 ) \\ & = & \frac{1}{2} (x^1)^\R{T} g_i^{(2)} ( x^0 ) x^1 + g_i^{(1)} ( x^0 ) x^2 \end{eqnarray} For :math:`i = 0 , \ldots , m-1`, and :math:`k = 0 , 1 , 2`, .. math:: \R{taylor\_y} [ i * (q + 1) + k ] = y_i^k {xrst_toc_hidden example/atomic_three/forward.cpp example/atomic_three/dynamic.cpp } Examples ******** The files :ref:`atomic_three_forward.cpp-name` and :ref:`atomic_three_dynamic.cpp-name` contain examples and tests that uses this routine. {xrst_end atomic_three_forward}