# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>
# SPDX-FileContributor: 2003-23 Bradley M. Bell
# ----------------------------------------------------------------------------
/*
{xrst_begin forward_binary_op dev}
{xrst_spell
   subvp
}

Variable Forward Binary Operators
#################################

Syntax
******

| ``forward_`` *name* _ ``op`` (
| |tab| *p* , *q* , *i_z* , *arg* , *parameter* *cap_order* , *taylor*
| )

Assumption
**********
The operator corresponding to *name* has
two arguments and one result.

Notation
********

name
****
The last two characters in the *name* for a binary operator are
``p`` (for parameter) or ``v`` (for variable).
For example the name ``subvp`` corresponding to subtraction
with a variable on the left (first) and a parameter on the right (second).

x
=
We use *x* to denote the first argument of this binary operation.
This argument is a variable or a parameter depending on the operator.

y
=
We use *y* to denote the second argument of this binary operation.
This argument is a variable or a parameter depending on the operator.

z
=
We use *z* to denote the result of this binary operation.
The result is always a variable.

Base
****
is the base type for the operator; i.e., this operation was recorded
using ``AD`` < *Base* > and computations by this routine are done using
type *Base* .

p
*
This argument has type ``size_t`` and
is lowest order of the Taylor coefficient that we are computing.

q
*
The argument *q >* = *p* has type ``size_t`` and
is highest order of the Taylor coefficient that we are computing.

i_z
***
This argument has type ``size_t`` and
is the variable index corresponding to the result for this operation;
i.e. the row index in *taylor* corresponding to *z* .

arg
***
This argument has type ``const addr_t*`` .

i_x
===
We use *i_x* = *arg* [0] for the
index corresponding to the first operand for this operator.
If *x* is a parameter,
*parameter* [ *i_x* ] is the corresponding value.
If *x* is a variable,
*i_x* is the row index in *taylor* corresponding to ``x`` .

i_y
===
We use *i_y* = *arg* [0] for the
index corresponding to the first operand for this operator.
If *y* is a parameter,
*parameter* [ *i_y* ] is the corresponding value.
If *y* is a variable,
*i_y* is the row index in *taylor* corresponding to ``y`` .

parameter
*********
This argument has type ``const`` *Base* *
and maps parameter indices to parameter values.

cap_order
*********
This argument has type ``size_t`` and
is the maximum number of orders that will fit in *taylor* .

taylor
******
This argument has type *Base* * .
The Taylor coefficient corresponding to
variable *i* and order *k* is

   *taylor* [ *i* * *cap_order* + *k*  ]

.

Input
=====

#. If *x* is a variable,
   the Taylor coefficients for variable *i_x* up to order *q* .
#. If *y* is a variable,
   the Taylor coefficients for variable *i_y* up to order *q* .
#. The Taylor coefficients for variable *i_z* up to order *p* ``-1`` .

Output
======
The Taylor coefficients for variable *i_z* up to order *q* .

{xrst_end forward_binary_op}
------------------------------------------------------------------------------
{xrst_begin forward_binary_op_dir dev}
{xrst_spell
   tpv
}

Multiple Direction Forward Binary Operators
###########################################

Syntax
******

| ``forward_`` *name* _ ``op`` (
| |tab| *q* , *r* , *i_z* , *arg* , *parameter* , *cap_order* , *taylor*
| )

Assumption
**********
The operator corresponding to *name* has
two arguments and one result.

Notation
********

x
=
We use *x* to denote the first argument of this binary operation.
This argument is a variable or a parameter depending on the operator.

y
=
We use *y* to denote the second argument of this binary operation.
This argument is a variable or a parameter depending on the operator.

z
=
We use *z* to denote the result of this binary operation.
The result is always a variable.

Base
****
is the base type for the operator; i.e., this operation was recorded
using ``AD`` < *Base* > and computations by this routine are done using
type *Base* .

q
*
This argument has type ``size_t`` and
is the order of the Taylor coefficients that we are computing.
Furthermore *q*  > 0 and *q* < *cap_order* .

r
*
This argument has type ``size_t`` and
is number of directions for Taylor coefficients that we are computing.

i_z
***
This argument has type ``size_t`` and
is the variable index corresponding to the result for this operation;
i.e. the row index in *taylor* corresponding to *z* .

arg
***
This argument has type ``const addr_t`` * *arg* .

i_x
===
We use *i_x* = *arg* [0] for the
index corresponding to the first operand for this operator.
If *x* is a parameter,
*parameter* [ *i_x* ] is the corresponding value.
If *x* is a variable,
*i_x* is the row index in *taylor* corresponding to ``x`` .

i_y
===
We use *i_y* = *arg* [0] for the
index corresponding to the first operand for this operator.
If *y* is a parameter,
*parameter* [ *i_y* ] is the corresponding value.
If *y* is a variable,
*i_y* is the row index in *taylor* corresponding to ``y`` .

parameter
*********
This argument has type ``const`` *Base* *
and maps parameter indices to parameter values.

cap_order
*********
This argument has type ``size_t`` and
is the maximum number of orders that will fit in *taylor* .
The zero order Taylor coefficient for a variable
is the same for all directions.  We use the notation

   *tpv* = ( *cap_order* ``- 1`` ) * ``r`` + 1

which is the number of Taylor coefficients per variable.

taylor
******
This argument has type *Base* * .
The zero order Taylor coefficient for variable *i* is

   *taylor* [ *i* * *tpv*  + 0 ]

.
For *k > 0* ,
and *ell* = 0 , .. , *r-1* ,
The Taylor coefficient for variable *i* ,
order *k* , and direction *ell* is

   *taylor* [ *i* * *tpv* + ( *k* ``- 1`` ) * *r* + *ell*  + 1 ]

.

Input
*****

#. If *x* is a variable,
   the Taylor coefficients for variable *i_x* up to order *q*
   and all *r* directions.
#. If *y* is a variable,
   the Taylor coefficients for variable *i_x* up to order *q*
   and all *r* directions.
#. The Taylor coefficients for variable *i_z* up to order *q-1*
   and all *r* directions.

Output
******
The Taylor coefficients for variable *i_z* up to order *q*
and all *r* directions.

{xrst_end forward_binary_op_dir}
-------------------------------------------------------------------------------
/*
{xrst_begin forward_binary_op_0 dev}

Zero Order Forward Binary Operators
###################################

Syntax
******

| ``forward_`` *name* _ ``op_0`` (
| |tab| *i_z* , *arg* , *parameter* , *cap_order* , *taylor*
| )

Assumption
**********
The operator corresponding to *name* has
two arguments and one result.

Notation
********

x
=
We use *x* to denote the first argument of this binary operation.
This argument is a variable or a parameter depending on the operator.

y
=
We use *y* to denote the second argument of this binary operation.
This argument is a variable or a parameter depending on the operator.

z
=
We use *z* to denote the result of this binary operation.
The result is always a variable.

Base
****
is the base type for the operator; i.e., this operation was recorded
using ``AD`` < *Base* > and computations by this routine are done using
type *Base* .

i_z
***
This argument has type ``size_t`` and
is the variable index corresponding to the result for this operation;
i.e. the row index in *taylor* corresponding to *z* .

arg
***
This argument has type ``const addr_t*`` .

i_x
===
We use *i_x* = *arg* [0] for the
index corresponding to the first operand for this operator.
If *x* is a parameter,
*parameter* [ *i_x* ] is the corresponding value.
If *x* is a variable,
*i_x* is the row index in *taylor* corresponding to ``x`` .

i_y
===
We use *i_y* = *arg* [0] for the
index corresponding to the first operand for this operator.
If *y* is a parameter,
*parameter* [ *i_y* ] is the corresponding value.
If *y* is a variable,
*i_y* is the row index in *taylor* corresponding to ``y`` .

parameter
*********
This argument has type ``const`` *Base* *
and maps parameter indices to parameter values.

cap_order
*********
This argument has type ``size_t`` and
is the maximum number of orders that will fit in *taylor* .

taylor
******
This argument has type *Base* * .
The Taylor coefficient corresponding to
variable *i* and order *k* is

   *taylor* [ *i* * *cap_order* + *k*  ]

.

Input
=====
If *x* is a variable,
the zero order Taylor coefficients for variable *i_x* .
If *y* is a variable,
the zero order Taylor coefficients for variable *i_y* .

Output
======
The zero order Taylor coefficients for variable *i_z* .

{xrst_end forward_binary_op_0}
------------------------------------------------------------------------------
/*
{xrst_begin reverse_binary_op dev}

Reverse Binary Operators
########################

Syntax
******

| ``reverse_`` *name* _ ``op`` (
| *d* , *i_z* , *arg* , *parameter* , *cap_order* , *taylor* , *nc_partial* , *partial*
| )

Assumption
**********
The operator corresponding to *name* has one argument and one result.

Notation
********

x
=
We use *x* to denote the first argument of this binary operation.
This argument is a variable or a parameter depending on the operator.

y
=
We use *y* to denote the second argument of this binary operation.
This argument is a variable or a parameter depending on the operator.

z
=
We use *z* to denote the result of this binary operation.
The result is always a variable.

G
=
We use :math:`G(z, y, x, w, \ldots )` to denote a scalar valued function
of the variables up to variable index *i_z* .

H
=
We use :math:`H(y, x, w, \ldots )` to denote the scalar valued function
of the variables up to variable index *i_z* ``-1`` defined by

.. math::

   H(y, x, w, \ldots ) = G [ z(x, y), y, x, w, \ldots ) ]

Base
****
is the base type for the operator; i.e., this operation was recorded
using ``AD`` < *Base* > and computations by this routine are done using
type *Base* .

d
*
This argument has type ``size_t`` and
is this highest order Taylor coefficient that we are computing
partial derivatives with respect to.
Furthermore *d* < *cap_order* and *d* < *nc_partial* .

i_z
***
This argument has type ``size_t`` and
is the variable index corresponding to the result for this operation;
i.e. the row index in *taylor* corresponding to *z* .

arg
***
This argument has type ``const addr_t*`` .

i_x
===
We use *i_x* = *arg* [0] for the
index corresponding to the first operand for this operator.
If *x* is a parameter,
*parameter* [ *i_x* ] is the corresponding value.
If *x* is a variable,
*i_x* is the row index in *taylor* corresponding to ``x`` .

i_y
===
We use *i_y* = *arg* [0] for the
index corresponding to the first operand for this operator.
If *y* is a parameter,
*parameter* [ *i_y* ] is the corresponding value.
If *y* is a variable,
*i_y* is the row index in *taylor* corresponding to ``y`` .

parameter
*********
This argument has type ``const`` *Base* *
and maps parameter indices to parameter values.

cap_order
*********
This argument has type ``size_t`` and
is the maximum number of orders that will fit in *taylor* .

taylor
******
This argument has type ``const`` *Base* * .
The Taylor coefficient corresponding to
variable *i* and order *k* is

   *taylor* [ *i* * *cap_order* + *k*  ]

.

nc_partial
**********
This argument has type ``size_t`` and
is the number of columns in the partial array.

partial
*******
This argument has type *Base* * .
The partial derivative w.r.t. variable *i* and
Taylor coefficient of order *k* is

   *partial* [ *i* * *nc_partial* + ``k`` ]

for *k* = 0 , ..., *d* .

Input
=====
For variable *i* = 0 ,..., *i_z* ,
*partial* contains the
partial derivatives of :math:`G(z, y, x, w, \ldots)`.

Output
======
The array *partial* contains the
partial derivatives of :math:`H(x, w, \ldots)`.
The partial derivative for variable *i_z* is unspecified.

{xrst_end reverse_binary_op}
------------------------------------------------------------------------------
