\(\newcommand{\W}[1]{ \; #1 \; }\) \(\newcommand{\R}[1]{ {\rm #1} }\) \(\newcommand{\B}[1]{ {\bf #1} }\) \(\newcommand{\D}[2]{ \frac{\partial #1}{\partial #2} }\) \(\newcommand{\DD}[3]{ \frac{\partial^2 #1}{\partial #2 \partial #3} }\) \(\newcommand{\Dpow}[2]{ \frac{\partial^{#1}}{\partial {#2}^{#1}} }\) \(\newcommand{\dpow}[2]{ \frac{ {\rm d}^{#1}}{{\rm d}\, {#2}^{#1}} }\)
atomic_four_vector_reverse_op.hpp¶
View page sourceAtomic Vector Forward Mode: Example Implementation¶
Purpose¶
The reverse
routine overrides the virtual functions
used by the atomic_four base class for reverse mode calculations; see
reverse .
It determines which operator is specified for this call and transfers
the call to the operator’s implementation.
There are two versions of the reverse
routine, one for Base
and one for AD<Base>
.
Source¶
# include <cppad/example/atomic_four/vector/vector.hpp>
namespace CppAD { // BEGIN_CPPAD_NAMESPACE
//
// reverse override
// this routine used by ADFun<Base> objects
template <class Base>
bool atomic_vector<Base>::reverse(
size_t call_id,
const CppAD::vector<bool>& select_x,
size_t order_up,
const CppAD::vector<Base>& tx,
const CppAD::vector<Base>& ty,
CppAD::vector<Base>& px,
const CppAD::vector<Base>& py)
{
// q
size_t q = order_up + 1;
//
// op, n, m
op_enum_t op = op_enum_t( call_id );
size_t n = select_x.size();
size_t m = n / 2;
if( is_unary(op) )
m = n;
assert( tx.size() == q * n );
assert( ty.size() == q * m );
//
bool ok = false;
switch(op)
{
// addition
case add_enum:
reverse_add(m, q, tx, ty, px, py);
ok = true;
break;
// subtraction
case sub_enum:
reverse_sub(m, q, tx, ty, px, py);
ok = true;
break;
// multiplication
case mul_enum:
reverse_mul(m, q, tx, ty, px, py);
ok = true;
break;
// division
case div_enum:
reverse_div(m, q, tx, ty, px, py);
ok = true;
break;
// unary minus
case neg_enum:
reverse_neg(m, q, tx, ty, px, py);
ok = true;
break;
// error
case number_op_enum:
assert(false);
break;
}
return ok;
}
// reverse override
// this routine used by ADFun< CppAD::AD<Base> , Base> objects
template <class Base>
bool atomic_vector<Base>::reverse(
size_t call_id,
const CppAD::vector<bool>& select_x,
size_t order_up,
const CppAD::vector< CppAD::AD<Base> >& atx,
const CppAD::vector< CppAD::AD<Base> >& aty,
CppAD::vector< CppAD::AD<Base> >& apx,
const CppAD::vector< CppAD::AD<Base> >& apy)
{
// q
size_t q = order_up + 1;
//
// op, m
op_enum_t op = op_enum_t( call_id );
size_t n = select_x.size();
size_t m = n / 2;
if( is_unary(op) )
m = n;
assert( atx.size() == q * n );
assert( aty.size() == q * m );
bool ok = false;
switch(op)
{
// addition
case add_enum:
reverse_add(m, q, atx, aty, apx, apy);
ok = true;
break;
// subtraction
case sub_enum:
reverse_sub(m, q, atx, aty, apx, apy);
ok = true;
break;
// multiplication
case mul_enum:
reverse_mul(m, q, atx, aty, apx, apy);
ok = true;
break;
// division
case div_enum:
reverse_div(m, q, atx, aty, apx, apy);
ok = true;
break;
// unary minus
case neg_enum:
reverse_neg(m, q, atx, aty, apx, apy);
ok = true;
break;
// error
case number_op_enum:
assert(false);
break;
}
return ok;
}
} // END_CPPAD_NAMESPACE