# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>
# SPDX-FileContributor: 2003-24 Bradley M. Bell
# ----------------------------------------------------------------------------
{xrst_begin_parent var_binary_op dev}
{xrst_spell
   addpv
   addvv
   azmul
   delim
   divpv
   divvp
   divvv
   mulpv
   mulvv
   powpv
   powvp
   powvv
   subpv
   subvp
   subvv
   zmulpv
   zmulvp
   zmulvv
}

Binary Operators
################
All these operators have the same prototype and could be implemented as
virtual functions for a binary base case.
Compilers can not optimize across virtual function calls and testing indicates
that a virtual function implementation is significant slower.

User Syntax
***********
| *z* = *fun* ( *x* , *y* )
| *z* = *x* *Op* *y*

x
*
is a parameter or variable and is the first argument for this operator.

y
*
is a parameter or variable and is the second argument for this operator.

z
*
is the primary result for this operator which is also a variable.
The PowvpOp and PowvvOp operators has a two auxiliary results;
see :ref:`var_binary_op@n_res` below.

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

Fun
***

.. csv-table::
   :widths: auto
   :header-rows: 1
   :delim: ;

   op_code;      Fun;     fun; Op;         x;         y;  z
   AddpvOp;    addpv;        ; \+; parameter;  variable;  *x* + *y*
   AddvvOp;    addvv;        ; \+;  variable;  variable;  *x* + *y*
   DivpvOp;    divpv;        ; \/; parameter;  variable;  *x* / *y*
   DivvpOp;    divvp;        ; \/;  variable; parameter;  *x* / *y*
   DivvvOp;    divvv;        ; \/;  variable;  variable;  *x* / *y*
   MulpvOp;    mulpv;        ; \*; parameter;  variable;  *x* * *y*
   MulvvOp;    mulvv;        ; \*;  variable;  variable;  *x* * *y*
   SubpvOp;    subpv;        ; \-; parameter;  variable;  *x* - *y*
   SubvpOp;    subvp;        ; \-;  variable; parameter;  *x* - *y*
   SubvvOp;    subvv;        ; \-;  variable;  variable;  *x* - *y*
   PowpvOp;    zmulpv;    pow;   ; parameter;  variable;    pow( *x* , *y* )
   PowvpOp;    zmulvp;    pow;   ;  variable; parameter;    pow( *x* , *y* )
   PowvvOp;    zmulvv;    pow;   ;  variable;  variable;    pow( *x* , *y* )
   ZmulpvOp;   zmulpv;  azmul;   ; parameter;  variable;  azmul( *x* , *y* )
   ZmulvpOp;   zmulvp;  azmul;   ;  variable; parameter;  azmul( *x* , *y* )
   ZmulvvOp;   zmulvv;  azmul;   ;  variable;  variable;  azmul( *x* , *y* )

i_z
***
is the variable index corresponding to *z* .

n_res
*****
is the number of results that are variables.
This is 1 for all the binary operators except for PowpvOp and PowvvOp.
For the PowpvOp and PowvvOP operators, *n_res* is 3
and the variable indices of the auxiliary results are *i_z* - 1 and *i_z* - 2.

arg
***

arg[0]
======
If *x* is a variable (parameter)
*arg* [0] is the variable index (parameter index) corresponding to *x* .

arg[1]
======
If *y* is a variable (parameter)
*arg* [1] is the variable index (parameter index) corresponding to *y* .

parameter
*********
maps parameter indices to parameter values.

{xrst_end var_binary_op}
------------------------------------------------------------------------------
{xrst_begin var_binary_forward_0 dev}

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

x, y, z, n_res
**************
see
:ref:`var_binary_op@x` ,
:ref:`var_binary_op@y` ,
:ref:`var_binary_op@z` ,
:ref:`var_binary_op@n_res`

Prototype
*********
{xrst_code cpp}
template <class Base>
inline void Fun_forward_0(
   size_t        i_z         ,
   const addr_t* arg         ,
   const Base*   parameter   ,
   size_t        cap_order   ,
   Base*         taylor      )
{xrst_code}

Base, Fun, i_z, arg, parameter
******************************
see
:ref:`var_binary_op@Base` ,
:ref:`var_binary_op@Fun` ,
:ref:`var_binary_op@i_z` ,
:ref:`var_binary_op@arg` ,
:ref:`var_binary_op@parameter`

cap_order
*********
is the maximum number of orders that can fit in *taylor* .

taylor
******
The Taylor coefficient corresponding to variable *i* and order *k* is

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

Input
=====
The zero order Taylor coefficients
for variables with index *i* less than or equal *i_z* - *n_res* .

Output
======
The zero order Taylor coefficients for variables with index
*i_z* - *n_res* , .. , *i_z* .

{xrst_end var_binary_forward_0}
------------------------------------------------------------------------------
{xrst_begin var_binary_forward_any dev}

Any Order Forward Binary Variable Operators
###########################################

x, y, z, n_res
**************
see
:ref:`var_binary_op@x` ,
:ref:`var_binary_op@y` ,
:ref:`var_binary_op@z` ,
:ref:`var_binary_op@n_res`

Prototype
*********
{xrst_code cpp}
template <class Base>
inline void Fun_forward_any(
   size_t        order_low   ,
   size_t        order_up    ,
   size_t        i_z         ,
   const addr_t* arg         ,
   const Base*   parameter   ,
   size_t        cap_order   ,
   Base*         taylor      )
{xrst_code}

Base, Fun, i_z, arg, parameter
******************************
see
:ref:`var_binary_op@Base` ,
:ref:`var_binary_op@Fun` ,
:ref:`var_binary_op@i_z` ,
:ref:`var_binary_op@arg` ,
:ref:`var_binary_op@parameter`

{xrst_template ;
   include/cppad/local/var_op/template/forward_op.xrst
   headers: cap_order, order_low, order_up, taylor
}

{xrst_end var_binary_forward_any}
------------------------------------------------------------------------------
{xrst_begin var_binary_forward_dir dev}

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

x, y, z, n_res
**************
see
:ref:`var_binary_op@x` ,
:ref:`var_binary_op@y` ,
:ref:`var_binary_op@z` ,
:ref:`var_binary_op@n_res`

Prototype
*********
{xrst_code cpp}
template <class Base>
inline void Fun_forward_dir(
   size_t        order_up    ,
   size_t        n_dir       ,
   size_t        i_z         ,
   const addr_t* arg         ,
   const Base*   parameter   ,
   size_t        cap_order   ,
   Base*         taylor      )
{xrst_code}

Base, Fun, i_z, arg, parameter
******************************
see
:ref:`var_binary_op@Base` ,
:ref:`var_binary_op@Fun` ,
:ref:`var_binary_op@i_z` ,
:ref:`var_binary_op@arg` ,
:ref:`var_binary_op@parameter`

{xrst_template ;
   include/cppad/local/var_op/template/forward_dir.xrst
   headers: n_dir, cap_order, order_up, taylor
}

{xrst_end var_binary_forward_dir}
------------------------------------------------------------------------------
{xrst_begin var_binary_reverse dev}

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

x, y, z, n_res
**************
see
:ref:`var_binary_op@x` ,
:ref:`var_binary_op@y` ,
:ref:`var_binary_op@z` ,
:ref:`var_binary_op@n_res`

Prototype
*********
{xrst_code cpp}
template <class Base>
inline void Fun_reverse(
   size_t        i_z          ,
   const addr_t* arg          ,
   const Base*   parameter    ,
   size_t        cap_order    ,
   const Base*   taylor       ,
   size_t        n_order      ,
   Base*         partial      )
{xrst_code}

Base, Fun, i_z, arg, parameter
******************************
see
:ref:`var_binary_op@Base` ,
:ref:`var_binary_op@Fun` ,
:ref:`var_binary_op@i_z` ,
:ref:`var_binary_op@arg` ,
:ref:`var_binary_op@parameter`

cap_order
*********
is the maximum number of orders that can fit in *taylor* .

taylor
******
The Taylor coefficient corresponding to variable *i* and order *k* is

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

{xrst_template ;
   include/cppad/local/var_op/template/reverse_op.xrst
   headers: n_order, partial

   @x, y@ ; x
}

{xrst_end var_binary_reverse}
------------------------------------------------------------------------------
