mirror of
https://github.com/sunnypilot/sunnypilot.git
synced 2026-09-19 16:43:42 +08:00
external folder
This commit is contained in:
+160
@@ -0,0 +1,160 @@
|
||||
# ifndef CPPAD_LOCAL_ABS_OP_HPP
|
||||
# define CPPAD_LOCAL_ABS_OP_HPP
|
||||
|
||||
/* --------------------------------------------------------------------------
|
||||
CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-17 Bradley M. Bell
|
||||
|
||||
CppAD is distributed under multiple licenses. This distribution is under
|
||||
the terms of the
|
||||
Eclipse Public License Version 1.0.
|
||||
|
||||
A copy of this license is included in the COPYING file of this distribution.
|
||||
Please visit http://www.coin-or.org/CppAD/ for information on other licenses.
|
||||
-------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
namespace CppAD { namespace local { // BEGIN_CPPAD_LOCAL_NAMESPACE
|
||||
/*!
|
||||
\file abs_op.hpp
|
||||
Forward and reverse mode calculations for z = fabs(x).
|
||||
*/
|
||||
|
||||
/*!
|
||||
Compute forward mode Taylor coefficient for result of op = AbsOp.
|
||||
|
||||
The C++ source code corresponding to this operation is
|
||||
\verbatim
|
||||
z = fabs(x)
|
||||
\endverbatim
|
||||
|
||||
\copydetails CppAD::local::forward_unary1_op
|
||||
*/
|
||||
template <class Base>
|
||||
inline void forward_abs_op(
|
||||
size_t p ,
|
||||
size_t q ,
|
||||
size_t i_z ,
|
||||
size_t i_x ,
|
||||
size_t cap_order ,
|
||||
Base* taylor )
|
||||
{
|
||||
// check assumptions
|
||||
CPPAD_ASSERT_UNKNOWN( NumArg(AbsOp) == 1 );
|
||||
CPPAD_ASSERT_UNKNOWN( NumRes(AbsOp) == 1 );
|
||||
CPPAD_ASSERT_UNKNOWN( q < cap_order );
|
||||
CPPAD_ASSERT_UNKNOWN( p <= q );
|
||||
|
||||
// Taylor coefficients corresponding to argument and result
|
||||
Base* x = taylor + i_x * cap_order;
|
||||
Base* z = taylor + i_z * cap_order;
|
||||
|
||||
for(size_t j = p; j <= q; j++)
|
||||
z[j] = sign(x[0]) * x[j];
|
||||
}
|
||||
|
||||
/*!
|
||||
Multiple directions forward mode Taylor coefficient for op = AbsOp.
|
||||
|
||||
The C++ source code corresponding to this operation is
|
||||
\verbatim
|
||||
z = fabs(x)
|
||||
\endverbatim
|
||||
|
||||
\copydetails CppAD::local::forward_unary1_op_dir
|
||||
*/
|
||||
template <class Base>
|
||||
inline void forward_abs_op_dir(
|
||||
size_t q ,
|
||||
size_t r ,
|
||||
size_t i_z ,
|
||||
size_t i_x ,
|
||||
size_t cap_order ,
|
||||
Base* taylor )
|
||||
{
|
||||
// check assumptions
|
||||
CPPAD_ASSERT_UNKNOWN( NumArg(AbsOp) == 1 );
|
||||
CPPAD_ASSERT_UNKNOWN( NumRes(AbsOp) == 1 );
|
||||
CPPAD_ASSERT_UNKNOWN( 0 < q );
|
||||
CPPAD_ASSERT_UNKNOWN( q < cap_order );
|
||||
|
||||
// Taylor coefficients corresponding to argument and result
|
||||
size_t num_taylor_per_var = (cap_order-1) * r + 1;
|
||||
Base* x = taylor + i_x * num_taylor_per_var;
|
||||
Base* z = taylor + i_z * num_taylor_per_var;
|
||||
|
||||
size_t m = (q-1) * r + 1;
|
||||
for(size_t ell = 0; ell < r; ell++)
|
||||
z[m + ell] = sign(x[0]) * x[m + ell];
|
||||
}
|
||||
|
||||
/*!
|
||||
Compute zero order forward mode Taylor coefficient for result of op = AbsOp.
|
||||
|
||||
The C++ source code corresponding to this operation is
|
||||
\verbatim
|
||||
z = fabs(x)
|
||||
\endverbatim
|
||||
|
||||
\copydetails CppAD::local::forward_unary1_op_0
|
||||
*/
|
||||
template <class Base>
|
||||
inline void forward_abs_op_0(
|
||||
size_t i_z ,
|
||||
size_t i_x ,
|
||||
size_t cap_order ,
|
||||
Base* taylor )
|
||||
{
|
||||
|
||||
// check assumptions
|
||||
CPPAD_ASSERT_UNKNOWN( NumArg(AbsOp) == 1 );
|
||||
CPPAD_ASSERT_UNKNOWN( NumRes(AbsOp) == 1 );
|
||||
CPPAD_ASSERT_UNKNOWN( 0 < cap_order );
|
||||
|
||||
// Taylor coefficients corresponding to argument and result
|
||||
Base x0 = *(taylor + i_x * cap_order);
|
||||
Base* z = taylor + i_z * cap_order;
|
||||
|
||||
z[0] = fabs(x0);
|
||||
}
|
||||
/*!
|
||||
Compute reverse mode partial derivatives for result of op = AbsOp.
|
||||
|
||||
The C++ source code corresponding to this operation is
|
||||
\verbatim
|
||||
z = fabs(x)
|
||||
\endverbatim
|
||||
|
||||
\copydetails CppAD::local::reverse_unary1_op
|
||||
*/
|
||||
|
||||
template <class Base>
|
||||
inline void reverse_abs_op(
|
||||
size_t d ,
|
||||
size_t i_z ,
|
||||
size_t i_x ,
|
||||
size_t cap_order ,
|
||||
const Base* taylor ,
|
||||
size_t nc_partial ,
|
||||
Base* partial )
|
||||
{ size_t j;
|
||||
|
||||
// check assumptions
|
||||
CPPAD_ASSERT_UNKNOWN( NumArg(AbsOp) == 1 );
|
||||
CPPAD_ASSERT_UNKNOWN( NumRes(AbsOp) == 1 );
|
||||
CPPAD_ASSERT_UNKNOWN( d < cap_order );
|
||||
CPPAD_ASSERT_UNKNOWN( d < nc_partial );
|
||||
|
||||
// Taylor coefficients and partials corresponding to argument
|
||||
const Base* x = taylor + i_x * cap_order;
|
||||
Base* px = partial + i_x * nc_partial;
|
||||
|
||||
// Taylor coefficients and partials corresponding to result
|
||||
Base* pz = partial + i_z * nc_partial;
|
||||
|
||||
// do not need azmul because sign is either +1, -1, or zero
|
||||
for(j = 0; j <= d; j++)
|
||||
px[j] += sign(x[0]) * pz[j];
|
||||
}
|
||||
|
||||
} } // END_CPPAD_LOCAL_NAMESPACE
|
||||
# endif
|
||||
+263
@@ -0,0 +1,263 @@
|
||||
# ifndef CPPAD_LOCAL_ACOS_OP_HPP
|
||||
# define CPPAD_LOCAL_ACOS_OP_HPP
|
||||
|
||||
/* --------------------------------------------------------------------------
|
||||
CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-17 Bradley M. Bell
|
||||
|
||||
CppAD is distributed under multiple licenses. This distribution is under
|
||||
the terms of the
|
||||
Eclipse Public License Version 1.0.
|
||||
|
||||
A copy of this license is included in the COPYING file of this distribution.
|
||||
Please visit http://www.coin-or.org/CppAD/ for information on other licenses.
|
||||
-------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
namespace CppAD { namespace local { // BEGIN_CPPAD_LOCAL_NAMESPACE
|
||||
/*!
|
||||
\file acos_op.hpp
|
||||
Forward and reverse mode calculations for z = acos(x).
|
||||
*/
|
||||
|
||||
|
||||
/*!
|
||||
Compute forward mode Taylor coefficient for result of op = AcosOp.
|
||||
|
||||
The C++ source code corresponding to this operation is
|
||||
\verbatim
|
||||
z = acos(x)
|
||||
\endverbatim
|
||||
The auxillary result is
|
||||
\verbatim
|
||||
y = sqrt(1 - x * x)
|
||||
\endverbatim
|
||||
The value of y, and its derivatives, are computed along with the value
|
||||
and derivatives of z.
|
||||
|
||||
\copydetails CppAD::local::forward_unary2_op
|
||||
*/
|
||||
template <class Base>
|
||||
inline void forward_acos_op(
|
||||
size_t p ,
|
||||
size_t q ,
|
||||
size_t i_z ,
|
||||
size_t i_x ,
|
||||
size_t cap_order ,
|
||||
Base* taylor )
|
||||
{
|
||||
// check assumptions
|
||||
CPPAD_ASSERT_UNKNOWN( NumArg(AcosOp) == 1 );
|
||||
CPPAD_ASSERT_UNKNOWN( NumRes(AcosOp) == 2 );
|
||||
CPPAD_ASSERT_UNKNOWN( q < cap_order );
|
||||
CPPAD_ASSERT_UNKNOWN( p <= q );
|
||||
|
||||
// Taylor coefficients corresponding to argument and result
|
||||
Base* x = taylor + i_x * cap_order;
|
||||
Base* z = taylor + i_z * cap_order;
|
||||
Base* b = z - cap_order; // called y in documentation
|
||||
|
||||
size_t k;
|
||||
Base uj;
|
||||
if( p == 0 )
|
||||
{ z[0] = acos( x[0] );
|
||||
uj = Base(1.0) - x[0] * x[0];
|
||||
b[0] = sqrt( uj );
|
||||
p++;
|
||||
}
|
||||
for(size_t j = p; j <= q; j++)
|
||||
{ uj = Base(0.0);
|
||||
for(k = 0; k <= j; k++)
|
||||
uj -= x[k] * x[j-k];
|
||||
b[j] = Base(0.0);
|
||||
z[j] = Base(0.0);
|
||||
for(k = 1; k < j; k++)
|
||||
{ b[j] -= Base(double(k)) * b[k] * b[j-k];
|
||||
z[j] -= Base(double(k)) * z[k] * b[j-k];
|
||||
}
|
||||
b[j] /= Base(double(j));
|
||||
z[j] /= Base(double(j));
|
||||
//
|
||||
b[j] += uj / Base(2.0);
|
||||
z[j] -= x[j];
|
||||
//
|
||||
b[j] /= b[0];
|
||||
z[j] /= b[0];
|
||||
}
|
||||
}
|
||||
/*!
|
||||
Multiple directions forward mode Taylor coefficient for op = AcosOp.
|
||||
|
||||
The C++ source code corresponding to this operation is
|
||||
\verbatim
|
||||
z = acos(x)
|
||||
\endverbatim
|
||||
The auxillary result is
|
||||
\verbatim
|
||||
y = sqrt(1 - x * x)
|
||||
\endverbatim
|
||||
The value of y, and its derivatives, are computed along with the value
|
||||
and derivatives of z.
|
||||
|
||||
\copydetails CppAD::local::forward_unary2_op_dir
|
||||
*/
|
||||
template <class Base>
|
||||
inline void forward_acos_op_dir(
|
||||
size_t q ,
|
||||
size_t r ,
|
||||
size_t i_z ,
|
||||
size_t i_x ,
|
||||
size_t cap_order ,
|
||||
Base* taylor )
|
||||
{
|
||||
// check assumptions
|
||||
CPPAD_ASSERT_UNKNOWN( NumArg(AcosOp) == 1 );
|
||||
CPPAD_ASSERT_UNKNOWN( NumRes(AcosOp) == 2 );
|
||||
CPPAD_ASSERT_UNKNOWN( 0 < q );
|
||||
CPPAD_ASSERT_UNKNOWN( q < cap_order );
|
||||
|
||||
// Taylor coefficients corresponding to argument and result
|
||||
size_t num_taylor_per_var = (cap_order-1) * r + 1;
|
||||
Base* x = taylor + i_x * num_taylor_per_var;
|
||||
Base* z = taylor + i_z * num_taylor_per_var;
|
||||
Base* b = z - num_taylor_per_var; // called y in documentation
|
||||
|
||||
size_t k, ell;
|
||||
size_t m = (q-1) * r + 1;
|
||||
for(ell = 0; ell < r; ell ++)
|
||||
{ Base uq = - 2.0 * x[m + ell] * x[0];
|
||||
for(k = 1; k < q; k++)
|
||||
uq -= x[(k-1)*r+1+ell] * x[(q-k-1)*r+1+ell];
|
||||
b[m+ell] = Base(0.0);
|
||||
z[m+ell] = Base(0.0);
|
||||
for(k = 1; k < q; k++)
|
||||
{ b[m+ell] += Base(double(k)) * b[(k-1)*r+1+ell] * b[(q-k-1)*r+1+ell];
|
||||
z[m+ell] += Base(double(k)) * z[(k-1)*r+1+ell] * b[(q-k-1)*r+1+ell];
|
||||
}
|
||||
b[m+ell] = ( uq / Base(2.0) - b[m+ell] / Base(double(q)) ) / b[0];
|
||||
z[m+ell] = -( x[m+ell] + z[m+ell] / Base(double(q)) ) / b[0];
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
Compute zero order forward mode Taylor coefficient for result of op = AcosOp.
|
||||
|
||||
The C++ source code corresponding to this operation is
|
||||
\verbatim
|
||||
z = acos(x)
|
||||
\endverbatim
|
||||
The auxillary result is
|
||||
\verbatim
|
||||
y = sqrt( 1 - x * x )
|
||||
\endverbatim
|
||||
The value of y is computed along with the value of z.
|
||||
|
||||
\copydetails CppAD::local::forward_unary2_op_0
|
||||
*/
|
||||
template <class Base>
|
||||
inline void forward_acos_op_0(
|
||||
size_t i_z ,
|
||||
size_t i_x ,
|
||||
size_t cap_order ,
|
||||
Base* taylor )
|
||||
{
|
||||
// check assumptions
|
||||
CPPAD_ASSERT_UNKNOWN( NumArg(AcosOp) == 1 );
|
||||
CPPAD_ASSERT_UNKNOWN( NumRes(AcosOp) == 2 );
|
||||
CPPAD_ASSERT_UNKNOWN( 0 < cap_order );
|
||||
|
||||
// Taylor coefficients corresponding to argument and result
|
||||
Base* x = taylor + i_x * cap_order;
|
||||
Base* z = taylor + i_z * cap_order;
|
||||
Base* b = z - cap_order; // called y in documentation
|
||||
|
||||
z[0] = acos( x[0] );
|
||||
b[0] = sqrt( Base(1.0) - x[0] * x[0] );
|
||||
}
|
||||
/*!
|
||||
Compute reverse mode partial derivatives for result of op = AcosOp.
|
||||
|
||||
The C++ source code corresponding to this operation is
|
||||
\verbatim
|
||||
z = acos(x)
|
||||
\endverbatim
|
||||
The auxillary result is
|
||||
\verbatim
|
||||
y = sqrt( 1 - x * x )
|
||||
\endverbatim
|
||||
The value of y is computed along with the value of z.
|
||||
|
||||
\copydetails CppAD::local::reverse_unary2_op
|
||||
*/
|
||||
|
||||
template <class Base>
|
||||
inline void reverse_acos_op(
|
||||
size_t d ,
|
||||
size_t i_z ,
|
||||
size_t i_x ,
|
||||
size_t cap_order ,
|
||||
const Base* taylor ,
|
||||
size_t nc_partial ,
|
||||
Base* partial )
|
||||
{
|
||||
// check assumptions
|
||||
CPPAD_ASSERT_UNKNOWN( NumArg(AcosOp) == 1 );
|
||||
CPPAD_ASSERT_UNKNOWN( NumRes(AcosOp) == 2 );
|
||||
CPPAD_ASSERT_UNKNOWN( d < cap_order );
|
||||
CPPAD_ASSERT_UNKNOWN( d < nc_partial );
|
||||
|
||||
// Taylor coefficients and partials corresponding to argument
|
||||
const Base* x = taylor + i_x * cap_order;
|
||||
Base* px = partial + i_x * nc_partial;
|
||||
|
||||
// Taylor coefficients and partials corresponding to first result
|
||||
const Base* z = taylor + i_z * cap_order;
|
||||
Base* pz = partial + i_z * nc_partial;
|
||||
|
||||
// Taylor coefficients and partials corresponding to auxillary result
|
||||
const Base* b = z - cap_order; // called y in documentation
|
||||
Base* pb = pz - nc_partial;
|
||||
|
||||
Base inv_b0 = Base(1.0) / b[0];
|
||||
|
||||
// number of indices to access
|
||||
size_t j = d;
|
||||
size_t k;
|
||||
while(j)
|
||||
{
|
||||
// scale partials w.r.t b[j] by 1 / b[0]
|
||||
pb[j] = azmul(pb[j], inv_b0);
|
||||
|
||||
// scale partials w.r.t z[j] by 1 / b[0]
|
||||
pz[j] = azmul(pz[j], inv_b0);
|
||||
|
||||
// update partials w.r.t b^0
|
||||
pb[0] -= azmul(pz[j], z[j]) + azmul(pb[j], b[j]);
|
||||
|
||||
// update partial w.r.t. x^0
|
||||
px[0] -= azmul(pb[j], x[j]);
|
||||
|
||||
// update partial w.r.t. x^j
|
||||
px[j] -= pz[j] + azmul(pb[j], x[0]);
|
||||
|
||||
// further scale partial w.r.t. z[j] by 1 / j
|
||||
pz[j] /= Base(double(j));
|
||||
|
||||
for(k = 1; k < j; k++)
|
||||
{ // update partials w.r.t b^(j-k)
|
||||
pb[j-k] -= Base(double(k)) * azmul(pz[j], z[k]) + azmul(pb[j], b[k]);
|
||||
|
||||
// update partials w.r.t. x^k
|
||||
px[k] -= azmul(pb[j], x[j-k]);
|
||||
|
||||
// update partials w.r.t. z^k
|
||||
pz[k] -= Base(double(k)) * azmul(pz[j], b[j-k]);
|
||||
}
|
||||
--j;
|
||||
}
|
||||
|
||||
// j == 0 case
|
||||
px[0] -= azmul( pz[0] + azmul(pb[0], x[0]), inv_b0);
|
||||
}
|
||||
|
||||
} } // END_CPPAD_LOCAL_NAMESPACE
|
||||
# endif
|
||||
+265
@@ -0,0 +1,265 @@
|
||||
# ifndef CPPAD_LOCAL_ACOSH_OP_HPP
|
||||
# define CPPAD_LOCAL_ACOSH_OP_HPP
|
||||
# if CPPAD_USE_CPLUSPLUS_2011
|
||||
|
||||
/* --------------------------------------------------------------------------
|
||||
CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-17 Bradley M. Bell
|
||||
|
||||
CppAD is distributed under multiple licenses. This distribution is under
|
||||
the terms of the
|
||||
Eclipse Public License Version 1.0.
|
||||
|
||||
A copy of this license is included in the COPYING file of this distribution.
|
||||
Please visit http://www.coin-or.org/CppAD/ for information on other licenses.
|
||||
-------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
namespace CppAD { namespace local { // BEGIN_CPPAD_LOCAL_NAMESPACE
|
||||
/*!
|
||||
\file acosh_op.hpp
|
||||
Forward and reverse mode calculations for z = acosh(x).
|
||||
*/
|
||||
|
||||
|
||||
/*!
|
||||
Compute forward mode Taylor coefficient for result of op = AcoshOp.
|
||||
|
||||
The C++ source code corresponding to this operation is
|
||||
\verbatim
|
||||
z = acosh(x)
|
||||
\endverbatim
|
||||
The auxillary result is
|
||||
\verbatim
|
||||
y = sqrt(x * x - 1)
|
||||
\endverbatim
|
||||
The value of y, and its derivatives, are computed along with the value
|
||||
and derivatives of z.
|
||||
|
||||
\copydetails CppAD::local::forward_unary2_op
|
||||
*/
|
||||
template <class Base>
|
||||
inline void forward_acosh_op(
|
||||
size_t p ,
|
||||
size_t q ,
|
||||
size_t i_z ,
|
||||
size_t i_x ,
|
||||
size_t cap_order ,
|
||||
Base* taylor )
|
||||
{
|
||||
// check assumptions
|
||||
CPPAD_ASSERT_UNKNOWN( NumArg(AcoshOp) == 1 );
|
||||
CPPAD_ASSERT_UNKNOWN( NumRes(AcoshOp) == 2 );
|
||||
CPPAD_ASSERT_UNKNOWN( q < cap_order );
|
||||
CPPAD_ASSERT_UNKNOWN( p <= q );
|
||||
|
||||
// Taylor coefficients corresponding to argument and result
|
||||
Base* x = taylor + i_x * cap_order;
|
||||
Base* z = taylor + i_z * cap_order;
|
||||
Base* b = z - cap_order; // called y in documentation
|
||||
|
||||
size_t k;
|
||||
Base uj;
|
||||
if( p == 0 )
|
||||
{ z[0] = acosh( x[0] );
|
||||
uj = x[0] * x[0] - Base(1.0);
|
||||
b[0] = sqrt( uj );
|
||||
p++;
|
||||
}
|
||||
for(size_t j = p; j <= q; j++)
|
||||
{ uj = Base(0.0);
|
||||
for(k = 0; k <= j; k++)
|
||||
uj += x[k] * x[j-k];
|
||||
b[j] = Base(0.0);
|
||||
z[j] = Base(0.0);
|
||||
for(k = 1; k < j; k++)
|
||||
{ b[j] -= Base(double(k)) * b[k] * b[j-k];
|
||||
z[j] -= Base(double(k)) * z[k] * b[j-k];
|
||||
}
|
||||
b[j] /= Base(double(j));
|
||||
z[j] /= Base(double(j));
|
||||
//
|
||||
b[j] += uj / Base(2.0);
|
||||
z[j] += x[j];
|
||||
//
|
||||
b[j] /= b[0];
|
||||
z[j] /= b[0];
|
||||
}
|
||||
}
|
||||
/*!
|
||||
Multiple directions forward mode Taylor coefficient for op = AcoshOp.
|
||||
|
||||
The C++ source code corresponding to this operation is
|
||||
\verbatim
|
||||
z = acosh(x)
|
||||
\endverbatim
|
||||
The auxillary result is
|
||||
\verbatim
|
||||
y = sqrt(x * x - 1)
|
||||
\endverbatim
|
||||
The value of y, and its derivatives, are computed along with the value
|
||||
and derivatives of z.
|
||||
|
||||
\copydetails CppAD::local::forward_unary2_op_dir
|
||||
*/
|
||||
template <class Base>
|
||||
inline void forward_acosh_op_dir(
|
||||
size_t q ,
|
||||
size_t r ,
|
||||
size_t i_z ,
|
||||
size_t i_x ,
|
||||
size_t cap_order ,
|
||||
Base* taylor )
|
||||
{
|
||||
// check assumptions
|
||||
CPPAD_ASSERT_UNKNOWN( NumArg(AcoshOp) == 1 );
|
||||
CPPAD_ASSERT_UNKNOWN( NumRes(AcoshOp) == 2 );
|
||||
CPPAD_ASSERT_UNKNOWN( 0 < q );
|
||||
CPPAD_ASSERT_UNKNOWN( q < cap_order );
|
||||
|
||||
// Taylor coefficients corresponding to argument and result
|
||||
size_t num_taylor_per_var = (cap_order-1) * r + 1;
|
||||
Base* x = taylor + i_x * num_taylor_per_var;
|
||||
Base* z = taylor + i_z * num_taylor_per_var;
|
||||
Base* b = z - num_taylor_per_var; // called y in documentation
|
||||
|
||||
size_t k, ell;
|
||||
size_t m = (q-1) * r + 1;
|
||||
for(ell = 0; ell < r; ell ++)
|
||||
{ Base uq = 2.0 * x[m + ell] * x[0];
|
||||
for(k = 1; k < q; k++)
|
||||
uq += x[(k-1)*r+1+ell] * x[(q-k-1)*r+1+ell];
|
||||
b[m+ell] = Base(0.0);
|
||||
z[m+ell] = Base(0.0);
|
||||
for(k = 1; k < q; k++)
|
||||
{ b[m+ell] += Base(double(k)) * b[(k-1)*r+1+ell] * b[(q-k-1)*r+1+ell];
|
||||
z[m+ell] += Base(double(k)) * z[(k-1)*r+1+ell] * b[(q-k-1)*r+1+ell];
|
||||
}
|
||||
b[m+ell] = ( uq / Base(2.0) - b[m+ell] / Base(double(q)) ) / b[0];
|
||||
z[m+ell] = ( x[m+ell] - z[m+ell] / Base(double(q)) ) / b[0];
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
Compute zero order forward mode Taylor coefficient for result of op = AcoshOp.
|
||||
|
||||
The C++ source code corresponding to this operation is
|
||||
\verbatim
|
||||
z = acosh(x)
|
||||
\endverbatim
|
||||
The auxillary result is
|
||||
\verbatim
|
||||
y = sqrt( x * x - 1 )
|
||||
\endverbatim
|
||||
The value of y is computed along with the value of z.
|
||||
|
||||
\copydetails CppAD::local::forward_unary2_op_0
|
||||
*/
|
||||
template <class Base>
|
||||
inline void forward_acosh_op_0(
|
||||
size_t i_z ,
|
||||
size_t i_x ,
|
||||
size_t cap_order ,
|
||||
Base* taylor )
|
||||
{
|
||||
// check assumptions
|
||||
CPPAD_ASSERT_UNKNOWN( NumArg(AcoshOp) == 1 );
|
||||
CPPAD_ASSERT_UNKNOWN( NumRes(AcoshOp) == 2 );
|
||||
CPPAD_ASSERT_UNKNOWN( 0 < cap_order );
|
||||
|
||||
// Taylor coefficients corresponding to argument and result
|
||||
Base* x = taylor + i_x * cap_order;
|
||||
Base* z = taylor + i_z * cap_order;
|
||||
Base* b = z - cap_order; // called y in documentation
|
||||
|
||||
z[0] = acosh( x[0] );
|
||||
b[0] = sqrt( x[0] * x[0] - Base(1.0) );
|
||||
}
|
||||
/*!
|
||||
Compute reverse mode partial derivatives for result of op = AcoshOp.
|
||||
|
||||
The C++ source code corresponding to this operation is
|
||||
\verbatim
|
||||
z = acosh(x)
|
||||
\endverbatim
|
||||
The auxillary result is
|
||||
\verbatim
|
||||
y = sqrt( x * x - 1 )
|
||||
\endverbatim
|
||||
The value of y is computed along with the value of z.
|
||||
|
||||
\copydetails CppAD::local::reverse_unary2_op
|
||||
*/
|
||||
|
||||
template <class Base>
|
||||
inline void reverse_acosh_op(
|
||||
size_t d ,
|
||||
size_t i_z ,
|
||||
size_t i_x ,
|
||||
size_t cap_order ,
|
||||
const Base* taylor ,
|
||||
size_t nc_partial ,
|
||||
Base* partial )
|
||||
{
|
||||
// check assumptions
|
||||
CPPAD_ASSERT_UNKNOWN( NumArg(AcoshOp) == 1 );
|
||||
CPPAD_ASSERT_UNKNOWN( NumRes(AcoshOp) == 2 );
|
||||
CPPAD_ASSERT_UNKNOWN( d < cap_order );
|
||||
CPPAD_ASSERT_UNKNOWN( d < nc_partial );
|
||||
|
||||
// Taylor coefficients and partials corresponding to argument
|
||||
const Base* x = taylor + i_x * cap_order;
|
||||
Base* px = partial + i_x * nc_partial;
|
||||
|
||||
// Taylor coefficients and partials corresponding to first result
|
||||
const Base* z = taylor + i_z * cap_order;
|
||||
Base* pz = partial + i_z * nc_partial;
|
||||
|
||||
// Taylor coefficients and partials corresponding to auxillary result
|
||||
const Base* b = z - cap_order; // called y in documentation
|
||||
Base* pb = pz - nc_partial;
|
||||
|
||||
Base inv_b0 = Base(1.0) / b[0];
|
||||
|
||||
// number of indices to access
|
||||
size_t j = d;
|
||||
size_t k;
|
||||
while(j)
|
||||
{
|
||||
// scale partials w.r.t b[j] by 1 / b[0]
|
||||
pb[j] = azmul(pb[j], inv_b0);
|
||||
|
||||
// scale partials w.r.t z[j] by 1 / b[0]
|
||||
pz[j] = azmul(pz[j], inv_b0);
|
||||
|
||||
// update partials w.r.t b^0
|
||||
pb[0] -= azmul(pz[j], z[j]) + azmul(pb[j], b[j]);
|
||||
|
||||
// update partial w.r.t. x^0
|
||||
px[0] += azmul(pb[j], x[j]);
|
||||
|
||||
// update partial w.r.t. x^j
|
||||
px[j] += pz[j] + azmul(pb[j], x[0]);
|
||||
|
||||
// further scale partial w.r.t. z[j] by 1 / j
|
||||
pz[j] /= Base(double(j));
|
||||
|
||||
for(k = 1; k < j; k++)
|
||||
{ // update partials w.r.t b^(j-k)
|
||||
pb[j-k] -= Base(double(k)) * azmul(pz[j], z[k]) + azmul(pb[j], b[k]);
|
||||
|
||||
// update partials w.r.t. x^k
|
||||
px[k] += azmul(pb[j], x[j-k]);
|
||||
|
||||
// update partials w.r.t. z^k
|
||||
pz[k] -= Base(double(k)) * azmul(pz[j], b[j-k]);
|
||||
}
|
||||
--j;
|
||||
}
|
||||
|
||||
// j == 0 case
|
||||
px[0] += azmul(pz[0] + azmul(pb[0], x[0]), inv_b0);
|
||||
}
|
||||
|
||||
} } // END_CPPAD_LOCAL_NAMESPACE
|
||||
# endif
|
||||
# endif
|
||||
+219
@@ -0,0 +1,219 @@
|
||||
# ifndef CPPAD_LOCAL_AD_TAPE_HPP
|
||||
# define CPPAD_LOCAL_AD_TAPE_HPP
|
||||
|
||||
/* --------------------------------------------------------------------------
|
||||
CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-17 Bradley M. Bell
|
||||
|
||||
CppAD is distributed under multiple licenses. This distribution is under
|
||||
the terms of the
|
||||
Eclipse Public License Version 1.0.
|
||||
|
||||
A copy of this license is included in the COPYING file of this distribution.
|
||||
Please visit http://www.coin-or.org/CppAD/ for information on other licenses.
|
||||
-------------------------------------------------------------------------- */
|
||||
# include <cppad/core/define.hpp>
|
||||
|
||||
namespace CppAD { namespace local { // BEGIN_CPPAD_LOCAL__NAMESPACE
|
||||
|
||||
/*!
|
||||
Class used to hold tape that records AD<Base> operations.
|
||||
|
||||
\tparam Base
|
||||
An <tt>AD<Base></tt> object is used to recording <tt>AD<Base></tt> operations.
|
||||
*/
|
||||
|
||||
template <class Base>
|
||||
class ADTape {
|
||||
// Friends =============================================================
|
||||
|
||||
// classes -------------------------------------------------------------
|
||||
friend class AD<Base>;
|
||||
friend class ADFun<Base>;
|
||||
friend class atomic_base<Base>;
|
||||
friend class discrete<Base>;
|
||||
friend class VecAD<Base>;
|
||||
friend class VecAD_reference<Base>;
|
||||
|
||||
// functions -----------------------------------------------------------
|
||||
// PrintFor
|
||||
friend void CppAD::PrintFor <Base> (
|
||||
const AD<Base>& flag ,
|
||||
const char* before ,
|
||||
const AD<Base>& var ,
|
||||
const char* after
|
||||
);
|
||||
// CondExpOp
|
||||
friend AD<Base> CppAD::CondExpOp <Base> (
|
||||
enum CompareOp cop ,
|
||||
const AD<Base> &left ,
|
||||
const AD<Base> &right ,
|
||||
const AD<Base> &trueCase ,
|
||||
const AD<Base> &falseCase
|
||||
);
|
||||
// pow
|
||||
friend AD<Base> CppAD::pow <Base>
|
||||
(const AD<Base> &x, const AD<Base> &y);
|
||||
// azmul
|
||||
friend AD<Base> CppAD::azmul <Base>
|
||||
(const AD<Base> &x, const AD<Base> &y);
|
||||
// Parameter
|
||||
friend bool CppAD::Parameter <Base>
|
||||
(const AD<Base> &u);
|
||||
// Variable
|
||||
friend bool CppAD::Variable <Base>
|
||||
(const AD<Base> &u);
|
||||
// operators -----------------------------------------------------------
|
||||
// arithematic binary operators
|
||||
friend AD<Base> CppAD::operator + <Base>
|
||||
(const AD<Base> &left, const AD<Base> &right);
|
||||
friend AD<Base> CppAD::operator - <Base>
|
||||
(const AD<Base> &left, const AD<Base> &right);
|
||||
friend AD<Base> CppAD::operator * <Base>
|
||||
(const AD<Base> &left, const AD<Base> &right);
|
||||
friend AD<Base> CppAD::operator / <Base>
|
||||
(const AD<Base> &left, const AD<Base> &right);
|
||||
|
||||
// comparison operators
|
||||
friend bool CppAD::operator < <Base>
|
||||
(const AD<Base> &left, const AD<Base> &right);
|
||||
friend bool CppAD::operator <= <Base>
|
||||
(const AD<Base> &left, const AD<Base> &right);
|
||||
friend bool CppAD::operator > <Base>
|
||||
(const AD<Base> &left, const AD<Base> &right);
|
||||
friend bool CppAD::operator >= <Base>
|
||||
(const AD<Base> &left, const AD<Base> &right);
|
||||
friend bool CppAD::operator == <Base>
|
||||
(const AD<Base> &left, const AD<Base> &right);
|
||||
friend bool CppAD::operator != <Base>
|
||||
(const AD<Base> &left, const AD<Base> &right);
|
||||
// ======================================================================
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
private:
|
||||
// ----------------------------------------------------------------------
|
||||
// private data
|
||||
/*!
|
||||
Unique identifier for this tape. It is always greater than
|
||||
CPPAD_MAX_NUM_THREADS, and different for every tape (even ones that have
|
||||
been deleted). In addition, id_ % CPPAD_MAX_NUM_THREADS is the thread
|
||||
number for this tape. Set by Independent and effectively const
|
||||
*/
|
||||
tape_id_t id_;
|
||||
/// Number of independent variables in this tapes reconding.
|
||||
/// Set by Independent and effectively const
|
||||
size_t size_independent_;
|
||||
/// This is where the information is recorded.
|
||||
local::recorder<Base> Rec_;
|
||||
// ----------------------------------------------------------------------
|
||||
// private functions
|
||||
//
|
||||
// add a parameter to the tape
|
||||
addr_t RecordParOp(const Base &x);
|
||||
|
||||
// see CondExp.h
|
||||
void RecordCondExp(
|
||||
enum CompareOp cop ,
|
||||
AD<Base> &returnValue ,
|
||||
const AD<Base> &left ,
|
||||
const AD<Base> &right ,
|
||||
const AD<Base> &trueCase ,
|
||||
const AD<Base> &falseCase
|
||||
);
|
||||
|
||||
// place a VecAD object in the tape
|
||||
size_t AddVec(
|
||||
size_t length,
|
||||
const pod_vector<Base>& data
|
||||
);
|
||||
|
||||
public:
|
||||
// default constructor and destructor
|
||||
|
||||
// public function only used by CppAD::Independent
|
||||
template <typename VectorADBase>
|
||||
void Independent(VectorADBase &u);
|
||||
template <typename VectorADBase>
|
||||
void Independent(VectorADBase &u, size_t abort_op_index);
|
||||
|
||||
};
|
||||
// ---------------------------------------------------------------------------
|
||||
// Private functions
|
||||
//
|
||||
|
||||
/*!
|
||||
Place a parameter in the tape.
|
||||
|
||||
On rare occations it is necessary to place a parameter in the tape; e.g.,
|
||||
when it is one of the dependent variabes.
|
||||
|
||||
\param z
|
||||
value of the parameter that we are placing in the tape.
|
||||
|
||||
\return
|
||||
variable index (for this recording) correpsonding to the parameter.
|
||||
|
||||
\par 2DO
|
||||
All these operates are preformed in \c Rec_, so we should
|
||||
move this routine from <tt>ADTape<Base></tt> to <tt>recorder<Base></tt>.
|
||||
*/
|
||||
template <class Base>
|
||||
addr_t ADTape<Base>::RecordParOp(const Base &z)
|
||||
{ addr_t z_taddr;
|
||||
addr_t ind;
|
||||
CPPAD_ASSERT_UNKNOWN( NumRes(ParOp) == 1 );
|
||||
CPPAD_ASSERT_UNKNOWN( NumArg(ParOp) == 1 );
|
||||
z_taddr = Rec_.PutOp(ParOp);
|
||||
ind = Rec_.PutPar(z);
|
||||
Rec_.PutArg(ind);
|
||||
|
||||
return z_taddr;
|
||||
}
|
||||
|
||||
/*!
|
||||
Put initialization for a VecAD<Base> object in the tape.
|
||||
|
||||
This routine should be called once for each VecAD object when just
|
||||
before it changes from a parameter to a variable.
|
||||
|
||||
\param length
|
||||
size of the <tt>VecAD<Base></tt> object.
|
||||
|
||||
\param data
|
||||
initial values for the <tt>VecAD<Base></tt> object
|
||||
(values before it becomes a variable).
|
||||
|
||||
\return
|
||||
index of the start of this vector in the list of vector indices.
|
||||
The value for this vector index is the length of the vector.
|
||||
There are \c length indices following for this vector.
|
||||
The values for these vector indices are the corresponding
|
||||
parameter indices in the tape for the initial value of the corresponding
|
||||
vec_ad element.
|
||||
|
||||
\par 2DO
|
||||
All these operates are preformed in \c Rec_, so we should
|
||||
move this routine from <tt>ADTape<Base></tt> to <tt>recorder<Base></tt>.
|
||||
*/
|
||||
template <class Base>
|
||||
size_t ADTape<Base>::AddVec(size_t length, const pod_vector<Base>& data)
|
||||
{ CPPAD_ASSERT_UNKNOWN( length > 0 );
|
||||
size_t i;
|
||||
size_t value_index;
|
||||
|
||||
// store the length in VecInd
|
||||
size_t start = Rec_.PutVecInd(length);
|
||||
|
||||
// store indices of the values in VecInd
|
||||
for(i = 0; i < length; i++)
|
||||
{
|
||||
value_index = Rec_.PutPar( data[i] );
|
||||
Rec_.PutVecInd( value_index );
|
||||
}
|
||||
|
||||
// return the taddr of the length (where the vector starts)
|
||||
return start;
|
||||
}
|
||||
|
||||
} } // END_CPPAD_LOCAL_NAMESPACE
|
||||
|
||||
# endif
|
||||
+339
@@ -0,0 +1,339 @@
|
||||
// $Id: add_op.hpp 3865 2017-01-19 01:57:55Z bradbell $
|
||||
# ifndef CPPAD_LOCAL_ADD_OP_HPP
|
||||
# define CPPAD_LOCAL_ADD_OP_HPP
|
||||
|
||||
/* --------------------------------------------------------------------------
|
||||
CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-17 Bradley M. Bell
|
||||
|
||||
CppAD is distributed under multiple licenses. This distribution is under
|
||||
the terms of the
|
||||
Eclipse Public License Version 1.0.
|
||||
|
||||
A copy of this license is included in the COPYING file of this distribution.
|
||||
Please visit http://www.coin-or.org/CppAD/ for information on other licenses.
|
||||
-------------------------------------------------------------------------- */
|
||||
|
||||
namespace CppAD { namespace local { // BEGIN_CPPAD_LOCAL_NAMESPACE
|
||||
/*!
|
||||
\file add_op.hpp
|
||||
Forward and reverse mode calculations for z = x + y.
|
||||
*/
|
||||
|
||||
// --------------------------- Addvv -----------------------------------------
|
||||
/*!
|
||||
Compute forward mode Taylor coefficients for result of op = AddvvOp.
|
||||
|
||||
The C++ source code corresponding to this operation is
|
||||
\verbatim
|
||||
z = x + y
|
||||
\endverbatim
|
||||
In the documentation below,
|
||||
this operations is for the case where both x and y are variables
|
||||
and the argument \a parameter is not used.
|
||||
|
||||
\copydetails CppAD::local::forward_binary_op
|
||||
*/
|
||||
|
||||
template <class Base>
|
||||
inline void forward_addvv_op(
|
||||
size_t p ,
|
||||
size_t q ,
|
||||
size_t i_z ,
|
||||
const addr_t* arg ,
|
||||
const Base* parameter ,
|
||||
size_t cap_order ,
|
||||
Base* taylor )
|
||||
{
|
||||
// check assumptions
|
||||
CPPAD_ASSERT_UNKNOWN( NumArg(AddvvOp) == 2 );
|
||||
CPPAD_ASSERT_UNKNOWN( NumRes(AddvvOp) == 1 );
|
||||
CPPAD_ASSERT_UNKNOWN( q < cap_order );
|
||||
CPPAD_ASSERT_UNKNOWN( p <= q );
|
||||
|
||||
// Taylor coefficients corresponding to arguments and result
|
||||
Base* x = taylor + arg[0] * cap_order;
|
||||
Base* y = taylor + arg[1] * cap_order;
|
||||
Base* z = taylor + i_z * cap_order;
|
||||
|
||||
for(size_t j = p; j <= q; j++)
|
||||
z[j] = x[j] + y[j];
|
||||
}
|
||||
/*!
|
||||
Multiple directions forward mode Taylor coefficients for op = AddvvOp.
|
||||
|
||||
The C++ source code corresponding to this operation is
|
||||
\verbatim
|
||||
z = x + y
|
||||
\endverbatim
|
||||
In the documentation below,
|
||||
this operations is for the case where both x and y are variables
|
||||
and the argument \a parameter is not used.
|
||||
|
||||
\copydetails CppAD::local::forward_binary_op_dir
|
||||
*/
|
||||
|
||||
template <class Base>
|
||||
inline void forward_addvv_op_dir(
|
||||
size_t q ,
|
||||
size_t r ,
|
||||
size_t i_z ,
|
||||
const addr_t* arg ,
|
||||
const Base* parameter ,
|
||||
size_t cap_order ,
|
||||
Base* taylor )
|
||||
{
|
||||
// check assumptions
|
||||
CPPAD_ASSERT_UNKNOWN( NumArg(AddvvOp) == 2 );
|
||||
CPPAD_ASSERT_UNKNOWN( NumRes(AddvvOp) == 1 );
|
||||
CPPAD_ASSERT_UNKNOWN( q < cap_order );
|
||||
CPPAD_ASSERT_UNKNOWN( 0 < q );
|
||||
|
||||
// Taylor coefficients corresponding to arguments and result
|
||||
size_t num_taylor_per_var = (cap_order-1) * r + 1;
|
||||
Base* x = taylor + arg[0] * num_taylor_per_var;
|
||||
Base* y = taylor + arg[1] * num_taylor_per_var;
|
||||
Base* z = taylor + i_z * num_taylor_per_var;
|
||||
|
||||
size_t m = (q-1)*r + 1 ;
|
||||
for(size_t ell = 0; ell < r; ell++)
|
||||
z[m+ell] = x[m+ell] + y[m+ell];
|
||||
}
|
||||
|
||||
/*!
|
||||
Compute zero order forward mode Taylor coefficients for result of op = AddvvOp.
|
||||
|
||||
The C++ source code corresponding to this operation is
|
||||
\verbatim
|
||||
z = x + y
|
||||
\endverbatim
|
||||
In the documentation below,
|
||||
this operations is for the case where both x and y are variables
|
||||
and the argument \a parameter is not used.
|
||||
|
||||
\copydetails CppAD::local::forward_binary_op_0
|
||||
*/
|
||||
|
||||
template <class Base>
|
||||
inline void forward_addvv_op_0(
|
||||
size_t i_z ,
|
||||
const addr_t* arg ,
|
||||
const Base* parameter ,
|
||||
size_t cap_order ,
|
||||
Base* taylor )
|
||||
{
|
||||
// check assumptions
|
||||
CPPAD_ASSERT_UNKNOWN( NumArg(AddvvOp) == 2 );
|
||||
CPPAD_ASSERT_UNKNOWN( NumRes(AddvvOp) == 1 );
|
||||
|
||||
// Taylor coefficients corresponding to arguments and result
|
||||
Base* x = taylor + arg[0] * cap_order;
|
||||
Base* y = taylor + arg[1] * cap_order;
|
||||
Base* z = taylor + i_z * cap_order;
|
||||
|
||||
z[0] = x[0] + y[0];
|
||||
}
|
||||
|
||||
/*!
|
||||
Compute reverse mode partial derivatives for result of op = AddvvOp.
|
||||
|
||||
The C++ source code corresponding to this operation is
|
||||
\verbatim
|
||||
z = x + y
|
||||
\endverbatim
|
||||
In the documentation below,
|
||||
this operations is for the case where both x and y are variables
|
||||
and the argument \a parameter is not used.
|
||||
|
||||
\copydetails CppAD::local::reverse_binary_op
|
||||
*/
|
||||
|
||||
template <class Base>
|
||||
inline void reverse_addvv_op(
|
||||
size_t d ,
|
||||
size_t i_z ,
|
||||
const addr_t* arg ,
|
||||
const Base* parameter ,
|
||||
size_t cap_order ,
|
||||
const Base* taylor ,
|
||||
size_t nc_partial ,
|
||||
Base* partial )
|
||||
{
|
||||
// check assumptions
|
||||
CPPAD_ASSERT_UNKNOWN( NumArg(AddvvOp) == 2 );
|
||||
CPPAD_ASSERT_UNKNOWN( NumRes(AddvvOp) == 1 );
|
||||
CPPAD_ASSERT_UNKNOWN( d < cap_order );
|
||||
CPPAD_ASSERT_UNKNOWN( d < nc_partial );
|
||||
|
||||
// Partial derivatives corresponding to arguments and result
|
||||
Base* px = partial + arg[0] * nc_partial;
|
||||
Base* py = partial + arg[1] * nc_partial;
|
||||
Base* pz = partial + i_z * nc_partial;
|
||||
|
||||
// number of indices to access
|
||||
size_t i = d + 1;
|
||||
while(i)
|
||||
{ --i;
|
||||
px[i] += pz[i];
|
||||
py[i] += pz[i];
|
||||
}
|
||||
}
|
||||
|
||||
// --------------------------- Addpv -----------------------------------------
|
||||
/*!
|
||||
Compute forward mode Taylor coefficients for result of op = AddpvOp.
|
||||
|
||||
The C++ source code corresponding to this operation is
|
||||
\verbatim
|
||||
z = x + y
|
||||
\endverbatim
|
||||
In the documentation below,
|
||||
this operations is for the case where x is a parameter and y is a variable.
|
||||
|
||||
\copydetails CppAD::local::forward_binary_op
|
||||
*/
|
||||
template <class Base>
|
||||
inline void forward_addpv_op(
|
||||
size_t p ,
|
||||
size_t q ,
|
||||
size_t i_z ,
|
||||
const addr_t* arg ,
|
||||
const Base* parameter ,
|
||||
size_t cap_order ,
|
||||
Base* taylor )
|
||||
{
|
||||
// check assumptions
|
||||
CPPAD_ASSERT_UNKNOWN( NumArg(AddpvOp) == 2 );
|
||||
CPPAD_ASSERT_UNKNOWN( NumRes(AddpvOp) == 1 );
|
||||
CPPAD_ASSERT_UNKNOWN( q < cap_order );
|
||||
CPPAD_ASSERT_UNKNOWN( p <= q );
|
||||
|
||||
// Taylor coefficients corresponding to arguments and result
|
||||
Base* y = taylor + arg[1] * cap_order;
|
||||
Base* z = taylor + i_z * cap_order;
|
||||
|
||||
if( p == 0 )
|
||||
{ // Paraemter value
|
||||
Base x = parameter[ arg[0] ];
|
||||
z[0] = x + y[0];
|
||||
p++;
|
||||
}
|
||||
for(size_t j = p; j <= q; j++)
|
||||
z[j] = y[j];
|
||||
}
|
||||
/*!
|
||||
Multiple directions forward mode Taylor coefficients for op = AddpvOp.
|
||||
|
||||
The C++ source code corresponding to this operation is
|
||||
\verbatim
|
||||
z = x + y
|
||||
\endverbatim
|
||||
In the documentation below,
|
||||
this operations is for the case where x is a parameter and y is a variable.
|
||||
|
||||
\copydetails CppAD::local::forward_binary_op_dir
|
||||
*/
|
||||
template <class Base>
|
||||
inline void forward_addpv_op_dir(
|
||||
size_t q ,
|
||||
size_t r ,
|
||||
size_t i_z ,
|
||||
const addr_t* arg ,
|
||||
const Base* parameter ,
|
||||
size_t cap_order ,
|
||||
Base* taylor )
|
||||
{
|
||||
// check assumptions
|
||||
CPPAD_ASSERT_UNKNOWN( NumArg(AddpvOp) == 2 );
|
||||
CPPAD_ASSERT_UNKNOWN( NumRes(AddpvOp) == 1 );
|
||||
CPPAD_ASSERT_UNKNOWN( 0 < q );
|
||||
CPPAD_ASSERT_UNKNOWN( q < cap_order );
|
||||
|
||||
// Taylor coefficients corresponding to arguments and result
|
||||
size_t num_taylor_per_var = (cap_order-1) * r + 1;
|
||||
size_t m = (q-1) * r + 1;
|
||||
Base* y = taylor + arg[1] * num_taylor_per_var + m;
|
||||
Base* z = taylor + i_z * num_taylor_per_var + m;
|
||||
|
||||
for(size_t ell = 0; ell < r; ell++)
|
||||
z[ell] = y[ell];
|
||||
}
|
||||
/*!
|
||||
Compute zero order forward mode Taylor coefficient for result of op = AddpvOp.
|
||||
|
||||
The C++ source code corresponding to this operation is
|
||||
\verbatim
|
||||
z = x + y
|
||||
\endverbatim
|
||||
In the documentation below,
|
||||
this operations is for the case where x is a parameter and y is a variable.
|
||||
|
||||
\copydetails CppAD::local::forward_binary_op_0
|
||||
*/
|
||||
|
||||
template <class Base>
|
||||
inline void forward_addpv_op_0(
|
||||
size_t i_z ,
|
||||
const addr_t* arg ,
|
||||
const Base* parameter ,
|
||||
size_t cap_order ,
|
||||
Base* taylor )
|
||||
{
|
||||
// check assumptions
|
||||
CPPAD_ASSERT_UNKNOWN( NumArg(AddpvOp) == 2 );
|
||||
CPPAD_ASSERT_UNKNOWN( NumRes(AddpvOp) == 1 );
|
||||
|
||||
// Paraemter value
|
||||
Base x = parameter[ arg[0] ];
|
||||
|
||||
// Taylor coefficients corresponding to arguments and result
|
||||
Base* y = taylor + arg[1] * cap_order;
|
||||
Base* z = taylor + i_z * cap_order;
|
||||
|
||||
z[0] = x + y[0];
|
||||
}
|
||||
|
||||
/*!
|
||||
Compute reverse mode partial derivative for result of op = AddpvOp.
|
||||
|
||||
The C++ source code corresponding to this operation is
|
||||
\verbatim
|
||||
z = x + y
|
||||
\endverbatim
|
||||
In the documentation below,
|
||||
this operations is for the case where x is a parameter and y is a variable.
|
||||
|
||||
\copydetails CppAD::local::reverse_binary_op
|
||||
*/
|
||||
|
||||
template <class Base>
|
||||
inline void reverse_addpv_op(
|
||||
size_t d ,
|
||||
size_t i_z ,
|
||||
const addr_t* arg ,
|
||||
const Base* parameter ,
|
||||
size_t cap_order ,
|
||||
const Base* taylor ,
|
||||
size_t nc_partial ,
|
||||
Base* partial )
|
||||
{
|
||||
// check assumptions
|
||||
CPPAD_ASSERT_UNKNOWN( NumArg(AddvvOp) == 2 );
|
||||
CPPAD_ASSERT_UNKNOWN( NumRes(AddvvOp) == 1 );
|
||||
CPPAD_ASSERT_UNKNOWN( d < cap_order );
|
||||
CPPAD_ASSERT_UNKNOWN( d < nc_partial );
|
||||
|
||||
// Partial derivatives corresponding to arguments and result
|
||||
Base* py = partial + arg[1] * nc_partial;
|
||||
Base* pz = partial + i_z * nc_partial;
|
||||
|
||||
// number of indices to access
|
||||
size_t i = d + 1;
|
||||
while(i)
|
||||
{ --i;
|
||||
py[i] += pz[i];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
} } // END_CPPAD_LOCAL_NAMESPACE
|
||||
# endif
|
||||
+263
@@ -0,0 +1,263 @@
|
||||
# ifndef CPPAD_LOCAL_ASIN_OP_HPP
|
||||
# define CPPAD_LOCAL_ASIN_OP_HPP
|
||||
|
||||
/* --------------------------------------------------------------------------
|
||||
CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-17 Bradley M. Bell
|
||||
|
||||
CppAD is distributed under multiple licenses. This distribution is under
|
||||
the terms of the
|
||||
Eclipse Public License Version 1.0.
|
||||
|
||||
A copy of this license is included in the COPYING file of this distribution.
|
||||
Please visit http://www.coin-or.org/CppAD/ for information on other licenses.
|
||||
-------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
namespace CppAD { namespace local { // BEGIN_CPPAD_LOCAL_NAMESPACE
|
||||
/*!
|
||||
\file asin_op.hpp
|
||||
Forward and reverse mode calculations for z = asin(x).
|
||||
*/
|
||||
|
||||
|
||||
/*!
|
||||
Compute forward mode Taylor coefficient for result of op = AsinOp.
|
||||
|
||||
The C++ source code corresponding to this operation is
|
||||
\verbatim
|
||||
z = asin(x)
|
||||
\endverbatim
|
||||
The auxillary result is
|
||||
\verbatim
|
||||
y = sqrt(1 - x * x)
|
||||
\endverbatim
|
||||
The value of y, and its derivatives, are computed along with the value
|
||||
and derivatives of z.
|
||||
|
||||
\copydetails CppAD::local::forward_unary2_op
|
||||
*/
|
||||
template <class Base>
|
||||
inline void forward_asin_op(
|
||||
size_t p ,
|
||||
size_t q ,
|
||||
size_t i_z ,
|
||||
size_t i_x ,
|
||||
size_t cap_order ,
|
||||
Base* taylor )
|
||||
{
|
||||
// check assumptions
|
||||
CPPAD_ASSERT_UNKNOWN( NumArg(AsinOp) == 1 );
|
||||
CPPAD_ASSERT_UNKNOWN( NumRes(AsinOp) == 2 );
|
||||
CPPAD_ASSERT_UNKNOWN( q < cap_order );
|
||||
CPPAD_ASSERT_UNKNOWN( p <= q );
|
||||
|
||||
// Taylor coefficients corresponding to argument and result
|
||||
Base* x = taylor + i_x * cap_order;
|
||||
Base* z = taylor + i_z * cap_order;
|
||||
Base* b = z - cap_order; // called y in documentation
|
||||
|
||||
size_t k;
|
||||
Base uj;
|
||||
if( p == 0 )
|
||||
{ z[0] = asin( x[0] );
|
||||
uj = Base(1.0) - x[0] * x[0];
|
||||
b[0] = sqrt( uj );
|
||||
p++;
|
||||
}
|
||||
for(size_t j = p; j <= q; j++)
|
||||
{ uj = Base(0.0);
|
||||
for(k = 0; k <= j; k++)
|
||||
uj -= x[k] * x[j-k];
|
||||
b[j] = Base(0.0);
|
||||
z[j] = Base(0.0);
|
||||
for(k = 1; k < j; k++)
|
||||
{ b[j] -= Base(double(k)) * b[k] * b[j-k];
|
||||
z[j] -= Base(double(k)) * z[k] * b[j-k];
|
||||
}
|
||||
b[j] /= Base(double(j));
|
||||
z[j] /= Base(double(j));
|
||||
//
|
||||
b[j] += uj / Base(2.0);
|
||||
z[j] += x[j];
|
||||
//
|
||||
b[j] /= b[0];
|
||||
z[j] /= b[0];
|
||||
}
|
||||
}
|
||||
/*!
|
||||
Multiple directions forward mode Taylor coefficient for op = AsinOp.
|
||||
|
||||
The C++ source code corresponding to this operation is
|
||||
\verbatim
|
||||
z = asin(x)
|
||||
\endverbatim
|
||||
The auxillary result is
|
||||
\verbatim
|
||||
y = sqrt(1 - x * x)
|
||||
\endverbatim
|
||||
The value of y, and its derivatives, are computed along with the value
|
||||
and derivatives of z.
|
||||
|
||||
\copydetails CppAD::local::forward_unary2_op_dir
|
||||
*/
|
||||
template <class Base>
|
||||
inline void forward_asin_op_dir(
|
||||
size_t q ,
|
||||
size_t r ,
|
||||
size_t i_z ,
|
||||
size_t i_x ,
|
||||
size_t cap_order ,
|
||||
Base* taylor )
|
||||
{
|
||||
// check assumptions
|
||||
CPPAD_ASSERT_UNKNOWN( NumArg(AcosOp) == 1 );
|
||||
CPPAD_ASSERT_UNKNOWN( NumRes(AcosOp) == 2 );
|
||||
CPPAD_ASSERT_UNKNOWN( 0 < q );
|
||||
CPPAD_ASSERT_UNKNOWN( q < cap_order );
|
||||
|
||||
// Taylor coefficients corresponding to argument and result
|
||||
size_t num_taylor_per_var = (cap_order-1) * r + 1;
|
||||
Base* x = taylor + i_x * num_taylor_per_var;
|
||||
Base* z = taylor + i_z * num_taylor_per_var;
|
||||
Base* b = z - num_taylor_per_var; // called y in documentation
|
||||
|
||||
size_t k, ell;
|
||||
size_t m = (q-1) * r + 1;
|
||||
for(ell = 0; ell < r; ell ++)
|
||||
{ Base uq = - 2.0 * x[m + ell] * x[0];
|
||||
for(k = 1; k < q; k++)
|
||||
uq -= x[(k-1)*r+1+ell] * x[(q-k-1)*r+1+ell];
|
||||
b[m+ell] = Base(0.0);
|
||||
z[m+ell] = Base(0.0);
|
||||
for(k = 1; k < q; k++)
|
||||
{ b[m+ell] += Base(double(k)) * b[(k-1)*r+1+ell] * b[(q-k-1)*r+1+ell];
|
||||
z[m+ell] += Base(double(k)) * z[(k-1)*r+1+ell] * b[(q-k-1)*r+1+ell];
|
||||
}
|
||||
b[m+ell] = ( uq / Base(2.0) - b[m+ell] / Base(double(q)) ) / b[0];
|
||||
z[m+ell] = ( x[m+ell] - z[m+ell] / Base(double(q)) ) / b[0];
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
Compute zero order forward mode Taylor coefficient for result of op = AsinOp.
|
||||
|
||||
The C++ source code corresponding to this operation is
|
||||
\verbatim
|
||||
z = asin(x)
|
||||
\endverbatim
|
||||
The auxillary result is
|
||||
\verbatim
|
||||
y = sqrt( 1 - x * x )
|
||||
\endverbatim
|
||||
The value of y is computed along with the value of z.
|
||||
|
||||
\copydetails CppAD::local::forward_unary2_op_0
|
||||
*/
|
||||
template <class Base>
|
||||
inline void forward_asin_op_0(
|
||||
size_t i_z ,
|
||||
size_t i_x ,
|
||||
size_t cap_order ,
|
||||
Base* taylor )
|
||||
{
|
||||
// check assumptions
|
||||
CPPAD_ASSERT_UNKNOWN( NumArg(AsinOp) == 1 );
|
||||
CPPAD_ASSERT_UNKNOWN( NumRes(AsinOp) == 2 );
|
||||
CPPAD_ASSERT_UNKNOWN( 0 < cap_order );
|
||||
|
||||
// Taylor coefficients corresponding to argument and result
|
||||
Base* x = taylor + i_x * cap_order;
|
||||
Base* z = taylor + i_z * cap_order;
|
||||
Base* b = z - cap_order; // called y in documentation
|
||||
|
||||
z[0] = asin( x[0] );
|
||||
b[0] = sqrt( Base(1.0) - x[0] * x[0] );
|
||||
}
|
||||
/*!
|
||||
Compute reverse mode partial derivatives for result of op = AsinOp.
|
||||
|
||||
The C++ source code corresponding to this operation is
|
||||
\verbatim
|
||||
z = asin(x)
|
||||
\endverbatim
|
||||
The auxillary result is
|
||||
\verbatim
|
||||
y = sqrt( 1 - x * x )
|
||||
\endverbatim
|
||||
The value of y is computed along with the value of z.
|
||||
|
||||
\copydetails CppAD::local::reverse_unary2_op
|
||||
*/
|
||||
|
||||
template <class Base>
|
||||
inline void reverse_asin_op(
|
||||
size_t d ,
|
||||
size_t i_z ,
|
||||
size_t i_x ,
|
||||
size_t cap_order ,
|
||||
const Base* taylor ,
|
||||
size_t nc_partial ,
|
||||
Base* partial )
|
||||
{
|
||||
// check assumptions
|
||||
CPPAD_ASSERT_UNKNOWN( NumArg(AsinOp) == 1 );
|
||||
CPPAD_ASSERT_UNKNOWN( NumRes(AsinOp) == 2 );
|
||||
CPPAD_ASSERT_UNKNOWN( d < cap_order );
|
||||
CPPAD_ASSERT_UNKNOWN( d < nc_partial );
|
||||
|
||||
// Taylor coefficients and partials corresponding to argument
|
||||
const Base* x = taylor + i_x * cap_order;
|
||||
Base* px = partial + i_x * nc_partial;
|
||||
|
||||
// Taylor coefficients and partials corresponding to first result
|
||||
const Base* z = taylor + i_z * cap_order;
|
||||
Base* pz = partial + i_z * nc_partial;
|
||||
|
||||
// Taylor coefficients and partials corresponding to auxillary result
|
||||
const Base* b = z - cap_order; // called y in documentation
|
||||
Base* pb = pz - nc_partial;
|
||||
|
||||
Base inv_b0 = Base(1.0) / b[0];
|
||||
|
||||
// number of indices to access
|
||||
size_t j = d;
|
||||
size_t k;
|
||||
while(j)
|
||||
{
|
||||
// scale partials w.r.t b[j] by 1 / b[0]
|
||||
pb[j] = azmul(pb[j], inv_b0);
|
||||
|
||||
// scale partials w.r.t z[j] by 1 / b[0]
|
||||
pz[j] = azmul(pz[j], inv_b0);
|
||||
|
||||
// update partials w.r.t b^0
|
||||
pb[0] -= azmul(pz[j], z[j]) + azmul(pb[j], b[j]);
|
||||
|
||||
// update partial w.r.t. x^0
|
||||
px[0] -= azmul(pb[j], x[j]);
|
||||
|
||||
// update partial w.r.t. x^j
|
||||
px[j] += pz[j] - azmul(pb[j], x[0]);
|
||||
|
||||
// further scale partial w.r.t. z[j] by 1 / j
|
||||
pz[j] /= Base(double(j));
|
||||
|
||||
for(k = 1; k < j; k++)
|
||||
{ // update partials w.r.t b^(j-k)
|
||||
pb[j-k] -= Base(double(k)) * azmul(pz[j], z[k]) + azmul(pb[j], b[k]);
|
||||
|
||||
// update partials w.r.t. x^k
|
||||
px[k] -= azmul(pb[j], x[j-k]);
|
||||
|
||||
// update partials w.r.t. z^k
|
||||
pz[k] -= Base(double(k)) * azmul(pz[j], b[j-k]);
|
||||
}
|
||||
--j;
|
||||
}
|
||||
|
||||
// j == 0 case
|
||||
px[0] += azmul(pz[0] - azmul(pb[0], x[0]), inv_b0);
|
||||
}
|
||||
|
||||
} } // END_CPPAD_LOCAL_NAMESPACE
|
||||
# endif
|
||||
+265
@@ -0,0 +1,265 @@
|
||||
# ifndef CPPAD_LOCAL_ASINH_OP_HPP
|
||||
# define CPPAD_LOCAL_ASINH_OP_HPP
|
||||
# if CPPAD_USE_CPLUSPLUS_2011
|
||||
|
||||
/* --------------------------------------------------------------------------
|
||||
CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-17 Bradley M. Bell
|
||||
|
||||
CppAD is distributed under multiple licenses. This distribution is under
|
||||
the terms of the
|
||||
Eclipse Public License Version 1.0.
|
||||
|
||||
A copy of this license is included in the COPYING file of this distribution.
|
||||
Please visit http://www.coin-or.org/CppAD/ for information on other licenses.
|
||||
-------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
namespace CppAD { namespace local { // BEGIN_CPPAD_LOCAL_NAMESPACE
|
||||
/*!
|
||||
\file asinh_op.hpp
|
||||
Forward and reverse mode calculations for z = asinh(x).
|
||||
*/
|
||||
|
||||
|
||||
/*!
|
||||
Compute forward mode Taylor coefficient for result of op = AsinhOp.
|
||||
|
||||
The C++ source code corresponding to this operation is
|
||||
\verbatim
|
||||
z = asinh(x)
|
||||
\endverbatim
|
||||
The auxillary result is
|
||||
\verbatim
|
||||
y = sqrt(1 + x * x)
|
||||
\endverbatim
|
||||
The value of y, and its derivatives, are computed along with the value
|
||||
and derivatives of z.
|
||||
|
||||
\copydetails CppAD::local::forward_unary2_op
|
||||
*/
|
||||
template <class Base>
|
||||
inline void forward_asinh_op(
|
||||
size_t p ,
|
||||
size_t q ,
|
||||
size_t i_z ,
|
||||
size_t i_x ,
|
||||
size_t cap_order ,
|
||||
Base* taylor )
|
||||
{
|
||||
// check assumptions
|
||||
CPPAD_ASSERT_UNKNOWN( NumArg(AsinhOp) == 1 );
|
||||
CPPAD_ASSERT_UNKNOWN( NumRes(AsinhOp) == 2 );
|
||||
CPPAD_ASSERT_UNKNOWN( q < cap_order );
|
||||
CPPAD_ASSERT_UNKNOWN( p <= q );
|
||||
|
||||
// Taylor coefficients corresponding to argument and result
|
||||
Base* x = taylor + i_x * cap_order;
|
||||
Base* z = taylor + i_z * cap_order;
|
||||
Base* b = z - cap_order; // called y in documentation
|
||||
|
||||
size_t k;
|
||||
Base uj;
|
||||
if( p == 0 )
|
||||
{ z[0] = asinh( x[0] );
|
||||
uj = Base(1.0) + x[0] * x[0];
|
||||
b[0] = sqrt( uj );
|
||||
p++;
|
||||
}
|
||||
for(size_t j = p; j <= q; j++)
|
||||
{ uj = Base(0.0);
|
||||
for(k = 0; k <= j; k++)
|
||||
uj += x[k] * x[j-k];
|
||||
b[j] = Base(0.0);
|
||||
z[j] = Base(0.0);
|
||||
for(k = 1; k < j; k++)
|
||||
{ b[j] -= Base(double(k)) * b[k] * b[j-k];
|
||||
z[j] -= Base(double(k)) * z[k] * b[j-k];
|
||||
}
|
||||
b[j] /= Base(double(j));
|
||||
z[j] /= Base(double(j));
|
||||
//
|
||||
b[j] += uj / Base(2.0);
|
||||
z[j] += x[j];
|
||||
//
|
||||
b[j] /= b[0];
|
||||
z[j] /= b[0];
|
||||
}
|
||||
}
|
||||
/*!
|
||||
Multiple directions forward mode Taylor coefficient for op = AsinhOp.
|
||||
|
||||
The C++ source code corresponding to this operation is
|
||||
\verbatim
|
||||
z = asinh(x)
|
||||
\endverbatim
|
||||
The auxillary result is
|
||||
\verbatim
|
||||
y = sqrt(1 + x * x)
|
||||
\endverbatim
|
||||
The value of y, and its derivatives, are computed along with the value
|
||||
and derivatives of z.
|
||||
|
||||
\copydetails CppAD::local::forward_unary2_op_dir
|
||||
*/
|
||||
template <class Base>
|
||||
inline void forward_asinh_op_dir(
|
||||
size_t q ,
|
||||
size_t r ,
|
||||
size_t i_z ,
|
||||
size_t i_x ,
|
||||
size_t cap_order ,
|
||||
Base* taylor )
|
||||
{
|
||||
// check assumptions
|
||||
CPPAD_ASSERT_UNKNOWN( NumArg(AcosOp) == 1 );
|
||||
CPPAD_ASSERT_UNKNOWN( NumRes(AcosOp) == 2 );
|
||||
CPPAD_ASSERT_UNKNOWN( 0 < q );
|
||||
CPPAD_ASSERT_UNKNOWN( q < cap_order );
|
||||
|
||||
// Taylor coefficients corresponding to argument and result
|
||||
size_t num_taylor_per_var = (cap_order-1) * r + 1;
|
||||
Base* x = taylor + i_x * num_taylor_per_var;
|
||||
Base* z = taylor + i_z * num_taylor_per_var;
|
||||
Base* b = z - num_taylor_per_var; // called y in documentation
|
||||
|
||||
size_t k, ell;
|
||||
size_t m = (q-1) * r + 1;
|
||||
for(ell = 0; ell < r; ell ++)
|
||||
{ Base uq = 2.0 * x[m + ell] * x[0];
|
||||
for(k = 1; k < q; k++)
|
||||
uq += x[(k-1)*r+1+ell] * x[(q-k-1)*r+1+ell];
|
||||
b[m+ell] = Base(0.0);
|
||||
z[m+ell] = Base(0.0);
|
||||
for(k = 1; k < q; k++)
|
||||
{ b[m+ell] += Base(double(k)) * b[(k-1)*r+1+ell] * b[(q-k-1)*r+1+ell];
|
||||
z[m+ell] += Base(double(k)) * z[(k-1)*r+1+ell] * b[(q-k-1)*r+1+ell];
|
||||
}
|
||||
b[m+ell] = ( uq / Base(2.0) - b[m+ell] / Base(double(q)) ) / b[0];
|
||||
z[m+ell] = ( x[m+ell] - z[m+ell] / Base(double(q)) ) / b[0];
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
Compute zero order forward mode Taylor coefficient for result of op = AsinhOp.
|
||||
|
||||
The C++ source code corresponding to this operation is
|
||||
\verbatim
|
||||
z = asinh(x)
|
||||
\endverbatim
|
||||
The auxillary result is
|
||||
\verbatim
|
||||
y = sqrt( 1 + x * x )
|
||||
\endverbatim
|
||||
The value of y is computed along with the value of z.
|
||||
|
||||
\copydetails CppAD::local::forward_unary2_op_0
|
||||
*/
|
||||
template <class Base>
|
||||
inline void forward_asinh_op_0(
|
||||
size_t i_z ,
|
||||
size_t i_x ,
|
||||
size_t cap_order ,
|
||||
Base* taylor )
|
||||
{
|
||||
// check assumptions
|
||||
CPPAD_ASSERT_UNKNOWN( NumArg(AsinhOp) == 1 );
|
||||
CPPAD_ASSERT_UNKNOWN( NumRes(AsinhOp) == 2 );
|
||||
CPPAD_ASSERT_UNKNOWN( 0 < cap_order );
|
||||
|
||||
// Taylor coefficients corresponding to argument and result
|
||||
Base* x = taylor + i_x * cap_order;
|
||||
Base* z = taylor + i_z * cap_order;
|
||||
Base* b = z - cap_order; // called y in documentation
|
||||
|
||||
z[0] = asinh( x[0] );
|
||||
b[0] = sqrt( Base(1.0) + x[0] * x[0] );
|
||||
}
|
||||
/*!
|
||||
Compute reverse mode partial derivatives for result of op = AsinhOp.
|
||||
|
||||
The C++ source code corresponding to this operation is
|
||||
\verbatim
|
||||
z = asinh(x)
|
||||
\endverbatim
|
||||
The auxillary result is
|
||||
\verbatim
|
||||
y = sqrt( 1 + x * x )
|
||||
\endverbatim
|
||||
The value of y is computed along with the value of z.
|
||||
|
||||
\copydetails CppAD::local::reverse_unary2_op
|
||||
*/
|
||||
|
||||
template <class Base>
|
||||
inline void reverse_asinh_op(
|
||||
size_t d ,
|
||||
size_t i_z ,
|
||||
size_t i_x ,
|
||||
size_t cap_order ,
|
||||
const Base* taylor ,
|
||||
size_t nc_partial ,
|
||||
Base* partial )
|
||||
{
|
||||
// check assumptions
|
||||
CPPAD_ASSERT_UNKNOWN( NumArg(AsinhOp) == 1 );
|
||||
CPPAD_ASSERT_UNKNOWN( NumRes(AsinhOp) == 2 );
|
||||
CPPAD_ASSERT_UNKNOWN( d < cap_order );
|
||||
CPPAD_ASSERT_UNKNOWN( d < nc_partial );
|
||||
|
||||
// Taylor coefficients and partials corresponding to argument
|
||||
const Base* x = taylor + i_x * cap_order;
|
||||
Base* px = partial + i_x * nc_partial;
|
||||
|
||||
// Taylor coefficients and partials corresponding to first result
|
||||
const Base* z = taylor + i_z * cap_order;
|
||||
Base* pz = partial + i_z * nc_partial;
|
||||
|
||||
// Taylor coefficients and partials corresponding to auxillary result
|
||||
const Base* b = z - cap_order; // called y in documentation
|
||||
Base* pb = pz - nc_partial;
|
||||
|
||||
Base inv_b0 = Base(1.0) / b[0];
|
||||
|
||||
// number of indices to access
|
||||
size_t j = d;
|
||||
size_t k;
|
||||
while(j)
|
||||
{
|
||||
// scale partials w.r.t b[j] by 1 / b[0]
|
||||
pb[j] = azmul(pb[j], inv_b0);
|
||||
|
||||
// scale partials w.r.t z[j] by 1 / b[0]
|
||||
pz[j] = azmul(pz[j], inv_b0);
|
||||
|
||||
// update partials w.r.t b^0
|
||||
pb[0] -= azmul(pz[j], z[j]) + azmul(pb[j], b[j]);
|
||||
|
||||
// update partial w.r.t. x^0
|
||||
px[0] += azmul(pb[j], x[j]);
|
||||
|
||||
// update partial w.r.t. x^j
|
||||
px[j] += pz[j] + azmul(pb[j], x[0]);
|
||||
|
||||
// further scale partial w.r.t. z[j] by 1 / j
|
||||
pz[j] /= Base(double(j));
|
||||
|
||||
for(k = 1; k < j; k++)
|
||||
{ // update partials w.r.t b^(j-k)
|
||||
pb[j-k] -= Base(double(k)) * azmul(pz[j], z[k]) + azmul(pb[j], b[k]);
|
||||
|
||||
// update partials w.r.t. x^k
|
||||
px[k] += azmul(pb[j], x[j-k]);
|
||||
|
||||
// update partials w.r.t. z^k
|
||||
pz[k] -= Base(double(k)) * azmul(pz[j], b[j-k]);
|
||||
}
|
||||
--j;
|
||||
}
|
||||
|
||||
// j == 0 case
|
||||
px[0] += azmul(pz[0] + azmul(pb[0], x[0]), inv_b0);
|
||||
}
|
||||
|
||||
} } // END_CPPAD_LOCAL_NAMESPACE
|
||||
# endif
|
||||
# endif
|
||||
+235
@@ -0,0 +1,235 @@
|
||||
# ifndef CPPAD_LOCAL_ATAN_OP_HPP
|
||||
# define CPPAD_LOCAL_ATAN_OP_HPP
|
||||
|
||||
/* --------------------------------------------------------------------------
|
||||
CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-17 Bradley M. Bell
|
||||
|
||||
CppAD is distributed under multiple licenses. This distribution is under
|
||||
the terms of the
|
||||
Eclipse Public License Version 1.0.
|
||||
|
||||
A copy of this license is included in the COPYING file of this distribution.
|
||||
Please visit http://www.coin-or.org/CppAD/ for information on other licenses.
|
||||
-------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
namespace CppAD { namespace local { // BEGIN_CPPAD_LOCAL_NAMESPACE
|
||||
/*!
|
||||
\file atan_op.hpp
|
||||
Forward and reverse mode calculations for z = atan(x).
|
||||
*/
|
||||
|
||||
|
||||
/*!
|
||||
Forward mode Taylor coefficient for result of op = AtanOp.
|
||||
|
||||
The C++ source code corresponding to this operation is
|
||||
\verbatim
|
||||
z = atan(x)
|
||||
\endverbatim
|
||||
The auxillary result is
|
||||
\verbatim
|
||||
y = 1 + x * x
|
||||
\endverbatim
|
||||
The value of y, and its derivatives, are computed along with the value
|
||||
and derivatives of z.
|
||||
|
||||
\copydetails CppAD::local::forward_unary2_op
|
||||
*/
|
||||
template <class Base>
|
||||
inline void forward_atan_op(
|
||||
size_t p ,
|
||||
size_t q ,
|
||||
size_t i_z ,
|
||||
size_t i_x ,
|
||||
size_t cap_order ,
|
||||
Base* taylor )
|
||||
{
|
||||
// check assumptions
|
||||
CPPAD_ASSERT_UNKNOWN( NumArg(AtanOp) == 1 );
|
||||
CPPAD_ASSERT_UNKNOWN( NumRes(AtanOp) == 2 );
|
||||
CPPAD_ASSERT_UNKNOWN( q < cap_order );
|
||||
CPPAD_ASSERT_UNKNOWN( p <= q );
|
||||
|
||||
// Taylor coefficients corresponding to argument and result
|
||||
Base* x = taylor + i_x * cap_order;
|
||||
Base* z = taylor + i_z * cap_order;
|
||||
Base* b = z - cap_order; // called y in documentation
|
||||
|
||||
size_t k;
|
||||
if( p == 0 )
|
||||
{ z[0] = atan( x[0] );
|
||||
b[0] = Base(1.0) + x[0] * x[0];
|
||||
p++;
|
||||
}
|
||||
for(size_t j = p; j <= q; j++)
|
||||
{
|
||||
b[j] = Base(2.0) * x[0] * x[j];
|
||||
z[j] = Base(0.0);
|
||||
for(k = 1; k < j; k++)
|
||||
{ b[j] += x[k] * x[j-k];
|
||||
z[j] -= Base(double(k)) * z[k] * b[j-k];
|
||||
}
|
||||
z[j] /= Base(double(j));
|
||||
z[j] += x[j];
|
||||
z[j] /= b[0];
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
Multiple direction Taylor coefficient for op = AtanOp.
|
||||
|
||||
The C++ source code corresponding to this operation is
|
||||
\verbatim
|
||||
z = atan(x)
|
||||
\endverbatim
|
||||
The auxillary result is
|
||||
\verbatim
|
||||
y = 1 + x * x
|
||||
\endverbatim
|
||||
The value of y, and its derivatives, are computed along with the value
|
||||
and derivatives of z.
|
||||
|
||||
\copydetails CppAD::local::forward_unary2_op_dir
|
||||
*/
|
||||
template <class Base>
|
||||
inline void forward_atan_op_dir(
|
||||
size_t q ,
|
||||
size_t r ,
|
||||
size_t i_z ,
|
||||
size_t i_x ,
|
||||
size_t cap_order ,
|
||||
Base* taylor )
|
||||
{
|
||||
// check assumptions
|
||||
CPPAD_ASSERT_UNKNOWN( NumArg(AtanOp) == 1 );
|
||||
CPPAD_ASSERT_UNKNOWN( NumRes(AtanOp) == 2 );
|
||||
CPPAD_ASSERT_UNKNOWN( 0 < q );
|
||||
CPPAD_ASSERT_UNKNOWN( q < cap_order );
|
||||
|
||||
// Taylor coefficients corresponding to argument and result
|
||||
size_t num_taylor_per_var = (cap_order-1) * r + 1;
|
||||
Base* x = taylor + i_x * num_taylor_per_var;
|
||||
Base* z = taylor + i_z * num_taylor_per_var;
|
||||
Base* b = z - num_taylor_per_var; // called y in documentation
|
||||
|
||||
size_t m = (q-1) * r + 1;
|
||||
for(size_t ell = 0; ell < r; ell++)
|
||||
{ b[m+ell] = Base(2.0) * x[m+ell] * x[0];
|
||||
z[m+ell] = Base(double(q)) * x[m+ell];
|
||||
for(size_t k = 1; k < q; k++)
|
||||
{ b[m+ell] += x[(k-1)*r+1+ell] * x[(q-k-1)*r+1+ell];
|
||||
z[m+ell] -= Base(double(k)) * z[(k-1)*r+1+ell] * b[(q-k-1)*r+1+ell];
|
||||
}
|
||||
z[m+ell] /= ( Base(double(q)) * b[0] );
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
Zero order forward mode Taylor coefficient for result of op = AtanOp.
|
||||
|
||||
The C++ source code corresponding to this operation is
|
||||
\verbatim
|
||||
z = atan(x)
|
||||
\endverbatim
|
||||
The auxillary result is
|
||||
\verbatim
|
||||
y = 1 + x * x
|
||||
\endverbatim
|
||||
The value of y is computed along with the value of z.
|
||||
|
||||
\copydetails CppAD::local::forward_unary2_op_0
|
||||
*/
|
||||
template <class Base>
|
||||
inline void forward_atan_op_0(
|
||||
size_t i_z ,
|
||||
size_t i_x ,
|
||||
size_t cap_order ,
|
||||
Base* taylor )
|
||||
{
|
||||
// check assumptions
|
||||
CPPAD_ASSERT_UNKNOWN( NumArg(AtanOp) == 1 );
|
||||
CPPAD_ASSERT_UNKNOWN( NumRes(AtanOp) == 2 );
|
||||
CPPAD_ASSERT_UNKNOWN( 0 < cap_order );
|
||||
|
||||
// Taylor coefficients corresponding to argument and result
|
||||
Base* x = taylor + i_x * cap_order;
|
||||
Base* z = taylor + i_z * cap_order;
|
||||
Base* b = z - cap_order; // called y in documentation
|
||||
|
||||
z[0] = atan( x[0] );
|
||||
b[0] = Base(1.0) + x[0] * x[0];
|
||||
}
|
||||
/*!
|
||||
Reverse mode partial derivatives for result of op = AtanOp.
|
||||
|
||||
The C++ source code corresponding to this operation is
|
||||
\verbatim
|
||||
z = atan(x)
|
||||
\endverbatim
|
||||
The auxillary result is
|
||||
\verbatim
|
||||
y = 1 + x * x
|
||||
\endverbatim
|
||||
The value of y is computed along with the value of z.
|
||||
|
||||
\copydetails CppAD::local::reverse_unary2_op
|
||||
*/
|
||||
|
||||
template <class Base>
|
||||
inline void reverse_atan_op(
|
||||
size_t d ,
|
||||
size_t i_z ,
|
||||
size_t i_x ,
|
||||
size_t cap_order ,
|
||||
const Base* taylor ,
|
||||
size_t nc_partial ,
|
||||
Base* partial )
|
||||
{
|
||||
// check assumptions
|
||||
CPPAD_ASSERT_UNKNOWN( NumArg(AtanOp) == 1 );
|
||||
CPPAD_ASSERT_UNKNOWN( NumRes(AtanOp) == 2 );
|
||||
CPPAD_ASSERT_UNKNOWN( d < cap_order );
|
||||
CPPAD_ASSERT_UNKNOWN( d < nc_partial );
|
||||
|
||||
// Taylor coefficients and partials corresponding to argument
|
||||
const Base* x = taylor + i_x * cap_order;
|
||||
Base* px = partial + i_x * nc_partial;
|
||||
|
||||
// Taylor coefficients and partials corresponding to first result
|
||||
const Base* z = taylor + i_z * cap_order;
|
||||
Base* pz = partial + i_z * nc_partial;
|
||||
|
||||
// Taylor coefficients and partials corresponding to auxillary result
|
||||
const Base* b = z - cap_order; // called y in documentation
|
||||
Base* pb = pz - nc_partial;
|
||||
|
||||
Base inv_b0 = Base(1.0) / b[0];
|
||||
|
||||
// number of indices to access
|
||||
size_t j = d;
|
||||
size_t k;
|
||||
while(j)
|
||||
{ // scale partials w.r.t z[j] and b[j]
|
||||
pz[j] = azmul(pz[j], inv_b0);
|
||||
pb[j] *= Base(2.0);
|
||||
|
||||
pb[0] -= azmul(pz[j], z[j]);
|
||||
px[j] += pz[j] + azmul(pb[j], x[0]);
|
||||
px[0] += azmul(pb[j], x[j]);
|
||||
|
||||
// more scaling of partials w.r.t z[j]
|
||||
pz[j] /= Base(double(j));
|
||||
|
||||
for(k = 1; k < j; k++)
|
||||
{ pb[j-k] -= Base(double(k)) * azmul(pz[j], z[k]);
|
||||
pz[k] -= Base(double(k)) * azmul(pz[j], b[j-k]);
|
||||
px[k] += azmul(pb[j], x[j-k]);
|
||||
}
|
||||
--j;
|
||||
}
|
||||
px[0] += azmul(pz[0], inv_b0) + Base(2.0) * azmul(pb[0], x[0]);
|
||||
}
|
||||
|
||||
} } // END_CPPAD_LOCAL_NAMESPACE
|
||||
# endif
|
||||
+237
@@ -0,0 +1,237 @@
|
||||
# ifndef CPPAD_LOCAL_ATANH_OP_HPP
|
||||
# define CPPAD_LOCAL_ATANH_OP_HPP
|
||||
# if CPPAD_USE_CPLUSPLUS_2011
|
||||
|
||||
/* --------------------------------------------------------------------------
|
||||
CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-17 Bradley M. Bell
|
||||
|
||||
CppAD is distributed under multiple licenses. This distribution is under
|
||||
the terms of the
|
||||
Eclipse Public License Version 1.0.
|
||||
|
||||
A copy of this license is included in the COPYING file of this distribution.
|
||||
Please visit http://www.coin-or.org/CppAD/ for information on other licenses.
|
||||
-------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
namespace CppAD { namespace local { // BEGIN_CPPAD_LOCAL_NAMESPACE
|
||||
/*!
|
||||
\file atanh_op.hpp
|
||||
Forward and reverse mode calculations for z = atanh(x).
|
||||
*/
|
||||
|
||||
|
||||
/*!
|
||||
Forward mode Taylor coefficient for result of op = AtanhOp.
|
||||
|
||||
The C++ source code corresponding to this operation is
|
||||
\verbatim
|
||||
z = atanh(x)
|
||||
\endverbatim
|
||||
The auxillary result is
|
||||
\verbatim
|
||||
y = 1 - x * x
|
||||
\endverbatim
|
||||
The value of y, and its derivatives, are computed along with the value
|
||||
and derivatives of z.
|
||||
|
||||
\copydetails CppAD::local::forward_unary2_op
|
||||
*/
|
||||
template <class Base>
|
||||
inline void forward_atanh_op(
|
||||
size_t p ,
|
||||
size_t q ,
|
||||
size_t i_z ,
|
||||
size_t i_x ,
|
||||
size_t cap_order ,
|
||||
Base* taylor )
|
||||
{
|
||||
// check assumptions
|
||||
CPPAD_ASSERT_UNKNOWN( NumArg(AtanhOp) == 1 );
|
||||
CPPAD_ASSERT_UNKNOWN( NumRes(AtanhOp) == 2 );
|
||||
CPPAD_ASSERT_UNKNOWN( q < cap_order );
|
||||
CPPAD_ASSERT_UNKNOWN( p <= q );
|
||||
|
||||
// Taylor coefficients corresponding to argument and result
|
||||
Base* x = taylor + i_x * cap_order;
|
||||
Base* z = taylor + i_z * cap_order;
|
||||
Base* b = z - cap_order; // called y in documentation
|
||||
|
||||
size_t k;
|
||||
if( p == 0 )
|
||||
{ z[0] = atanh( x[0] );
|
||||
b[0] = Base(1.0) - x[0] * x[0];
|
||||
p++;
|
||||
}
|
||||
for(size_t j = p; j <= q; j++)
|
||||
{
|
||||
b[j] = - Base(2.0) * x[0] * x[j];
|
||||
z[j] = Base(0.0);
|
||||
for(k = 1; k < j; k++)
|
||||
{ b[j] -= x[k] * x[j-k];
|
||||
z[j] -= Base(double(k)) * z[k] * b[j-k];
|
||||
}
|
||||
z[j] /= Base(double(j));
|
||||
z[j] += x[j];
|
||||
z[j] /= b[0];
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
Multiple direction Taylor coefficient for op = AtanhOp.
|
||||
|
||||
The C++ source code corresponding to this operation is
|
||||
\verbatim
|
||||
z = atanh(x)
|
||||
\endverbatim
|
||||
The auxillary result is
|
||||
\verbatim
|
||||
y = 1 - x * x
|
||||
\endverbatim
|
||||
The value of y, and its derivatives, are computed along with the value
|
||||
and derivatives of z.
|
||||
|
||||
\copydetails CppAD::local::forward_unary2_op_dir
|
||||
*/
|
||||
template <class Base>
|
||||
inline void forward_atanh_op_dir(
|
||||
size_t q ,
|
||||
size_t r ,
|
||||
size_t i_z ,
|
||||
size_t i_x ,
|
||||
size_t cap_order ,
|
||||
Base* taylor )
|
||||
{
|
||||
// check assumptions
|
||||
CPPAD_ASSERT_UNKNOWN( NumArg(AtanhOp) == 1 );
|
||||
CPPAD_ASSERT_UNKNOWN( NumRes(AtanhOp) == 2 );
|
||||
CPPAD_ASSERT_UNKNOWN( 0 < q );
|
||||
CPPAD_ASSERT_UNKNOWN( q < cap_order );
|
||||
|
||||
// Taylor coefficients corresponding to argument and result
|
||||
size_t num_taylor_per_var = (cap_order-1) * r + 1;
|
||||
Base* x = taylor + i_x * num_taylor_per_var;
|
||||
Base* z = taylor + i_z * num_taylor_per_var;
|
||||
Base* b = z - num_taylor_per_var; // called y in documentation
|
||||
|
||||
size_t m = (q-1) * r + 1;
|
||||
for(size_t ell = 0; ell < r; ell++)
|
||||
{ b[m+ell] = - Base(2.0) * x[m+ell] * x[0];
|
||||
z[m+ell] = Base(double(q)) * x[m+ell];
|
||||
for(size_t k = 1; k < q; k++)
|
||||
{ b[m+ell] -= x[(k-1)*r+1+ell] * x[(q-k-1)*r+1+ell];
|
||||
z[m+ell] -= Base(double(k)) * z[(k-1)*r+1+ell] * b[(q-k-1)*r+1+ell];
|
||||
}
|
||||
z[m+ell] /= ( Base(double(q)) * b[0] );
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
Zero order forward mode Taylor coefficient for result of op = AtanhOp.
|
||||
|
||||
The C++ source code corresponding to this operation is
|
||||
\verbatim
|
||||
z = atanh(x)
|
||||
\endverbatim
|
||||
The auxillary result is
|
||||
\verbatim
|
||||
y = 1 - x * x
|
||||
\endverbatim
|
||||
The value of y is computed along with the value of z.
|
||||
|
||||
\copydetails CppAD::local::forward_unary2_op_0
|
||||
*/
|
||||
template <class Base>
|
||||
inline void forward_atanh_op_0(
|
||||
size_t i_z ,
|
||||
size_t i_x ,
|
||||
size_t cap_order ,
|
||||
Base* taylor )
|
||||
{
|
||||
// check assumptions
|
||||
CPPAD_ASSERT_UNKNOWN( NumArg(AtanhOp) == 1 );
|
||||
CPPAD_ASSERT_UNKNOWN( NumRes(AtanhOp) == 2 );
|
||||
CPPAD_ASSERT_UNKNOWN( 0 < cap_order );
|
||||
|
||||
// Taylor coefficients corresponding to argument and result
|
||||
Base* x = taylor + i_x * cap_order;
|
||||
Base* z = taylor + i_z * cap_order;
|
||||
Base* b = z - cap_order; // called y in documentation
|
||||
|
||||
z[0] = atanh( x[0] );
|
||||
b[0] = Base(1.0) - x[0] * x[0];
|
||||
}
|
||||
/*!
|
||||
Reverse mode partial derivatives for result of op = AtanhOp.
|
||||
|
||||
The C++ source code corresponding to this operation is
|
||||
\verbatim
|
||||
z = atanh(x)
|
||||
\endverbatim
|
||||
The auxillary result is
|
||||
\verbatim
|
||||
y = 1 - x * x
|
||||
\endverbatim
|
||||
The value of y is computed along with the value of z.
|
||||
|
||||
\copydetails CppAD::local::reverse_unary2_op
|
||||
*/
|
||||
|
||||
template <class Base>
|
||||
inline void reverse_atanh_op(
|
||||
size_t d ,
|
||||
size_t i_z ,
|
||||
size_t i_x ,
|
||||
size_t cap_order ,
|
||||
const Base* taylor ,
|
||||
size_t nc_partial ,
|
||||
Base* partial )
|
||||
{
|
||||
// check assumptions
|
||||
CPPAD_ASSERT_UNKNOWN( NumArg(AtanhOp) == 1 );
|
||||
CPPAD_ASSERT_UNKNOWN( NumRes(AtanhOp) == 2 );
|
||||
CPPAD_ASSERT_UNKNOWN( d < cap_order );
|
||||
CPPAD_ASSERT_UNKNOWN( d < nc_partial );
|
||||
|
||||
// Taylor coefficients and partials corresponding to argument
|
||||
const Base* x = taylor + i_x * cap_order;
|
||||
Base* px = partial + i_x * nc_partial;
|
||||
|
||||
// Taylor coefficients and partials corresponding to first result
|
||||
const Base* z = taylor + i_z * cap_order;
|
||||
Base* pz = partial + i_z * nc_partial;
|
||||
|
||||
// Taylor coefficients and partials corresponding to auxillary result
|
||||
const Base* b = z - cap_order; // called y in documentation
|
||||
Base* pb = pz - nc_partial;
|
||||
|
||||
Base inv_b0 = Base(1.0) / b[0];
|
||||
|
||||
// number of indices to access
|
||||
size_t j = d;
|
||||
size_t k;
|
||||
while(j)
|
||||
{ // scale partials w.r.t z[j] and b[j]
|
||||
pz[j] = azmul(pz[j], inv_b0);
|
||||
pb[j] *= Base(2.0);
|
||||
|
||||
pb[0] -= azmul(pz[j], z[j]);
|
||||
px[j] += pz[j] - azmul(pb[j], x[0]);
|
||||
px[0] -= azmul(pb[j], x[j]);
|
||||
|
||||
// more scaling of partials w.r.t z[j]
|
||||
pz[j] /= Base(double(j));
|
||||
|
||||
for(k = 1; k < j; k++)
|
||||
{ pb[j-k] -= Base(double(k)) * azmul(pz[j], z[k]);
|
||||
pz[k] -= Base(double(k)) * azmul(pz[j], b[j-k]);
|
||||
px[k] -= azmul(pb[j], x[j-k]);
|
||||
}
|
||||
--j;
|
||||
}
|
||||
px[0] += azmul(pz[0], inv_b0) - Base(2.0) * azmul(pb[0], x[0]);
|
||||
}
|
||||
|
||||
} } // END_CPPAD_LOCAL_NAMESPACE
|
||||
# endif
|
||||
# endif
|
||||
@@ -0,0 +1,295 @@
|
||||
# ifndef CPPAD_LOCAL_COLOR_GENERAL_HPP
|
||||
# define CPPAD_LOCAL_COLOR_GENERAL_HPP
|
||||
|
||||
/* --------------------------------------------------------------------------
|
||||
CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-17 Bradley M. Bell
|
||||
|
||||
CppAD is distributed under multiple licenses. This distribution is under
|
||||
the terms of the
|
||||
Eclipse Public License Version 1.0.
|
||||
|
||||
A copy of this license is included in the COPYING file of this distribution.
|
||||
Please visit http://www.coin-or.org/CppAD/ for information on other licenses.
|
||||
-------------------------------------------------------------------------- */
|
||||
|
||||
# include <cppad/configure.hpp>
|
||||
# include <cppad/local/cppad_colpack.hpp>
|
||||
|
||||
namespace CppAD { namespace local { // BEGIN_CPPAD_LOCAL_NAMESPACE
|
||||
/*!
|
||||
\file color_general.hpp
|
||||
Coloring algorithm for a general sparse matrix.
|
||||
*/
|
||||
// --------------------------------------------------------------------------
|
||||
/*!
|
||||
Determine which rows of a general sparse matrix can be computed together;
|
||||
i.e., do not have non-zero entries with the same column index.
|
||||
|
||||
\tparam VectorSize
|
||||
is a simple vector class with elements of type size_t.
|
||||
|
||||
\tparam VectorSet
|
||||
is an unspecified type with the exception that it must support the
|
||||
operations under pattern and the following operations where
|
||||
p is a VectorSet object:
|
||||
\n
|
||||
<code>VectorSet p</code>
|
||||
Constructs a new vector of sets object.
|
||||
\n
|
||||
<code>p.resize(ns, ne)</code>
|
||||
resizes \c p to \c ns sets with elements between zero \c ne.
|
||||
All of the \c ns sets are initially empty.
|
||||
\n
|
||||
<code>p.add_element(s, e)</code>
|
||||
add element \c e to set with index \c s.
|
||||
|
||||
\param pattern [in]
|
||||
Is a representation of the sparsity pattern for the matrix.
|
||||
\n
|
||||
<code>m = pattern.n_set()</code>
|
||||
\n
|
||||
sets \c m to the number of rows in the sparse matrix.
|
||||
All of the row indices are less than this value.
|
||||
\n
|
||||
<code>n = pattern.end()</code>
|
||||
\n
|
||||
sets \c n to the number of columns in the sparse matrix.
|
||||
All of the column indices are less than this value.
|
||||
\n
|
||||
<code>VectorSet::const_iterator itr(pattern, i)</code>
|
||||
constructs an iterator that starts iterating over
|
||||
columns in the i-th row of the sparsity pattern.
|
||||
\n
|
||||
<code>j = *itr</code>
|
||||
Sets j to the next possibly non-zero column.
|
||||
\n
|
||||
<code>++itr</code>
|
||||
Advances to the next possibly non-zero column.
|
||||
|
||||
\param row [in]
|
||||
is a vector specifying which row indices to compute.
|
||||
|
||||
\param col [in]
|
||||
is a vector, with the same size as row,
|
||||
that specifies which column indices to compute.
|
||||
For each valid index k, the index pair
|
||||
<code>(row[k], col[k])</code> must be present in the sparsity pattern.
|
||||
It may be that some entries in the sparsity pattern do not need to be computed;
|
||||
i.e, do not appear in the set of
|
||||
<code>(row[k], col[k])</code> entries.
|
||||
|
||||
\param color [out]
|
||||
is a vector with size m.
|
||||
The input value of its elements does not matter.
|
||||
Upon return, it is a coloring for the rows of the sparse matrix.
|
||||
\n
|
||||
\n
|
||||
If for some i, <code>color[i] == m</code>, then
|
||||
the i-th row does not appear in the vector row.
|
||||
Otherwise, <code>color[i] < m</code>.
|
||||
\n
|
||||
\n
|
||||
Suppose two differen rows, <code>i != r</code> have the same color and
|
||||
column index j is such that both of the pairs
|
||||
<code>(i, j)</code> and <code>(r, j)</code> appear in the sparsity pattern.
|
||||
It follows that neither of these pairs appear in the set of
|
||||
<code>(row[k], col[k])</code> entries.
|
||||
\n
|
||||
\n
|
||||
This routine tries to minimize, with respect to the choice of colors,
|
||||
the maximum, with respct to k, of <code>color[ row[k] ]</code>
|
||||
(not counting the indices k for which row[k] == m).
|
||||
*/
|
||||
template <class VectorSet, class VectorSize>
|
||||
void color_general_cppad(
|
||||
const VectorSet& pattern ,
|
||||
const VectorSize& row ,
|
||||
const VectorSize& col ,
|
||||
CppAD::vector<size_t>& color )
|
||||
{ size_t i, j, k, ell, r;
|
||||
|
||||
size_t K = row.size();
|
||||
size_t m = pattern.n_set();
|
||||
size_t n = pattern.end();
|
||||
|
||||
CPPAD_ASSERT_UNKNOWN( size_t( col.size() ) == K );
|
||||
CPPAD_ASSERT_UNKNOWN( size_t( color.size() ) == m );
|
||||
|
||||
// We define the set of rows, columns, and pairs that appear
|
||||
// by the set ( row[k], col[k] ) for k = 0, ... , K-1.
|
||||
|
||||
// initialize rows that appear
|
||||
CppAD::vector<bool> row_appear(m);
|
||||
for(i = 0; i < m; i++)
|
||||
row_appear[i] = false;
|
||||
|
||||
// rows and columns that appear
|
||||
VectorSet c2r_appear, r2c_appear;
|
||||
c2r_appear.resize(n, m);
|
||||
r2c_appear.resize(m, n);
|
||||
for(k = 0; k < K; k++)
|
||||
{ CPPAD_ASSERT_UNKNOWN( pattern.is_element(row[k], col[k]) );
|
||||
row_appear[ row[k] ] = true;
|
||||
c2r_appear.add_element(col[k], row[k]);
|
||||
r2c_appear.add_element(row[k], col[k]);
|
||||
}
|
||||
|
||||
// for each column, which rows are non-zero and do not appear
|
||||
VectorSet not_appear;
|
||||
not_appear.resize(n, m);
|
||||
for(i = 0; i < m; i++)
|
||||
{ typename VectorSet::const_iterator pattern_itr(pattern, i);
|
||||
j = *pattern_itr;
|
||||
while( j != pattern.end() )
|
||||
{ if( ! c2r_appear.is_element(j , i) )
|
||||
not_appear.add_element(j, i);
|
||||
j = *(++pattern_itr);
|
||||
}
|
||||
}
|
||||
|
||||
// initial coloring
|
||||
color.resize(m);
|
||||
ell = 0;
|
||||
for(i = 0; i < m; i++)
|
||||
{ if( row_appear[i] )
|
||||
color[i] = ell++;
|
||||
else color[i] = m;
|
||||
}
|
||||
/*
|
||||
See GreedyPartialD2Coloring Algorithm Section 3.6.2 of
|
||||
Graph Coloring in Optimization Revisited by
|
||||
Assefaw Gebremedhin, Fredrik Maane, Alex Pothen
|
||||
|
||||
The algorithm above was modified (by Brad Bell) to take advantage of the
|
||||
fact that only the entries (subset of the sparsity pattern) specified by
|
||||
row and col need to be computed.
|
||||
*/
|
||||
CppAD::vector<bool> forbidden(m);
|
||||
for(i = 1; i < m; i++) // for each row that appears
|
||||
if( color[i] < m )
|
||||
{
|
||||
// initial all colors as ok for this row
|
||||
// (value of forbidden for ell > initial color[i] does not matter)
|
||||
for(ell = 0; ell <= color[i]; ell++)
|
||||
forbidden[ell] = false;
|
||||
|
||||
// -----------------------------------------------------
|
||||
// Forbid colors for which this row would destroy results:
|
||||
//
|
||||
// for each column that is non-zero for this row
|
||||
typename VectorSet::const_iterator pattern_itr(pattern, i);
|
||||
j = *pattern_itr;
|
||||
while( j != pattern.end() )
|
||||
{ // for each row that appears with this column
|
||||
typename VectorSet::const_iterator c2r_itr(c2r_appear, j);
|
||||
r = *c2r_itr;
|
||||
while( r != c2r_appear.end() )
|
||||
{ // if this is not the same row, forbid its color
|
||||
if( (r < i) & (color[r] < m) )
|
||||
forbidden[ color[r] ] = true;
|
||||
r = *(++c2r_itr);
|
||||
}
|
||||
j = *(++pattern_itr);
|
||||
}
|
||||
|
||||
|
||||
// -----------------------------------------------------
|
||||
// Forbid colors that destroy results needed for this row.
|
||||
//
|
||||
// for each column that appears with this row
|
||||
typename VectorSet::const_iterator r2c_itr(r2c_appear, i);
|
||||
j = *r2c_itr;
|
||||
while( j != r2c_appear.end() )
|
||||
{ // For each row that is non-zero for this column
|
||||
// (the appear rows have already been checked above).
|
||||
typename VectorSet::const_iterator not_itr(not_appear, j);
|
||||
r = *not_itr;
|
||||
while( r != not_appear.end() )
|
||||
{ // if this is not the same row, forbid its color
|
||||
if( (r < i) & (color[r] < m) )
|
||||
forbidden[ color[r] ] = true;
|
||||
r = *(++not_itr);
|
||||
}
|
||||
j = *(++r2c_itr);
|
||||
}
|
||||
|
||||
// pick the color with smallest index
|
||||
ell = 0;
|
||||
while( forbidden[ell] )
|
||||
{ ell++;
|
||||
CPPAD_ASSERT_UNKNOWN( ell <= color[i] );
|
||||
}
|
||||
color[i] = ell;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
# if CPPAD_HAS_COLPACK
|
||||
/*!
|
||||
Colpack version of determining which rows of a sparse matrix
|
||||
can be computed together.
|
||||
|
||||
\copydetails color_general
|
||||
*/
|
||||
template <class VectorSet, class VectorSize>
|
||||
void color_general_colpack(
|
||||
const VectorSet& pattern ,
|
||||
const VectorSize& row ,
|
||||
const VectorSize& col ,
|
||||
CppAD::vector<size_t>& color )
|
||||
{ size_t i, j, k;
|
||||
size_t m = pattern.n_set();
|
||||
size_t n = pattern.end();
|
||||
|
||||
// Determine number of non-zero entries in each row
|
||||
CppAD::vector<size_t> n_nonzero(m);
|
||||
size_t n_nonzero_total = 0;
|
||||
for(i = 0; i < m; i++)
|
||||
{ n_nonzero[i] = 0;
|
||||
typename VectorSet::const_iterator pattern_itr(pattern, i);
|
||||
j = *pattern_itr;
|
||||
while( j != pattern.end() )
|
||||
{ n_nonzero[i]++;
|
||||
j = *(++pattern_itr);
|
||||
}
|
||||
n_nonzero_total += n_nonzero[i];
|
||||
}
|
||||
|
||||
// Allocate memory and fill in Adolc sparsity pattern
|
||||
CppAD::vector<unsigned int*> adolc_pattern(m);
|
||||
CppAD::vector<unsigned int> adolc_memory(m + n_nonzero_total);
|
||||
size_t i_memory = 0;
|
||||
for(i = 0; i < m; i++)
|
||||
{ adolc_pattern[i] = adolc_memory.data() + i_memory;
|
||||
CPPAD_ASSERT_KNOWN(
|
||||
std::numeric_limits<unsigned int>::max() >= n_nonzero[i],
|
||||
"Matrix is too large for colpack"
|
||||
);
|
||||
adolc_pattern[i][0] = static_cast<unsigned int>( n_nonzero[i] );
|
||||
typename VectorSet::const_iterator pattern_itr(pattern, i);
|
||||
j = *pattern_itr;
|
||||
k = 1;
|
||||
while(j != pattern.end() )
|
||||
{
|
||||
CPPAD_ASSERT_KNOWN(
|
||||
std::numeric_limits<unsigned int>::max() >= j,
|
||||
"Matrix is too large for colpack"
|
||||
);
|
||||
adolc_pattern[i][k++] = static_cast<unsigned int>( j );
|
||||
j = *(++pattern_itr);
|
||||
}
|
||||
CPPAD_ASSERT_UNKNOWN( k == 1 + n_nonzero[i] );
|
||||
i_memory += k;
|
||||
}
|
||||
CPPAD_ASSERT_UNKNOWN( i_memory == m + n_nonzero_total );
|
||||
|
||||
// Must use an external routine for this part of the calculation because
|
||||
// ColPack/ColPackHeaders.h has as 'using namespace std' at global level.
|
||||
cppad_colpack_general(color, m, n, adolc_pattern);
|
||||
|
||||
return;
|
||||
}
|
||||
# endif // CPPAD_HAS_COLPACK
|
||||
|
||||
} } // END_CPPAD_LOCAL_NAMESPACE
|
||||
# endif
|
||||
@@ -0,0 +1,344 @@
|
||||
# ifndef CPPAD_LOCAL_COLOR_SYMMETRIC_HPP
|
||||
# define CPPAD_LOCAL_COLOR_SYMMETRIC_HPP
|
||||
|
||||
# include <cppad/configure.hpp>
|
||||
# include <cppad/local/cppad_colpack.hpp>
|
||||
|
||||
/* --------------------------------------------------------------------------
|
||||
CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-17 Bradley M. Bell
|
||||
|
||||
CppAD is distributed under multiple licenses. This distribution is under
|
||||
the terms of the
|
||||
Eclipse Public License Version 1.0.
|
||||
|
||||
A copy of this license is included in the COPYING file of this distribution.
|
||||
Please visit http://www.coin-or.org/CppAD/ for information on other licenses.
|
||||
-------------------------------------------------------------------------- */
|
||||
|
||||
namespace CppAD { namespace local { // BEGIN_CPPAD_LOCAL_NAMESPACE
|
||||
/*!
|
||||
\file color_symmetric.hpp
|
||||
Coloring algorithm for a symmetric sparse matrix.
|
||||
*/
|
||||
// --------------------------------------------------------------------------
|
||||
/*!
|
||||
CppAD algorithm for determining which rows of a symmetric sparse matrix can be
|
||||
computed together.
|
||||
|
||||
\tparam VectorSize
|
||||
is a simple vector class with elements of type size_t.
|
||||
|
||||
\tparam VectorSet
|
||||
is an unspecified type with the exception that it must support the
|
||||
operations under pattern and the following operations where
|
||||
p is a VectorSet object:
|
||||
\n
|
||||
<code>VectorSet p</code>
|
||||
Constructs a new vector of sets object.
|
||||
\n
|
||||
<code>p.resize(ns, ne)</code>
|
||||
resizes \c p to ns sets with elements between zero and \c ne.
|
||||
All of the sets are initially empty.
|
||||
\n
|
||||
<code>p.add_element(s, e)</code>
|
||||
add element \c e to set with index \c s.
|
||||
|
||||
\param pattern [in]
|
||||
Is a representation of the sparsity pattern for the matrix.
|
||||
\n
|
||||
<code>m = pattern.n_set()</code>
|
||||
\n
|
||||
sets m to the number of rows (and columns) in the sparse matrix.
|
||||
All of the row indices are less than this value.
|
||||
\n
|
||||
<code>n = pattern.end()</code>
|
||||
\n
|
||||
sets n to the number of columns in the sparse matrix
|
||||
(which must be equal to the number of rows).
|
||||
All of the column indices are less than this value.
|
||||
\n
|
||||
<code>VectorSet::const_iterator itr(pattern, i)</code>
|
||||
constructs an iterator that starts iterating over
|
||||
columns in the i-th row of the sparsity pattern.
|
||||
\n
|
||||
<code>j = *itr</code>
|
||||
Sets j to the next possibly non-zero column.
|
||||
\n
|
||||
<code>++itr</code>
|
||||
Advances to the next possibly non-zero column.
|
||||
\n
|
||||
|
||||
\param row [in/out]
|
||||
is a vector specifying which row indices to compute.
|
||||
|
||||
\param col [in/out]
|
||||
is a vector, with the same size as row,
|
||||
that specifies which column indices to compute.
|
||||
\n
|
||||
\n
|
||||
Input:
|
||||
For each valid index \c k, the index pair
|
||||
<code>(row[k], col[k])</code> must be present in the sparsity pattern.
|
||||
It may be that some entries in the sparsity pattern do not need to be computed;
|
||||
i.e, do not appear in the set of
|
||||
<code>(row[k], col[k])</code> entries.
|
||||
\n
|
||||
\n
|
||||
Output:
|
||||
On output, some of row and column indices may have been swapped
|
||||
\code
|
||||
std::swap( row[k], col[k] )
|
||||
\endcode
|
||||
So the the the color for row[k] can be used to compute entry
|
||||
(row[k], col[k]).
|
||||
|
||||
\param color [out]
|
||||
is a vector with size m.
|
||||
The input value of its elements does not matter.
|
||||
Upon return, it is a coloring for the rows of the sparse matrix.
|
||||
Note that if color[i] == m, then there is no index k for which
|
||||
row[k] == i (for the return value of row).
|
||||
\n
|
||||
\n
|
||||
Fix any (i, j) in the sparsity pattern.
|
||||
Suppose that there is a row index i1 with
|
||||
i1 != i, color[i1] == color[i] and (i1, j) is in the sparsity pattern.
|
||||
If follows that for all j1 with
|
||||
j1 != j and color[j1] == color[j],
|
||||
(j1, i ) is not in the sparsity pattern.
|
||||
\n
|
||||
\n
|
||||
This routine tries to minimize, with respect to the choice of colors,
|
||||
the maximum, with respect to k, of <code>color[ row[k] ]</code>.
|
||||
*/
|
||||
template <class VectorSet>
|
||||
void color_symmetric_cppad(
|
||||
const VectorSet& pattern ,
|
||||
CppAD::vector<size_t>& row ,
|
||||
CppAD::vector<size_t>& col ,
|
||||
CppAD::vector<size_t>& color )
|
||||
{ size_t o1, o2, i1, i2, j1, j2, k1, c1, c2;
|
||||
|
||||
size_t K = row.size();
|
||||
size_t m = pattern.n_set();
|
||||
CPPAD_ASSERT_UNKNOWN( m == pattern.end() );
|
||||
CPPAD_ASSERT_UNKNOWN( color.size() == m );
|
||||
CPPAD_ASSERT_UNKNOWN( col.size() == K );
|
||||
|
||||
// row, column pairs that appear in ( row[k], col[k] )
|
||||
CppAD::vector< std::set<size_t> > pair_needed(m);
|
||||
std::set<size_t>::iterator itr1, itr2;
|
||||
for(k1 = 0; k1 < K; k1++)
|
||||
{ CPPAD_ASSERT_UNKNOWN( pattern.is_element(row[k1], col[k1]) );
|
||||
pair_needed[ row[k1] ].insert( col[k1] );
|
||||
pair_needed[ col[k1] ].insert( row[k1] );
|
||||
}
|
||||
|
||||
// order the rows decending by number of pairs needed
|
||||
CppAD::vector<size_t> key(m), order2row(m);
|
||||
for(i1 = 0; i1 < m; i1++)
|
||||
{ CPPAD_ASSERT_UNKNOWN( pair_needed[i1].size() <= m );
|
||||
key[i1] = m - pair_needed[i1].size();
|
||||
}
|
||||
CppAD::index_sort(key, order2row);
|
||||
|
||||
// mapping from order index to row index
|
||||
CppAD::vector<size_t> row2order(m);
|
||||
for(o1 = 0; o1 < m; o1++)
|
||||
row2order[ order2row[o1] ] = o1;
|
||||
|
||||
// initial coloring
|
||||
color.resize(m);
|
||||
c1 = 0;
|
||||
for(o1 = 0; o1 < m; o1++)
|
||||
{ i1 = order2row[o1];
|
||||
if( pair_needed[i1].empty() )
|
||||
color[i1] = m;
|
||||
else
|
||||
color[i1] = c1++;
|
||||
}
|
||||
|
||||
// which colors are forbidden for this row
|
||||
CppAD::vector<bool> forbidden(m);
|
||||
|
||||
// must start with row zero so that we remove results computed for it
|
||||
for(o1 = 0; o1 < m; o1++) // for each row that appears (in order)
|
||||
if( color[ order2row[o1] ] < m )
|
||||
{ i1 = order2row[o1];
|
||||
c1 = color[i1];
|
||||
|
||||
// initial all colors as ok for this row
|
||||
// (value of forbidden for c > c1 does not matter)
|
||||
for(c2 = 0; c2 <= c1; c2++)
|
||||
forbidden[c2] = false;
|
||||
|
||||
// -----------------------------------------------------
|
||||
// Forbid grouping with rows that would destroy results that are
|
||||
// needed for this row.
|
||||
itr1 = pair_needed[i1].begin();
|
||||
while( itr1 != pair_needed[i1].end() )
|
||||
{ // entry (i1, j1) is needed for this row
|
||||
j1 = *itr1;
|
||||
|
||||
// Forbid rows i2 != i1 that have non-zero sparsity at (i2, j1).
|
||||
// Note that this is the same as non-zero sparsity at (j1, i2)
|
||||
typename VectorSet::const_iterator pattern_itr(pattern, j1);
|
||||
i2 = *pattern_itr;
|
||||
while( i2 != pattern.end() )
|
||||
{ c2 = color[i2];
|
||||
if( c2 < c1 )
|
||||
forbidden[c2] = true;
|
||||
i2 = *(++pattern_itr);
|
||||
}
|
||||
itr1++;
|
||||
}
|
||||
// -----------------------------------------------------
|
||||
// Forbid grouping with rows that this row would destroy results for
|
||||
for(o2 = 0; o2 < o1; o2++)
|
||||
{ i2 = order2row[o2];
|
||||
c2 = color[i2];
|
||||
itr2 = pair_needed[i2].begin();
|
||||
while( itr2 != pair_needed[i2].end() )
|
||||
{ j2 = *itr2;
|
||||
// row i2 needs pair (i2, j2).
|
||||
// Forbid grouping with i1 if (i1, j2) has non-zero sparsity
|
||||
if( pattern.is_element(i1, j2) )
|
||||
forbidden[c2] = true;
|
||||
itr2++;
|
||||
}
|
||||
}
|
||||
|
||||
// pick the color with smallest index
|
||||
c2 = 0;
|
||||
while( forbidden[c2] )
|
||||
{ c2++;
|
||||
CPPAD_ASSERT_UNKNOWN( c2 <= c1 );
|
||||
}
|
||||
color[i1] = c2;
|
||||
|
||||
// no longer need results that are computed by this row
|
||||
itr1 = pair_needed[i1].begin();
|
||||
while( itr1 != pair_needed[i1].end() )
|
||||
{ j1 = *itr1;
|
||||
if( row2order[j1] > o1 )
|
||||
{ itr2 = pair_needed[j1].find(i1);
|
||||
if( itr2 != pair_needed[j1].end() )
|
||||
{ pair_needed[j1].erase(itr2);
|
||||
if( pair_needed[j1].empty() )
|
||||
color[j1] = m;
|
||||
}
|
||||
}
|
||||
itr1++;
|
||||
}
|
||||
}
|
||||
|
||||
// determine which sparsity entries need to be reflected
|
||||
for(k1 = 0; k1 < row.size(); k1++)
|
||||
{ i1 = row[k1];
|
||||
j1 = col[k1];
|
||||
itr1 = pair_needed[i1].find(j1);
|
||||
if( itr1 == pair_needed[i1].end() )
|
||||
{ row[k1] = j1;
|
||||
col[k1] = i1;
|
||||
# ifndef NDEBUG
|
||||
itr1 = pair_needed[j1].find(i1);
|
||||
CPPAD_ASSERT_UNKNOWN( itr1 != pair_needed[j1].end() );
|
||||
# endif
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
/*!
|
||||
Colpack algorithm for determining which rows of a symmetric sparse matrix
|
||||
can be computed together.
|
||||
|
||||
\copydetails CppAD::local::color_symmetric_cppad
|
||||
*/
|
||||
template <class VectorSet>
|
||||
void color_symmetric_colpack(
|
||||
const VectorSet& pattern ,
|
||||
CppAD::vector<size_t>& row ,
|
||||
CppAD::vector<size_t>& col ,
|
||||
CppAD::vector<size_t>& color )
|
||||
{
|
||||
# if ! CPPAD_HAS_COLPACK
|
||||
CPPAD_ASSERT_UNKNOWN(false);
|
||||
return;
|
||||
# else
|
||||
size_t i, j, k;
|
||||
size_t m = pattern.n_set();
|
||||
CPPAD_ASSERT_UNKNOWN( m == pattern.end() );
|
||||
CPPAD_ASSERT_UNKNOWN( row.size() == col.size() );
|
||||
|
||||
// Determine number of non-zero entries in each row
|
||||
CppAD::vector<size_t> n_nonzero(m);
|
||||
size_t n_nonzero_total = 0;
|
||||
for(i = 0; i < m; i++)
|
||||
{ n_nonzero[i] = 0;
|
||||
typename VectorSet::const_iterator pattern_itr(pattern, i);
|
||||
j = *pattern_itr;
|
||||
while( j != pattern.end() )
|
||||
{ n_nonzero[i]++;
|
||||
j = *(++pattern_itr);
|
||||
}
|
||||
n_nonzero_total += n_nonzero[i];
|
||||
}
|
||||
|
||||
// Allocate memory and fill in Adolc sparsity pattern
|
||||
CppAD::vector<unsigned int*> adolc_pattern(m);
|
||||
CppAD::vector<unsigned int> adolc_memory(m + n_nonzero_total);
|
||||
size_t i_memory = 0;
|
||||
for(i = 0; i < m; i++)
|
||||
{ adolc_pattern[i] = adolc_memory.data() + i_memory;
|
||||
CPPAD_ASSERT_KNOWN(
|
||||
std::numeric_limits<unsigned int>::max() >= n_nonzero[i],
|
||||
"Matrix is too large for colpack"
|
||||
);
|
||||
adolc_pattern[i][0] = static_cast<unsigned int>( n_nonzero[i] );
|
||||
typename VectorSet::const_iterator pattern_itr(pattern, i);
|
||||
j = *pattern_itr;
|
||||
k = 1;
|
||||
while(j != pattern.end() )
|
||||
{
|
||||
CPPAD_ASSERT_KNOWN(
|
||||
std::numeric_limits<unsigned int>::max() >= j,
|
||||
"Matrix is too large for colpack"
|
||||
);
|
||||
adolc_pattern[i][k++] = static_cast<unsigned int>( j );
|
||||
j = *(++pattern_itr);
|
||||
}
|
||||
CPPAD_ASSERT_UNKNOWN( k == 1 + n_nonzero[i] );
|
||||
i_memory += k;
|
||||
}
|
||||
CPPAD_ASSERT_UNKNOWN( i_memory == m + n_nonzero_total );
|
||||
|
||||
// Must use an external routine for this part of the calculation because
|
||||
// ColPack/ColPackHeaders.h has as 'using namespace std' at global level.
|
||||
cppad_colpack_symmetric(color, m, adolc_pattern);
|
||||
|
||||
// determine which sparsity entries need to be reflected
|
||||
size_t i1, i2, j1, j2, k1, k2;
|
||||
for(k1 = 0; k1 < row.size(); k1++)
|
||||
{ i1 = row[k1];
|
||||
j1 = col[k1];
|
||||
bool reflect = false;
|
||||
for(i2 = 0; i2 < m; i2++) if( (i1 != i2) & (color[i1]==color[i2]) )
|
||||
{ for(k2 = 1; k2 <= adolc_pattern[i2][0]; k2++)
|
||||
{ j2 = adolc_pattern[i2][k2];
|
||||
reflect |= (j1 == j2);
|
||||
}
|
||||
}
|
||||
if( reflect )
|
||||
{ row[k1] = j1;
|
||||
col[k1] = i1;
|
||||
}
|
||||
}
|
||||
return;
|
||||
# endif // CPPAD_HAS_COLPACK
|
||||
}
|
||||
|
||||
} } // END_CPPAD_LOCAL_NAMESPACE
|
||||
|
||||
# endif
|
||||
+305
@@ -0,0 +1,305 @@
|
||||
// $Id: comp_op.hpp 3865 2017-01-19 01:57:55Z bradbell $
|
||||
# ifndef CPPAD_LOCAL_COMP_OP_HPP
|
||||
# define CPPAD_LOCAL_COMP_OP_HPP
|
||||
|
||||
/* --------------------------------------------------------------------------
|
||||
CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-17 Bradley M. Bell
|
||||
|
||||
CppAD is distributed under multiple licenses. This distribution is under
|
||||
the terms of the
|
||||
Eclipse Public License Version 1.0.
|
||||
|
||||
A copy of this license is included in the COPYING file of this distribution.
|
||||
Please visit http://www.coin-or.org/CppAD/ for information on other licenses.
|
||||
-------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
namespace CppAD { namespace local { // BEGIN_CPPAD_LOCAL_NAMESPACE
|
||||
/*!
|
||||
\file comp_op.hpp
|
||||
Zero order forward mode check how many comparisons changed.
|
||||
*/
|
||||
|
||||
// -------------------------------- <= -----------------------------------
|
||||
/*!
|
||||
Zero order forward mode comparison check that left <= right
|
||||
|
||||
\param count
|
||||
It the condition is not true, ths counter is incremented by one.
|
||||
|
||||
\param arg
|
||||
parameter[ arg[0] ] is the left operand and
|
||||
taylor[ arg[1] * cap_order + 0 ] is the zero order Taylor coefficient
|
||||
for the right operand.
|
||||
|
||||
\param parameter
|
||||
vector of parameter values.
|
||||
|
||||
\param cap_order
|
||||
number of Taylor coefficients allocated for each variable
|
||||
|
||||
\param taylor
|
||||
vector of taylor coefficients.
|
||||
*/
|
||||
template <class Base>
|
||||
inline void forward_lepv_op_0(
|
||||
size_t& count ,
|
||||
const addr_t* arg ,
|
||||
const Base* parameter ,
|
||||
size_t cap_order ,
|
||||
Base* taylor )
|
||||
{
|
||||
// check assumptions
|
||||
CPPAD_ASSERT_UNKNOWN( NumArg(LepvOp) == 2 );
|
||||
CPPAD_ASSERT_UNKNOWN( NumRes(LepvOp) == 0 );
|
||||
|
||||
// Taylor coefficients corresponding to arguments and result
|
||||
Base x = parameter[ arg[0] ];
|
||||
Base* y = taylor + arg[1] * cap_order;
|
||||
|
||||
count += GreaterThanZero(x - y[0]);
|
||||
}
|
||||
/*!
|
||||
Zero order forward mode comparison check that left <= right
|
||||
|
||||
\param count
|
||||
It the condition is not true, ths counter is incremented by one.
|
||||
|
||||
\param arg
|
||||
taylor[ arg[0] * cap_order + 0 ] is the zero order Taylor coefficient
|
||||
for the left operand and parameter[ arg[1] ] is the right operand
|
||||
|
||||
\param parameter
|
||||
vector of parameter values.
|
||||
|
||||
\param cap_order
|
||||
number of Taylor coefficients allocated for each variable
|
||||
|
||||
\param taylor
|
||||
vector of taylor coefficients.
|
||||
*/
|
||||
template <class Base>
|
||||
inline void forward_levp_op_0(
|
||||
size_t& count ,
|
||||
const addr_t* arg ,
|
||||
const Base* parameter ,
|
||||
size_t cap_order ,
|
||||
Base* taylor )
|
||||
{
|
||||
// check assumptions
|
||||
CPPAD_ASSERT_UNKNOWN( NumArg(LevpOp) == 2 );
|
||||
CPPAD_ASSERT_UNKNOWN( NumRes(LevpOp) == 0 );
|
||||
|
||||
// Taylor coefficients corresponding to arguments and result
|
||||
Base* x = taylor + arg[0] * cap_order;
|
||||
Base y = parameter[ arg[1] ];
|
||||
|
||||
count += GreaterThanZero(x[0] - y);
|
||||
}
|
||||
/*!
|
||||
Zero order forward mode comparison check that left <= right
|
||||
|
||||
\param count
|
||||
It the condition is not true, ths counter is incremented by one.
|
||||
|
||||
\param arg
|
||||
taylor[ arg[0] * cap_order + 0 ] is the zero order Taylor coefficient
|
||||
for the left operand and
|
||||
taylor[ arg[1] * cap_order + 0 ] is the zero order Taylor coefficient
|
||||
for the right operand.
|
||||
|
||||
\param parameter
|
||||
vector of parameter values.
|
||||
|
||||
\param cap_order
|
||||
number of Taylor coefficients allocated for each variable
|
||||
|
||||
\param taylor
|
||||
vector of taylor coefficients.
|
||||
*/
|
||||
template <class Base>
|
||||
inline void forward_levv_op_0(
|
||||
size_t& count ,
|
||||
const addr_t* arg ,
|
||||
const Base* parameter ,
|
||||
size_t cap_order ,
|
||||
Base* taylor )
|
||||
{
|
||||
// check assumptions
|
||||
CPPAD_ASSERT_UNKNOWN( NumArg(LevvOp) == 2 );
|
||||
CPPAD_ASSERT_UNKNOWN( NumRes(LevvOp) == 0 );
|
||||
|
||||
// Taylor coefficients corresponding to arguments and result
|
||||
Base* x = taylor + arg[0] * cap_order;
|
||||
Base* y = taylor + arg[1] * cap_order;
|
||||
|
||||
count += GreaterThanZero(x[0] - y[0]);
|
||||
}
|
||||
// ------------------------------- < -------------------------------------
|
||||
/*!
|
||||
Zero order forward mode comparison check that left < right
|
||||
|
||||
\copydetails CppAD::local::forward_lepv_op_0
|
||||
*/
|
||||
template <class Base>
|
||||
inline void forward_ltpv_op_0(
|
||||
size_t& count ,
|
||||
const addr_t* arg ,
|
||||
const Base* parameter ,
|
||||
size_t cap_order ,
|
||||
Base* taylor )
|
||||
{
|
||||
// check assumptions
|
||||
CPPAD_ASSERT_UNKNOWN( NumArg(LtpvOp) == 2 );
|
||||
CPPAD_ASSERT_UNKNOWN( NumRes(LtpvOp) == 0 );
|
||||
|
||||
// Taylor coefficients corresponding to arguments and result
|
||||
Base x = parameter[ arg[0] ];
|
||||
Base* y = taylor + arg[1] * cap_order;
|
||||
|
||||
count += GreaterThanOrZero(x - y[0]);
|
||||
}
|
||||
/*!
|
||||
Zero order forward mode comparison check that left < right
|
||||
|
||||
\copydetails CppAD::local::forward_levp_op_0
|
||||
*/
|
||||
template <class Base>
|
||||
inline void forward_ltvp_op_0(
|
||||
size_t& count ,
|
||||
const addr_t* arg ,
|
||||
const Base* parameter ,
|
||||
size_t cap_order ,
|
||||
Base* taylor )
|
||||
{
|
||||
// check assumptions
|
||||
CPPAD_ASSERT_UNKNOWN( NumArg(LtvpOp) == 2 );
|
||||
CPPAD_ASSERT_UNKNOWN( NumRes(LtvpOp) == 0 );
|
||||
|
||||
// Taylor coefficients corresponding to arguments and result
|
||||
Base* x = taylor + arg[0] * cap_order;
|
||||
Base y = parameter[ arg[1] ];
|
||||
|
||||
count += GreaterThanOrZero(x[0] - y);
|
||||
}
|
||||
/*!
|
||||
Zero order forward mode comparison check that left < right
|
||||
|
||||
\copydetails CppAD::local::forward_levv_op_0
|
||||
*/
|
||||
template <class Base>
|
||||
inline void forward_ltvv_op_0(
|
||||
size_t& count ,
|
||||
const addr_t* arg ,
|
||||
const Base* parameter ,
|
||||
size_t cap_order ,
|
||||
Base* taylor )
|
||||
{
|
||||
// check assumptions
|
||||
CPPAD_ASSERT_UNKNOWN( NumArg(LtvvOp) == 2 );
|
||||
CPPAD_ASSERT_UNKNOWN( NumRes(LtvvOp) == 0 );
|
||||
|
||||
// Taylor coefficients corresponding to arguments and result
|
||||
Base* x = taylor + arg[0] * cap_order;
|
||||
Base* y = taylor + arg[1] * cap_order;
|
||||
|
||||
count += GreaterThanOrZero(x[0] - y[0]);
|
||||
}
|
||||
// ------------------------------ == -------------------------------------
|
||||
/*!
|
||||
Zero order forward mode comparison check that left == right
|
||||
|
||||
\copydetails CppAD::local::forward_lepv_op_0
|
||||
*/
|
||||
template <class Base>
|
||||
inline void forward_eqpv_op_0(
|
||||
size_t& count ,
|
||||
const addr_t* arg ,
|
||||
const Base* parameter ,
|
||||
size_t cap_order ,
|
||||
Base* taylor )
|
||||
{
|
||||
// check assumptions
|
||||
CPPAD_ASSERT_UNKNOWN( NumArg(EqpvOp) == 2 );
|
||||
CPPAD_ASSERT_UNKNOWN( NumRes(EqpvOp) == 0 );
|
||||
|
||||
// Taylor coefficients corresponding to arguments and result
|
||||
Base x = parameter[ arg[0] ];
|
||||
Base* y = taylor + arg[1] * cap_order;
|
||||
|
||||
count += (x != y[0]);
|
||||
}
|
||||
/*!
|
||||
Zero order forward mode comparison check that left == right
|
||||
|
||||
\copydetails CppAD::local::forward_levv_op_0
|
||||
*/
|
||||
template <class Base>
|
||||
inline void forward_eqvv_op_0(
|
||||
size_t& count ,
|
||||
const addr_t* arg ,
|
||||
const Base* parameter ,
|
||||
size_t cap_order ,
|
||||
Base* taylor )
|
||||
{
|
||||
// check assumptions
|
||||
CPPAD_ASSERT_UNKNOWN( NumArg(EqvvOp) == 2 );
|
||||
CPPAD_ASSERT_UNKNOWN( NumRes(EqvvOp) == 0 );
|
||||
|
||||
// Taylor coefficients corresponding to arguments and result
|
||||
Base* x = taylor + arg[0] * cap_order;
|
||||
Base* y = taylor + arg[1] * cap_order;
|
||||
|
||||
count += (x[0] != y[0]);
|
||||
}
|
||||
// -------------------------------- != -----------------------------------
|
||||
/*!
|
||||
Zero order forward mode comparison check that left != right
|
||||
|
||||
\copydetails CppAD::local::forward_lepv_op_0
|
||||
*/
|
||||
template <class Base>
|
||||
inline void forward_nepv_op_0(
|
||||
size_t& count ,
|
||||
const addr_t* arg ,
|
||||
const Base* parameter ,
|
||||
size_t cap_order ,
|
||||
Base* taylor )
|
||||
{
|
||||
// check assumptions
|
||||
CPPAD_ASSERT_UNKNOWN( NumArg(NepvOp) == 2 );
|
||||
CPPAD_ASSERT_UNKNOWN( NumRes(NepvOp) == 0 );
|
||||
|
||||
// Taylor coefficients corresponding to arguments and result
|
||||
Base x = parameter[ arg[0] ];
|
||||
Base* y = taylor + arg[1] * cap_order;
|
||||
|
||||
count += (x == y[0]);
|
||||
}
|
||||
/*!
|
||||
Zero order forward mode comparison check that left != right
|
||||
|
||||
\copydetails CppAD::local::forward_levv_op_0
|
||||
*/
|
||||
template <class Base>
|
||||
inline void forward_nevv_op_0(
|
||||
size_t& count ,
|
||||
const addr_t* arg ,
|
||||
const Base* parameter ,
|
||||
size_t cap_order ,
|
||||
Base* taylor )
|
||||
{
|
||||
// check assumptions
|
||||
CPPAD_ASSERT_UNKNOWN( NumArg(NevvOp) == 2 );
|
||||
CPPAD_ASSERT_UNKNOWN( NumRes(NevvOp) == 0 );
|
||||
|
||||
// Taylor coefficients corresponding to arguments and result
|
||||
Base* x = taylor + arg[0] * cap_order;
|
||||
Base* y = taylor + arg[1] * cap_order;
|
||||
|
||||
count += (x[0] == y[0]);
|
||||
}
|
||||
|
||||
|
||||
} } // END_CPPAD_LOCAL_NAMESPACE
|
||||
# endif
|
||||
+1313
File diff suppressed because it is too large
Load Diff
+238
@@ -0,0 +1,238 @@
|
||||
# ifndef CPPAD_LOCAL_COS_OP_HPP
|
||||
# define CPPAD_LOCAL_COS_OP_HPP
|
||||
|
||||
/* --------------------------------------------------------------------------
|
||||
CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-17 Bradley M. Bell
|
||||
|
||||
CppAD is distributed under multiple licenses. This distribution is under
|
||||
the terms of the
|
||||
Eclipse Public License Version 1.0.
|
||||
|
||||
A copy of this license is included in the COPYING file of this distribution.
|
||||
Please visit http://www.coin-or.org/CppAD/ for information on other licenses.
|
||||
-------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
namespace CppAD { namespace local { // BEGIN_CPPAD_LOCAL_NAMESPACE
|
||||
/*!
|
||||
\file cos_op.hpp
|
||||
Forward and reverse mode calculations for z = cos(x).
|
||||
*/
|
||||
|
||||
/*!
|
||||
Compute forward mode Taylor coefficient for result of op = CosOp.
|
||||
|
||||
The C++ source code corresponding to this operation is
|
||||
\verbatim
|
||||
z = cos(x)
|
||||
\endverbatim
|
||||
The auxillary result is
|
||||
\verbatim
|
||||
y = sin(x)
|
||||
\endverbatim
|
||||
The value of y, and its derivatives, are computed along with the value
|
||||
and derivatives of z.
|
||||
|
||||
\copydetails CppAD::local::forward_unary2_op
|
||||
*/
|
||||
template <class Base>
|
||||
inline void forward_cos_op(
|
||||
size_t p ,
|
||||
size_t q ,
|
||||
size_t i_z ,
|
||||
size_t i_x ,
|
||||
size_t cap_order ,
|
||||
Base* taylor )
|
||||
{
|
||||
// check assumptions
|
||||
CPPAD_ASSERT_UNKNOWN( NumArg(CosOp) == 1 );
|
||||
CPPAD_ASSERT_UNKNOWN( NumRes(CosOp) == 2 );
|
||||
CPPAD_ASSERT_UNKNOWN( q < cap_order );
|
||||
CPPAD_ASSERT_UNKNOWN( p <= q );
|
||||
|
||||
// Taylor coefficients corresponding to argument and result
|
||||
Base* x = taylor + i_x * cap_order;
|
||||
Base* c = taylor + i_z * cap_order;
|
||||
Base* s = c - cap_order;
|
||||
|
||||
|
||||
// rest of this routine is identical for the following cases:
|
||||
// forward_sin_op, forward_cos_op, forward_sinh_op, forward_cosh_op.
|
||||
// (except that there is a sign difference for the hyperbolic case).
|
||||
size_t k;
|
||||
if( p == 0 )
|
||||
{ s[0] = sin( x[0] );
|
||||
c[0] = cos( x[0] );
|
||||
p++;
|
||||
}
|
||||
for(size_t j = p; j <= q; j++)
|
||||
{
|
||||
s[j] = Base(0.0);
|
||||
c[j] = Base(0.0);
|
||||
for(k = 1; k <= j; k++)
|
||||
{ s[j] += Base(double(k)) * x[k] * c[j-k];
|
||||
c[j] -= Base(double(k)) * x[k] * s[j-k];
|
||||
}
|
||||
s[j] /= Base(double(j));
|
||||
c[j] /= Base(double(j));
|
||||
}
|
||||
}
|
||||
/*!
|
||||
Compute forward mode Taylor coefficient for result of op = CosOp.
|
||||
|
||||
The C++ source code corresponding to this operation is
|
||||
\verbatim
|
||||
z = cos(x)
|
||||
\endverbatim
|
||||
The auxillary result is
|
||||
\verbatim
|
||||
y = sin(x)
|
||||
\endverbatim
|
||||
The value of y, and its derivatives, are computed along with the value
|
||||
and derivatives of z.
|
||||
|
||||
\copydetails CppAD::local::forward_unary2_op_dir
|
||||
*/
|
||||
template <class Base>
|
||||
inline void forward_cos_op_dir(
|
||||
size_t q ,
|
||||
size_t r ,
|
||||
size_t i_z ,
|
||||
size_t i_x ,
|
||||
size_t cap_order ,
|
||||
Base* taylor )
|
||||
{
|
||||
// check assumptions
|
||||
CPPAD_ASSERT_UNKNOWN( NumArg(CosOp) == 1 );
|
||||
CPPAD_ASSERT_UNKNOWN( NumRes(CosOp) == 2 );
|
||||
CPPAD_ASSERT_UNKNOWN( 0 < q );
|
||||
CPPAD_ASSERT_UNKNOWN( q < cap_order );
|
||||
|
||||
// Taylor coefficients corresponding to argument and result
|
||||
size_t num_taylor_per_var = (cap_order-1) * r + 1;
|
||||
Base* x = taylor + i_x * num_taylor_per_var;
|
||||
Base* c = taylor + i_z * num_taylor_per_var;
|
||||
Base* s = c - num_taylor_per_var;
|
||||
|
||||
|
||||
// rest of this routine is identical for the following cases:
|
||||
// forward_sin_op, forward_cos_op, forward_sinh_op, forward_cosh_op
|
||||
// (except that there is a sign difference for the hyperbolic case).
|
||||
size_t m = (q-1) * r + 1;
|
||||
for(size_t ell = 0; ell < r; ell++)
|
||||
{ s[m+ell] = Base(double(q)) * x[m + ell] * c[0];
|
||||
c[m+ell] = - Base(double(q)) * x[m + ell] * s[0];
|
||||
for(size_t k = 1; k < q; k++)
|
||||
{ s[m+ell] += Base(double(k)) * x[(k-1)*r+1+ell] * c[(q-k-1)*r+1+ell];
|
||||
c[m+ell] -= Base(double(k)) * x[(k-1)*r+1+ell] * s[(q-k-1)*r+1+ell];
|
||||
}
|
||||
s[m+ell] /= Base(double(q));
|
||||
c[m+ell] /= Base(double(q));
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
Compute zero order forward mode Taylor coefficient for result of op = CosOp.
|
||||
|
||||
The C++ source code corresponding to this operation is
|
||||
\verbatim
|
||||
z = cos(x)
|
||||
\endverbatim
|
||||
The auxillary result is
|
||||
\verbatim
|
||||
y = sin(x)
|
||||
\endverbatim
|
||||
The value of y is computed along with the value of z.
|
||||
|
||||
\copydetails CppAD::local::forward_unary2_op_0
|
||||
*/
|
||||
template <class Base>
|
||||
inline void forward_cos_op_0(
|
||||
size_t i_z ,
|
||||
size_t i_x ,
|
||||
size_t cap_order ,
|
||||
Base* taylor )
|
||||
{
|
||||
// check assumptions
|
||||
CPPAD_ASSERT_UNKNOWN( NumArg(CosOp) == 1 );
|
||||
CPPAD_ASSERT_UNKNOWN( NumRes(CosOp) == 2 );
|
||||
CPPAD_ASSERT_UNKNOWN( 0 < cap_order );
|
||||
|
||||
// Taylor coefficients corresponding to argument and result
|
||||
Base* x = taylor + i_x * cap_order;
|
||||
Base* c = taylor + i_z * cap_order; // called z in documentation
|
||||
Base* s = c - cap_order; // called y in documentation
|
||||
|
||||
c[0] = cos( x[0] );
|
||||
s[0] = sin( x[0] );
|
||||
}
|
||||
/*!
|
||||
Compute reverse mode partial derivatives for result of op = CosOp.
|
||||
|
||||
The C++ source code corresponding to this operation is
|
||||
\verbatim
|
||||
z = cos(x)
|
||||
\endverbatim
|
||||
The auxillary result is
|
||||
\verbatim
|
||||
y = sin(x)
|
||||
\endverbatim
|
||||
The value of y is computed along with the value of z.
|
||||
|
||||
\copydetails CppAD::local::reverse_unary2_op
|
||||
*/
|
||||
|
||||
template <class Base>
|
||||
inline void reverse_cos_op(
|
||||
size_t d ,
|
||||
size_t i_z ,
|
||||
size_t i_x ,
|
||||
size_t cap_order ,
|
||||
const Base* taylor ,
|
||||
size_t nc_partial ,
|
||||
Base* partial )
|
||||
{
|
||||
// check assumptions
|
||||
CPPAD_ASSERT_UNKNOWN( NumArg(CosOp) == 1 );
|
||||
CPPAD_ASSERT_UNKNOWN( NumRes(CosOp) == 2 );
|
||||
CPPAD_ASSERT_UNKNOWN( d < cap_order );
|
||||
CPPAD_ASSERT_UNKNOWN( d < nc_partial );
|
||||
|
||||
// Taylor coefficients and partials corresponding to argument
|
||||
const Base* x = taylor + i_x * cap_order;
|
||||
Base* px = partial + i_x * nc_partial;
|
||||
|
||||
// Taylor coefficients and partials corresponding to first result
|
||||
const Base* c = taylor + i_z * cap_order; // called z in doc
|
||||
Base* pc = partial + i_z * nc_partial;
|
||||
|
||||
// Taylor coefficients and partials corresponding to auxillary result
|
||||
const Base* s = c - cap_order; // called y in documentation
|
||||
Base* ps = pc - nc_partial;
|
||||
|
||||
|
||||
// rest of this routine is identical for the following cases:
|
||||
// reverse_sin_op, reverse_cos_op, reverse_sinh_op, reverse_cosh_op.
|
||||
size_t j = d;
|
||||
size_t k;
|
||||
while(j)
|
||||
{
|
||||
ps[j] /= Base(double(j));
|
||||
pc[j] /= Base(double(j));
|
||||
for(k = 1; k <= j; k++)
|
||||
{
|
||||
px[k] += Base(double(k)) * azmul(ps[j], c[j-k]);
|
||||
px[k] -= Base(double(k)) * azmul(pc[j], s[j-k]);
|
||||
|
||||
ps[j-k] -= Base(double(k)) * azmul(pc[j], x[k]);
|
||||
pc[j-k] += Base(double(k)) * azmul(ps[j], x[k]);
|
||||
|
||||
}
|
||||
--j;
|
||||
}
|
||||
px[0] += azmul(ps[0], c[0]);
|
||||
px[0] -= azmul(pc[0], s[0]);
|
||||
}
|
||||
|
||||
} } // END_CPPAD_LOCAL_NAMESPACE
|
||||
# endif
|
||||
+238
@@ -0,0 +1,238 @@
|
||||
# ifndef CPPAD_LOCAL_COSH_OP_HPP
|
||||
# define CPPAD_LOCAL_COSH_OP_HPP
|
||||
|
||||
/* --------------------------------------------------------------------------
|
||||
CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-17 Bradley M. Bell
|
||||
|
||||
CppAD is distributed under multiple licenses. This distribution is under
|
||||
the terms of the
|
||||
Eclipse Public License Version 1.0.
|
||||
|
||||
A copy of this license is included in the COPYING file of this distribution.
|
||||
Please visit http://www.coin-or.org/CppAD/ for information on other licenses.
|
||||
-------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
namespace CppAD { namespace local { // BEGIN_CPPAD_LOCAL_NAMESPACE
|
||||
/*!
|
||||
\file cosh_op.hpp
|
||||
Forward and reverse mode calculations for z = cosh(x).
|
||||
*/
|
||||
|
||||
|
||||
/*!
|
||||
Compute forward mode Taylor coefficient for result of op = CoshOp.
|
||||
|
||||
The C++ source code corresponding to this operation is
|
||||
\verbatim
|
||||
z = cosh(x)
|
||||
\endverbatim
|
||||
The auxillary result is
|
||||
\verbatim
|
||||
y = sinh(x)
|
||||
\endverbatim
|
||||
The value of y, and its derivatives, are computed along with the value
|
||||
and derivatives of z.
|
||||
|
||||
\copydetails CppAD::local::forward_unary2_op
|
||||
*/
|
||||
template <class Base>
|
||||
inline void forward_cosh_op(
|
||||
size_t p ,
|
||||
size_t q ,
|
||||
size_t i_z ,
|
||||
size_t i_x ,
|
||||
size_t cap_order ,
|
||||
Base* taylor )
|
||||
{
|
||||
// check assumptions
|
||||
CPPAD_ASSERT_UNKNOWN( NumArg(CoshOp) == 1 );
|
||||
CPPAD_ASSERT_UNKNOWN( NumRes(CoshOp) == 2 );
|
||||
CPPAD_ASSERT_UNKNOWN( q < cap_order );
|
||||
CPPAD_ASSERT_UNKNOWN( p <= q );
|
||||
|
||||
// Taylor coefficients corresponding to argument and result
|
||||
Base* x = taylor + i_x * cap_order;
|
||||
Base* c = taylor + i_z * cap_order;
|
||||
Base* s = c - cap_order;
|
||||
|
||||
// rest of this routine is identical for the following cases:
|
||||
// forward_sin_op, forward_cos_op, forward_sinh_op, forward_cosh_op.
|
||||
// (except that there is a sign difference for hyperbolic case).
|
||||
size_t k;
|
||||
if( p == 0 )
|
||||
{ s[0] = sinh( x[0] );
|
||||
c[0] = cosh( x[0] );
|
||||
p++;
|
||||
}
|
||||
for(size_t j = p; j <= q; j++)
|
||||
{
|
||||
s[j] = Base(0.0);
|
||||
c[j] = Base(0.0);
|
||||
for(k = 1; k <= j; k++)
|
||||
{ s[j] += Base(double(k)) * x[k] * c[j-k];
|
||||
c[j] += Base(double(k)) * x[k] * s[j-k];
|
||||
}
|
||||
s[j] /= Base(double(j));
|
||||
c[j] /= Base(double(j));
|
||||
}
|
||||
}
|
||||
/*!
|
||||
Compute forward mode Taylor coefficient for result of op = CoshOp.
|
||||
|
||||
The C++ source code corresponding to this operation is
|
||||
\verbatim
|
||||
z = cosh(x)
|
||||
\endverbatim
|
||||
The auxillary result is
|
||||
\verbatim
|
||||
y = sinh(x)
|
||||
\endverbatim
|
||||
The value of y, and its derivatives, are computed along with the value
|
||||
and derivatives of z.
|
||||
|
||||
\copydetails CppAD::local::forward_unary2_op_dir
|
||||
*/
|
||||
template <class Base>
|
||||
inline void forward_cosh_op_dir(
|
||||
size_t q ,
|
||||
size_t r ,
|
||||
size_t i_z ,
|
||||
size_t i_x ,
|
||||
size_t cap_order ,
|
||||
Base* taylor )
|
||||
{
|
||||
// check assumptions
|
||||
CPPAD_ASSERT_UNKNOWN( NumArg(CoshOp) == 1 );
|
||||
CPPAD_ASSERT_UNKNOWN( NumRes(CoshOp) == 2 );
|
||||
CPPAD_ASSERT_UNKNOWN( 0 < q );
|
||||
CPPAD_ASSERT_UNKNOWN( q < cap_order );
|
||||
|
||||
// Taylor coefficients corresponding to argument and result
|
||||
size_t num_taylor_per_var = (cap_order-1) * r + 1;
|
||||
Base* x = taylor + i_x * num_taylor_per_var;
|
||||
Base* s = taylor + i_z * num_taylor_per_var;
|
||||
Base* c = s - num_taylor_per_var;
|
||||
|
||||
|
||||
// rest of this routine is identical for the following cases:
|
||||
// forward_sin_op, forward_cos_op, forward_sinh_op, forward_cosh_op
|
||||
// (except that there is a sign difference for the hyperbolic case).
|
||||
size_t m = (q-1) * r + 1;
|
||||
for(size_t ell = 0; ell < r; ell++)
|
||||
{ s[m+ell] = Base(double(q)) * x[m + ell] * c[0];
|
||||
c[m+ell] = Base(double(q)) * x[m + ell] * s[0];
|
||||
for(size_t k = 1; k < q; k++)
|
||||
{ s[m+ell] += Base(double(k)) * x[(k-1)*r+1+ell] * c[(q-k-1)*r+1+ell];
|
||||
c[m+ell] += Base(double(k)) * x[(k-1)*r+1+ell] * s[(q-k-1)*r+1+ell];
|
||||
}
|
||||
s[m+ell] /= Base(double(q));
|
||||
c[m+ell] /= Base(double(q));
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
Compute zero order forward mode Taylor coefficient for result of op = CoshOp.
|
||||
|
||||
The C++ source code corresponding to this operation is
|
||||
\verbatim
|
||||
z = cosh(x)
|
||||
\endverbatim
|
||||
The auxillary result is
|
||||
\verbatim
|
||||
y = sinh(x)
|
||||
\endverbatim
|
||||
The value of y is computed along with the value of z.
|
||||
|
||||
\copydetails CppAD::local::forward_unary2_op_0
|
||||
*/
|
||||
template <class Base>
|
||||
inline void forward_cosh_op_0(
|
||||
size_t i_z ,
|
||||
size_t i_x ,
|
||||
size_t cap_order ,
|
||||
Base* taylor )
|
||||
{
|
||||
// check assumptions
|
||||
CPPAD_ASSERT_UNKNOWN( NumArg(CoshOp) == 1 );
|
||||
CPPAD_ASSERT_UNKNOWN( NumRes(CoshOp) == 2 );
|
||||
CPPAD_ASSERT_UNKNOWN( 0 < cap_order );
|
||||
|
||||
// Taylor coefficients corresponding to argument and result
|
||||
Base* x = taylor + i_x * cap_order;
|
||||
Base* c = taylor + i_z * cap_order; // called z in documentation
|
||||
Base* s = c - cap_order; // called y in documentation
|
||||
|
||||
c[0] = cosh( x[0] );
|
||||
s[0] = sinh( x[0] );
|
||||
}
|
||||
/*!
|
||||
Compute reverse mode partial derivatives for result of op = CoshOp.
|
||||
|
||||
The C++ source code corresponding to this operation is
|
||||
\verbatim
|
||||
z = cosh(x)
|
||||
\endverbatim
|
||||
The auxillary result is
|
||||
\verbatim
|
||||
y = sinh(x)
|
||||
\endverbatim
|
||||
The value of y is computed along with the value of z.
|
||||
|
||||
\copydetails CppAD::local::reverse_unary2_op
|
||||
*/
|
||||
|
||||
template <class Base>
|
||||
inline void reverse_cosh_op(
|
||||
size_t d ,
|
||||
size_t i_z ,
|
||||
size_t i_x ,
|
||||
size_t cap_order ,
|
||||
const Base* taylor ,
|
||||
size_t nc_partial ,
|
||||
Base* partial )
|
||||
{
|
||||
// check assumptions
|
||||
CPPAD_ASSERT_UNKNOWN( NumArg(CoshOp) == 1 );
|
||||
CPPAD_ASSERT_UNKNOWN( NumRes(CoshOp) == 2 );
|
||||
CPPAD_ASSERT_UNKNOWN( d < cap_order );
|
||||
CPPAD_ASSERT_UNKNOWN( d < nc_partial );
|
||||
|
||||
// Taylor coefficients and partials corresponding to argument
|
||||
const Base* x = taylor + i_x * cap_order;
|
||||
Base* px = partial + i_x * nc_partial;
|
||||
|
||||
// Taylor coefficients and partials corresponding to first result
|
||||
const Base* c = taylor + i_z * cap_order; // called z in doc
|
||||
Base* pc = partial + i_z * nc_partial;
|
||||
|
||||
// Taylor coefficients and partials corresponding to auxillary result
|
||||
const Base* s = c - cap_order; // called y in documentation
|
||||
Base* ps = pc - nc_partial;
|
||||
|
||||
|
||||
// rest of this routine is identical for the following cases:
|
||||
// reverse_sin_op, reverse_cos_op, reverse_sinh_op, reverse_cosh_op.
|
||||
size_t j = d;
|
||||
size_t k;
|
||||
while(j)
|
||||
{
|
||||
ps[j] /= Base(double(j));
|
||||
pc[j] /= Base(double(j));
|
||||
for(k = 1; k <= j; k++)
|
||||
{
|
||||
px[k] += Base(double(k)) * azmul(ps[j], c[j-k]);
|
||||
px[k] += Base(double(k)) * azmul(pc[j], s[j-k]);
|
||||
|
||||
ps[j-k] += Base(double(k)) * azmul(pc[j], x[k]);
|
||||
pc[j-k] += Base(double(k)) * azmul(ps[j], x[k]);
|
||||
|
||||
}
|
||||
--j;
|
||||
}
|
||||
px[0] += azmul(ps[0], c[0]);
|
||||
px[0] += azmul(pc[0], s[0]);
|
||||
}
|
||||
|
||||
} } // END_CPPAD_LOCAL_NAMESPACE
|
||||
# endif
|
||||
@@ -0,0 +1,104 @@
|
||||
// $Id: cppad_colpack.hpp 3845 2016-11-19 01:50:47Z bradbell $
|
||||
/* --------------------------------------------------------------------------
|
||||
CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-16 Bradley M. Bell
|
||||
|
||||
CppAD is distributed under multiple licenses. This distribution is under
|
||||
the terms of the
|
||||
Eclipse Public License Version 1.0.
|
||||
|
||||
A copy of this license is included in the COPYING file of this distribution.
|
||||
Please visit http://www.coin-or.org/CppAD/ for information on other licenses.
|
||||
-------------------------------------------------------------------------- */
|
||||
# ifndef CPPAD_LOCAL_CPPAD_COLPACK_HPP
|
||||
# define CPPAD_LOCAL_CPPAD_COLPACK_HPP
|
||||
# if CPPAD_HAS_COLPACK
|
||||
|
||||
namespace CppAD { namespace local { // BEGIN_CPPAD_LOCAL_NAMESPACE
|
||||
/*!
|
||||
\file cppad_colpack.hpp
|
||||
External interface to Colpack routines used by cppad.
|
||||
*/
|
||||
// ---------------------------------------------------------------------------
|
||||
/*!
|
||||
Link from CppAD to ColPack used for general sparse matrices.
|
||||
|
||||
This CppAD library routine is necessary because
|
||||
<code>ColPack/ColPackHeaders.h</code> has a
|
||||
<code>using namespace std</code> at the global level.
|
||||
|
||||
\param m [in]
|
||||
is the number of rows in the sparse matrix
|
||||
|
||||
\param n [in]
|
||||
is the nubmer of columns in the sparse matrix.
|
||||
|
||||
\param adolc_pattern [in]
|
||||
This vector has size \c m,
|
||||
<code>adolc_pattern[i][0]</code> is the number of non-zeros in row \c i.
|
||||
For <code>j = 1 , ... , adolc_sparsity[i]<code>,
|
||||
<code>adolc_pattern[i][j]</code> is the column index (base zero) for the
|
||||
non-zeros in row \c i.
|
||||
|
||||
\param color [out]
|
||||
is a vector with size \c m.
|
||||
The input value of its elements does not matter.
|
||||
Upon return, it is a coloring for the rows of the sparse matrix.
|
||||
\n
|
||||
\n
|
||||
If for some \c i, <code>color[i] == m</code>, then
|
||||
<code>adolc_pattern[i][0] == 0</code>.
|
||||
Otherwise, <code>color[i] < m</code>.
|
||||
\n
|
||||
\n
|
||||
Suppose two differen rows, <code>i != r</code> have the same color.
|
||||
It follows that for all column indices \c j;
|
||||
it is not the case that both
|
||||
<code>(i, j)</code> and <code>(r, j)</code> appear in the sparsity pattern.
|
||||
\n
|
||||
\n
|
||||
This routine tries to minimize, with respect to the choice of colors,
|
||||
the number of colors.
|
||||
*/
|
||||
extern void cppad_colpack_general(
|
||||
CppAD::vector<size_t>& color ,
|
||||
size_t m ,
|
||||
size_t n ,
|
||||
const CppAD::vector<unsigned int*>& adolc_pattern
|
||||
);
|
||||
|
||||
/*!
|
||||
Link from CppAD to ColPack used for symmetric sparse matrices
|
||||
(not yet used or tested).
|
||||
|
||||
This CppAD library routine is necessary because
|
||||
<code>ColPack/ColPackHeaders.h</code> has a
|
||||
<code>using namespace std</code> at the global level.
|
||||
|
||||
\param n [in]
|
||||
is the nubmer of rows and columns in the symmetric sparse matrix.
|
||||
|
||||
\param adolc_pattern [in]
|
||||
This vector has size \c n,
|
||||
<code>adolc_pattern[i][0]</code> is the number of non-zeros in row \c i.
|
||||
For <code>j = 1 , ... , adolc_sparsity[i]<code>,
|
||||
<code>adolc_pattern[i][j]</code> is the column index (base zero) for the
|
||||
non-zeros in row \c i.
|
||||
|
||||
\param color [out]
|
||||
The input value of its elements does not matter.
|
||||
Upon return, it is a coloring for the rows of the sparse matrix.
|
||||
The properties of this coloring have not yet been determined; see
|
||||
Efficient Computation of Sparse Hessians Using Coloring
|
||||
and Automatic Differentiation (pdf/ad/gebemedhin14.pdf)
|
||||
*/
|
||||
extern void cppad_colpack_symmetric(
|
||||
CppAD::vector<size_t>& color ,
|
||||
size_t n ,
|
||||
const CppAD::vector<unsigned int*>& adolc_pattern
|
||||
);
|
||||
|
||||
} } // END_CPPAD_LOCAL_NAMESPACE
|
||||
|
||||
# endif
|
||||
# endif
|
||||
|
||||
+200
@@ -0,0 +1,200 @@
|
||||
# ifndef CPPAD_LOCAL_CSKIP_OP_HPP
|
||||
# define CPPAD_LOCAL_CSKIP_OP_HPP
|
||||
|
||||
/* --------------------------------------------------------------------------
|
||||
CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-17 Bradley M. Bell
|
||||
|
||||
CppAD is distributed under multiple licenses. This distribution is under
|
||||
the terms of the
|
||||
Eclipse Public License Version 1.0.
|
||||
|
||||
A copy of this license is included in the COPYING file of this distribution.
|
||||
Please visit http://www.coin-or.org/CppAD/ for information on other licenses.
|
||||
-------------------------------------------------------------------------- */
|
||||
|
||||
namespace CppAD { namespace local { // BEGIN_CPPAD_LOCAL_NAMESPACE
|
||||
/*!
|
||||
\file cskip_op.hpp
|
||||
Zero order forward mode set which operations to skip.
|
||||
*/
|
||||
|
||||
/*!
|
||||
Zero order forward mode execution of op = CSkipOp.
|
||||
|
||||
\par Parameters and Variables
|
||||
The terms parameter and variable depend on if we are referring to its
|
||||
AD<Base> or Base value.
|
||||
We use Base parameter and Base variable to refer to the
|
||||
correspond Base value.
|
||||
We use AD<Base> parameter and AD<Base> variable to refer to the
|
||||
correspond AD<Base> value.
|
||||
|
||||
\tparam Base
|
||||
base type for the operator; i.e., this operation was recorded
|
||||
using AD<Base> and computations by this routine are done using type Base.
|
||||
|
||||
\param i_z
|
||||
variable index corresponding to the result of the previous operation.
|
||||
This is used for error checking. To be specific,
|
||||
the left and right operands for the CExpOp operation must have indexes
|
||||
less than or equal this value.
|
||||
|
||||
\param arg [in]
|
||||
\n
|
||||
\a arg[0]
|
||||
is static cast to size_t from the enum type
|
||||
\verbatim
|
||||
enum CompareOp {
|
||||
CompareLt,
|
||||
CompareLe,
|
||||
CompareEq,
|
||||
CompareGe,
|
||||
CompareGt,
|
||||
CompareNe
|
||||
}
|
||||
\endverbatim
|
||||
for this operation.
|
||||
Note that arg[0] cannot be equal to CompareNe.
|
||||
\n
|
||||
\n
|
||||
\a arg[1] & 1
|
||||
\n
|
||||
If this is zero, left is an AD<Base> parameter.
|
||||
Otherwise it is an AD<Base> variable.
|
||||
\n
|
||||
\n
|
||||
\a arg[1] & 2
|
||||
\n
|
||||
If this is zero, right is an AD<Base> parameter.
|
||||
Otherwise it is an AD<Base> variable.
|
||||
\n
|
||||
\a arg[2]
|
||||
is the index corresponding to left in comparision.
|
||||
\n
|
||||
\a arg[3]
|
||||
is the index corresponding to right in comparision.
|
||||
\n
|
||||
\a arg[4]
|
||||
is the number of operations to skip if the comparision result is true.
|
||||
\n
|
||||
\a arg[5]
|
||||
is the number of operations to skip if the comparision result is false.
|
||||
\n
|
||||
<tt>arg[5+i]</tt>
|
||||
for <tt>i = 1 , ... , arg[4]</tt> are the operations to skip if the
|
||||
comparision result is true and both left and right are
|
||||
identically Base parameters.
|
||||
\n
|
||||
<tt>arg[5+arg[4]+i]</tt>
|
||||
for <tt>i = 1 , ... , arg[5]</tt> are the operations to skip if the
|
||||
comparision result is false and both left and right are
|
||||
identically Base parameters.
|
||||
|
||||
\param num_par [in]
|
||||
is the total number of values in the vector parameter.
|
||||
|
||||
\param parameter [in]
|
||||
If left is an AD<Base> parameter,
|
||||
<code>parameter [ arg[2] ]</code> is its value.
|
||||
If right is an AD<Base> parameter,
|
||||
<code>parameter [ arg[3] ]</code> is its value.
|
||||
|
||||
\param cap_order [in]
|
||||
number of columns in the matrix containing the Taylor coefficients.
|
||||
|
||||
\param taylor [in]
|
||||
If left is an AD<Base> variable,
|
||||
<code>taylor [ arg[2] * cap_order + 0 ]</code>
|
||||
is the zeroth order Taylor coefficient corresponding to left.
|
||||
If right is an AD<Base> variable,
|
||||
<code>taylor [ arg[3] * cap_order + 0 ]</code>
|
||||
is the zeroth order Taylor coefficient corresponding to right.
|
||||
|
||||
\param cskip_op [in,out]
|
||||
is vector specifying which operations are at this point are know to be
|
||||
unecessary and can be skipped.
|
||||
This is both an input and an output.
|
||||
*/
|
||||
template <class Base>
|
||||
inline void forward_cskip_op_0(
|
||||
size_t i_z ,
|
||||
const addr_t* arg ,
|
||||
size_t num_par ,
|
||||
const Base* parameter ,
|
||||
size_t cap_order ,
|
||||
Base* taylor ,
|
||||
bool* cskip_op )
|
||||
{
|
||||
CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < size_t(CompareNe) );
|
||||
CPPAD_ASSERT_UNKNOWN( arg[1] != 0 );
|
||||
|
||||
Base left, right;
|
||||
if( arg[1] & 1 )
|
||||
{ // If variable arg[2] <= i_z, it has already been computed,
|
||||
// but it will be skipped for higher orders.
|
||||
CPPAD_ASSERT_UNKNOWN( size_t(arg[2]) <= i_z );
|
||||
left = taylor[ arg[2] * cap_order + 0 ];
|
||||
}
|
||||
else
|
||||
{ CPPAD_ASSERT_UNKNOWN( size_t(arg[2]) < num_par );
|
||||
left = parameter[ arg[2] ];
|
||||
}
|
||||
if( arg[1] & 2 )
|
||||
{ // If variable arg[3] <= i_z, it has already been computed,
|
||||
// but it will be skipped for higher orders.
|
||||
CPPAD_ASSERT_UNKNOWN( size_t(arg[3]) <= i_z );
|
||||
right = taylor[ arg[3] * cap_order + 0 ];
|
||||
}
|
||||
else
|
||||
{ CPPAD_ASSERT_UNKNOWN( size_t(arg[3]) < num_par );
|
||||
right = parameter[ arg[3] ];
|
||||
}
|
||||
bool ok_to_skip = IdenticalPar(left) & IdenticalPar(right);
|
||||
if( ! ok_to_skip )
|
||||
return;
|
||||
|
||||
// initialize to avoid compiler warning
|
||||
bool true_case = false;
|
||||
Base diff = left - right;
|
||||
switch( CompareOp( arg[0] ) )
|
||||
{
|
||||
case CompareLt:
|
||||
true_case = LessThanZero(diff);
|
||||
break;
|
||||
|
||||
case CompareLe:
|
||||
true_case = LessThanOrZero(diff);
|
||||
break;
|
||||
|
||||
case CompareEq:
|
||||
true_case = IdenticalZero(diff);
|
||||
break;
|
||||
|
||||
case CompareGe:
|
||||
true_case = GreaterThanOrZero(diff);
|
||||
break;
|
||||
|
||||
case CompareGt:
|
||||
true_case = GreaterThanZero(diff);
|
||||
break;
|
||||
|
||||
case CompareNe:
|
||||
true_case = ! IdenticalZero(diff);
|
||||
break;
|
||||
|
||||
default:
|
||||
CPPAD_ASSERT_UNKNOWN(false);
|
||||
}
|
||||
if( true_case )
|
||||
{ for(size_t i = 0; i < size_t(arg[4]); i++)
|
||||
cskip_op[ arg[6+i] ] = true;
|
||||
}
|
||||
else
|
||||
{ for(size_t i = 0; i < size_t(arg[5]); i++)
|
||||
cskip_op[ arg[6+arg[4]+i] ] = true;
|
||||
}
|
||||
return;
|
||||
}
|
||||
} } // END_CPPAD_LOCAL_NAMESPACE
|
||||
# endif
|
||||
|
||||
+623
@@ -0,0 +1,623 @@
|
||||
// $Id: csum_op.hpp 3845 2016-11-19 01:50:47Z bradbell $
|
||||
# ifndef CPPAD_LOCAL_CSUM_OP_HPP
|
||||
# define CPPAD_LOCAL_CSUM_OP_HPP
|
||||
|
||||
/* --------------------------------------------------------------------------
|
||||
CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-16 Bradley M. Bell
|
||||
|
||||
CppAD is distributed under multiple licenses. This distribution is under
|
||||
the terms of the
|
||||
Eclipse Public License Version 1.0.
|
||||
|
||||
A copy of this license is included in the COPYING file of this distribution.
|
||||
Please visit http://www.coin-or.org/CppAD/ for information on other licenses.
|
||||
-------------------------------------------------------------------------- */
|
||||
|
||||
namespace CppAD { namespace local { // BEGIN_CPPAD_LOCAL_NAMESPACE
|
||||
/*!
|
||||
\file csum_op.hpp
|
||||
Forward, reverse and sparsity calculations for cummulative summation.
|
||||
*/
|
||||
|
||||
/*!
|
||||
Compute forward mode Taylor coefficients for result of op = CsumOp.
|
||||
|
||||
This operation is
|
||||
\verbatim
|
||||
z = s + x(1) + ... + x(m) - y(1) - ... - y(n).
|
||||
\endverbatim
|
||||
|
||||
\tparam Base
|
||||
base type for the operator; i.e., this operation was recorded
|
||||
using AD< \a Base > and computations by this routine are done using type
|
||||
\a Base.
|
||||
|
||||
\param p
|
||||
lowest order of the Taylor coefficient that we are computing.
|
||||
|
||||
\param q
|
||||
highest order of the Taylor coefficient that we are computing.
|
||||
|
||||
\param i_z
|
||||
variable index corresponding to the result for this operation;
|
||||
i.e. the row index in \a taylor corresponding to z.
|
||||
|
||||
\param arg
|
||||
\a arg[0]
|
||||
is the number of addition variables in this cummulative summation; i.e.,
|
||||
<tt>m</tt>.
|
||||
\n
|
||||
\a arg[1]
|
||||
is the number of subtraction variables in this cummulative summation; i.e.,
|
||||
\c m.
|
||||
\n
|
||||
<tt>parameter[ arg[2] ]</tt>
|
||||
is the parameter value \c s in this cummunative summation.
|
||||
\n
|
||||
<tt>arg[2+i]</tt>
|
||||
for <tt>i = 1 , ... , m</tt> is the variable index of <tt>x(i)</tt>.
|
||||
\n
|
||||
<tt>arg[2+arg[0]+i]</tt>
|
||||
for <tt>i = 1 , ... , n</tt> is the variable index of <tt>y(i)</tt>.
|
||||
|
||||
\param num_par
|
||||
is the number of parameters in \a parameter.
|
||||
|
||||
\param parameter
|
||||
is the parameter vector for this operation sequence.
|
||||
|
||||
\param cap_order
|
||||
number of colums in the matrix containing all the Taylor coefficients.
|
||||
|
||||
\param taylor
|
||||
\b Input: <tt>taylor [ arg[2+i] * cap_order + k ]</tt>
|
||||
for <tt>i = 1 , ... , m</tt>
|
||||
and <tt>k = 0 , ... , q</tt>
|
||||
is the k-th order Taylor coefficient corresponding to <tt>x(i)</tt>
|
||||
\n
|
||||
\b Input: <tt>taylor [ arg[2+m+i] * cap_order + k ]</tt>
|
||||
for <tt>i = 1 , ... , n</tt>
|
||||
and <tt>k = 0 , ... , q</tt>
|
||||
is the k-th order Taylor coefficient corresponding to <tt>y(i)</tt>
|
||||
\n
|
||||
\b Input: <tt>taylor [ i_z * cap_order + k ]</tt>
|
||||
for k = 0 , ... , p,
|
||||
is the k-th order Taylor coefficient corresponding to z.
|
||||
\n
|
||||
\b Output: <tt>taylor [ i_z * cap_order + k ]</tt>
|
||||
for k = p , ... , q,
|
||||
is the \a k-th order Taylor coefficient corresponding to z.
|
||||
*/
|
||||
template <class Base>
|
||||
inline void forward_csum_op(
|
||||
size_t p ,
|
||||
size_t q ,
|
||||
size_t i_z ,
|
||||
const addr_t* arg ,
|
||||
size_t num_par ,
|
||||
const Base* parameter ,
|
||||
size_t cap_order ,
|
||||
Base* taylor )
|
||||
{ Base zero(0);
|
||||
size_t i, j, k;
|
||||
|
||||
// check assumptions
|
||||
CPPAD_ASSERT_UNKNOWN( NumRes(CSumOp) == 1 );
|
||||
CPPAD_ASSERT_UNKNOWN( q < cap_order );
|
||||
CPPAD_ASSERT_UNKNOWN( p <= q );
|
||||
CPPAD_ASSERT_UNKNOWN( size_t(arg[2]) < num_par );
|
||||
CPPAD_ASSERT_UNKNOWN(
|
||||
arg[0] + arg[1] == arg[ arg[0] + arg[1] + 3 ]
|
||||
);
|
||||
|
||||
// Taylor coefficients corresponding to result
|
||||
Base* z = taylor + i_z * cap_order;
|
||||
for(k = p; k <= q; k++)
|
||||
z[k] = zero;
|
||||
if( p == 0 )
|
||||
z[p] = parameter[ arg[2] ];
|
||||
Base* x;
|
||||
i = arg[0];
|
||||
j = 2;
|
||||
while(i--)
|
||||
{ CPPAD_ASSERT_UNKNOWN( size_t(arg[j+1]) < i_z );
|
||||
x = taylor + arg[++j] * cap_order;
|
||||
for(k = p; k <= q; k++)
|
||||
z[k] += x[k];
|
||||
}
|
||||
i = arg[1];
|
||||
while(i--)
|
||||
{ CPPAD_ASSERT_UNKNOWN( size_t(arg[j+1]) < i_z );
|
||||
x = taylor + arg[++j] * cap_order;
|
||||
for(k = p; k <= q; k++)
|
||||
z[k] -= x[k];
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
Multiple direction forward mode Taylor coefficients for op = CsumOp.
|
||||
|
||||
This operation is
|
||||
\verbatim
|
||||
z = s + x(1) + ... + x(m) - y(1) - ... - y(n).
|
||||
\endverbatim
|
||||
|
||||
\tparam Base
|
||||
base type for the operator; i.e., this operation was recorded
|
||||
using AD<Base> and computations by this routine are done using type
|
||||
\a Base.
|
||||
|
||||
\param q
|
||||
order ot the Taylor coefficients that we are computing.
|
||||
|
||||
\param r
|
||||
number of directions for Taylor coefficients that we are computing.
|
||||
|
||||
\param i_z
|
||||
variable index corresponding to the result for this operation;
|
||||
i.e. the row index in \a taylor corresponding to z.
|
||||
|
||||
\param arg
|
||||
\a arg[0]
|
||||
is the number of addition variables in this cummulative summation; i.e.,
|
||||
<tt>m</tt>.
|
||||
\n
|
||||
\a arg[1]
|
||||
is the number of subtraction variables in this cummulative summation; i.e.,
|
||||
\c m.
|
||||
\n
|
||||
<tt>parameter[ arg[2] ]</tt>
|
||||
is the parameter value \c s in this cummunative summation.
|
||||
\n
|
||||
<tt>arg[2+i]</tt>
|
||||
for <tt>i = 1 , ... , m</tt> is the variable index of <tt>x(i)</tt>.
|
||||
\n
|
||||
<tt>arg[2+arg[0]+i]</tt>
|
||||
for <tt>i = 1 , ... , n</tt> is the variable index of <tt>y(i)</tt>.
|
||||
|
||||
\param num_par
|
||||
is the number of parameters in \a parameter.
|
||||
|
||||
\param parameter
|
||||
is the parameter vector for this operation sequence.
|
||||
|
||||
\param cap_order
|
||||
number of colums in the matrix containing all the Taylor coefficients.
|
||||
|
||||
\param taylor
|
||||
\b Input: <tt>taylor [ arg[2+i]*((cap_order-1)*r + 1) + 0 ]</tt>
|
||||
for <tt>i = 1 , ... , m</tt>
|
||||
is the 0-th order Taylor coefficient corresponding to <tt>x(i)</tt> and
|
||||
<tt>taylor [ arg[2+i]*((cap_order-1)*r + 1) + (q-1)*r + ell + 1 ]</tt>
|
||||
for <tt>i = 1 , ... , m</tt>,
|
||||
<tt>ell = 0 , ... , r-1</tt>
|
||||
is the q-th order Taylor coefficient corresponding to <tt>x(i)</tt>
|
||||
and direction ell.
|
||||
\n
|
||||
\b Input: <tt>taylor [ arg[2+m+i]*((cap_order-1)*r + 1) + 0 ]</tt>
|
||||
for <tt>i = 1 , ... , n</tt>
|
||||
is the 0-th order Taylor coefficient corresponding to <tt>y(i)</tt> and
|
||||
<tt>taylor [ arg[2+m+i]*((cap_order-1)*r + 1) + (q-1)*r + ell + 1 ]</tt>
|
||||
for <tt>i = 1 , ... , n</tt>,
|
||||
<tt>ell = 0 , ... , r-1</tt>
|
||||
is the q-th order Taylor coefficient corresponding to <tt>y(i)</tt>
|
||||
and direction ell.
|
||||
\n
|
||||
\b Output: <tt>taylor [ i_z*((cap_order-1)*r+1) + (q-1)*r + ell + 1 ]</tt>
|
||||
is the \a q-th order Taylor coefficient corresponding to z
|
||||
for direction <tt>ell = 0 , ... , r-1</tt>.
|
||||
*/
|
||||
template <class Base>
|
||||
inline void forward_csum_op_dir(
|
||||
size_t q ,
|
||||
size_t r ,
|
||||
size_t i_z ,
|
||||
const addr_t* arg ,
|
||||
size_t num_par ,
|
||||
const Base* parameter ,
|
||||
size_t cap_order ,
|
||||
Base* taylor )
|
||||
{ Base zero(0);
|
||||
size_t i, j, ell;
|
||||
|
||||
// check assumptions
|
||||
CPPAD_ASSERT_UNKNOWN( NumRes(CSumOp) == 1 );
|
||||
CPPAD_ASSERT_UNKNOWN( q < cap_order );
|
||||
CPPAD_ASSERT_UNKNOWN( 0 < q );
|
||||
CPPAD_ASSERT_UNKNOWN( size_t(arg[2]) < num_par );
|
||||
CPPAD_ASSERT_UNKNOWN(
|
||||
arg[0] + arg[1] == arg[ arg[0] + arg[1] + 3 ]
|
||||
);
|
||||
|
||||
// Taylor coefficients corresponding to result
|
||||
size_t num_taylor_per_var = (cap_order-1) * r + 1;
|
||||
size_t m = (q-1)*r + 1;
|
||||
Base* z = taylor + i_z * num_taylor_per_var + m;
|
||||
for(ell = 0; ell < r; ell++)
|
||||
z[ell] = zero;
|
||||
Base* x;
|
||||
i = arg[0];
|
||||
j = 2;
|
||||
while(i--)
|
||||
{ CPPAD_ASSERT_UNKNOWN( size_t(arg[j+1]) < i_z );
|
||||
x = taylor + arg[++j] * num_taylor_per_var + m;
|
||||
for(ell = 0; ell < r; ell++)
|
||||
z[ell] += x[ell];
|
||||
}
|
||||
i = arg[1];
|
||||
while(i--)
|
||||
{ CPPAD_ASSERT_UNKNOWN( size_t(arg[j+1]) < i_z );
|
||||
x = taylor + arg[++j] * num_taylor_per_var + m;
|
||||
for(ell = 0; ell < r; ell++)
|
||||
z[ell] -= x[ell];
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
Compute reverse mode Taylor coefficients for result of op = CsumOp.
|
||||
|
||||
This operation is
|
||||
\verbatim
|
||||
z = q + x(1) + ... + x(m) - y(1) - ... - y(n).
|
||||
H(y, x, w, ...) = G[ z(x, y), y, x, w, ... ]
|
||||
\endverbatim
|
||||
|
||||
\tparam Base
|
||||
base type for the operator; i.e., this operation was recorded
|
||||
using AD< \a Base > and computations by this routine are done using type
|
||||
\a Base.
|
||||
|
||||
\param d
|
||||
order the highest order Taylor coefficient that we are computing
|
||||
the partial derivatives with respect to.
|
||||
|
||||
\param i_z
|
||||
variable index corresponding to the result for this operation;
|
||||
i.e. the row index in \a taylor corresponding to z.
|
||||
|
||||
\param arg
|
||||
\a arg[0]
|
||||
is the number of addition variables in this cummulative summation; i.e.,
|
||||
<tt>m</tt>.
|
||||
\n
|
||||
\a arg[1]
|
||||
is the number of subtraction variables in this cummulative summation; i.e.,
|
||||
\c m.
|
||||
\n
|
||||
<tt>parameter[ arg[2] ]</tt>
|
||||
is the parameter value \c q in this cummunative summation.
|
||||
\n
|
||||
<tt>arg[2+i]</tt>
|
||||
for <tt>i = 1 , ... , m</tt> is the value <tt>x(i)</tt>.
|
||||
\n
|
||||
<tt>arg[2+arg[0]+i]</tt>
|
||||
for <tt>i = 1 , ... , n</tt> is the value <tt>y(i)</tt>.
|
||||
|
||||
\param nc_partial
|
||||
number of colums in the matrix containing all the partial derivatives.
|
||||
|
||||
\param partial
|
||||
\b Input: <tt>partial [ arg[2+i] * nc_partial + k ]</tt>
|
||||
for <tt>i = 1 , ... , m</tt>
|
||||
and <tt>k = 0 , ... , d</tt>
|
||||
is the partial derivative of G(z, y, x, w, ...) with respect to the
|
||||
k-th order Taylor coefficient corresponding to <tt>x(i)</tt>
|
||||
\n
|
||||
\b Input: <tt>partial [ arg[2+m+i] * nc_partial + k ]</tt>
|
||||
for <tt>i = 1 , ... , n</tt>
|
||||
and <tt>k = 0 , ... , d</tt>
|
||||
is the partial derivative of G(z, y, x, w, ...) with respect to the
|
||||
k-th order Taylor coefficient corresponding to <tt>y(i)</tt>
|
||||
\n
|
||||
\b Input: <tt>partial [ i_z * nc_partial + k ]</tt>
|
||||
for <tt>i = 1 , ... , n</tt>
|
||||
and <tt>k = 0 , ... , d</tt>
|
||||
is the partial derivative of G(z, y, x, w, ...) with respect to the
|
||||
k-th order Taylor coefficient corresponding to \c z.
|
||||
\n
|
||||
\b Output: <tt>partial [ arg[2+i] * nc_partial + k ]</tt>
|
||||
for <tt>i = 1 , ... , m</tt>
|
||||
and <tt>k = 0 , ... , d</tt>
|
||||
is the partial derivative of H(y, x, w, ...) with respect to the
|
||||
k-th order Taylor coefficient corresponding to <tt>x(i)</tt>
|
||||
\n
|
||||
\b Output: <tt>partial [ arg[2+m+i] * nc_partial + k ]</tt>
|
||||
for <tt>i = 1 , ... , n</tt>
|
||||
and <tt>k = 0 , ... , d</tt>
|
||||
is the partial derivative of H(y, x, w, ...) with respect to the
|
||||
k-th order Taylor coefficient corresponding to <tt>y(i)</tt>
|
||||
*/
|
||||
|
||||
template <class Base>
|
||||
inline void reverse_csum_op(
|
||||
size_t d ,
|
||||
size_t i_z ,
|
||||
const addr_t* arg ,
|
||||
size_t nc_partial ,
|
||||
Base* partial )
|
||||
{
|
||||
// check assumptions
|
||||
CPPAD_ASSERT_UNKNOWN( NumRes(CSumOp) == 1 );
|
||||
CPPAD_ASSERT_UNKNOWN( d < nc_partial );
|
||||
|
||||
// Taylor coefficients and partial derivative corresponding to result
|
||||
Base* pz = partial + i_z * nc_partial;
|
||||
Base* px;
|
||||
size_t i, j, k;
|
||||
size_t d1 = d + 1;
|
||||
i = arg[0];
|
||||
j = 2;
|
||||
while(i--)
|
||||
{ CPPAD_ASSERT_UNKNOWN( size_t(arg[j+1]) < i_z );
|
||||
px = partial + arg[++j] * nc_partial;
|
||||
k = d1;
|
||||
while(k--)
|
||||
px[k] += pz[k];
|
||||
}
|
||||
i = arg[1];
|
||||
while(i--)
|
||||
{ CPPAD_ASSERT_UNKNOWN( size_t(arg[j+1]) < i_z );
|
||||
px = partial + arg[++j] * nc_partial;
|
||||
k = d1;
|
||||
while(k--)
|
||||
px[k] -= pz[k];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
Forward mode Jacobian sparsity pattern for CSumOp operator.
|
||||
|
||||
This operation is
|
||||
\verbatim
|
||||
z = q + x(1) + ... + x(m) - y(1) - ... - y(n).
|
||||
\endverbatim
|
||||
|
||||
\tparam Vector_set
|
||||
is the type used for vectors of sets. It can be either
|
||||
sparse_pack or sparse_list.
|
||||
|
||||
\param i_z
|
||||
variable index corresponding to the result for this operation;
|
||||
i.e. the index in \a sparsity corresponding to z.
|
||||
|
||||
\param arg
|
||||
\a arg[0]
|
||||
is the number of addition variables in this cummulative summation; i.e.,
|
||||
<tt>m + n</tt>.
|
||||
\n
|
||||
\a arg[1]
|
||||
is the number of subtraction variables in this cummulative summation; i.e.,
|
||||
\c m.
|
||||
\n
|
||||
<tt>parameter[ arg[2] ]</tt>
|
||||
is the parameter value \c q in this cummunative summation.
|
||||
\n
|
||||
<tt>arg[2+i]</tt>
|
||||
for <tt>i = 1 , ... , m</tt> is the value <tt>x(i)</tt>.
|
||||
\n
|
||||
<tt>arg[2+arg[1]+i]</tt>
|
||||
for <tt>i = 1 , ... , n</tt> is the value <tt>y(i)</tt>.
|
||||
|
||||
\param sparsity
|
||||
\b Input:
|
||||
For <tt>i = 1 , ... , m</tt>,
|
||||
the set with index \a arg[2+i] in \a sparsity
|
||||
is the sparsity bit pattern for <tt>x(i)</tt>.
|
||||
This identifies which of the independent variables the variable
|
||||
<tt>x(i)</tt> depends on.
|
||||
\n
|
||||
\b Input:
|
||||
For <tt>i = 1 , ... , n</tt>,
|
||||
the set with index \a arg[2+arg[0]+i] in \a sparsity
|
||||
is the sparsity bit pattern for <tt>x(i)</tt>.
|
||||
This identifies which of the independent variables the variable
|
||||
<tt>y(i)</tt> depends on.
|
||||
\n
|
||||
\b Output:
|
||||
The set with index \a i_z in \a sparsity
|
||||
is the sparsity bit pattern for z.
|
||||
This identifies which of the independent variables the variable z
|
||||
depends on.
|
||||
*/
|
||||
|
||||
template <class Vector_set>
|
||||
inline void forward_sparse_jacobian_csum_op(
|
||||
size_t i_z ,
|
||||
const addr_t* arg ,
|
||||
Vector_set& sparsity )
|
||||
{ sparsity.clear(i_z);
|
||||
|
||||
size_t i, j;
|
||||
i = arg[0] + arg[1];
|
||||
j = 2;
|
||||
while(i--)
|
||||
{ CPPAD_ASSERT_UNKNOWN( size_t(arg[j+1]) < i_z );
|
||||
sparsity.binary_union(
|
||||
i_z , // index in sparsity for result
|
||||
i_z , // index in sparsity for left operand
|
||||
arg[++j] , // index for right operand
|
||||
sparsity // sparsity vector for right operand
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
Reverse mode Jacobian sparsity pattern for CSumOp operator.
|
||||
|
||||
This operation is
|
||||
\verbatim
|
||||
z = q + x(1) + ... + x(m) - y(1) - ... - y(n).
|
||||
H(y, x, w, ...) = G[ z(x, y), y, x, w, ... ]
|
||||
\endverbatim
|
||||
|
||||
\tparam Vector_set
|
||||
is the type used for vectors of sets. It can be either
|
||||
sparse_pack or sparse_list.
|
||||
|
||||
\param i_z
|
||||
variable index corresponding to the result for this operation;
|
||||
i.e. the index in \a sparsity corresponding to z.
|
||||
|
||||
\param arg
|
||||
\a arg[0]
|
||||
is the number of addition variables in this cummulative summation; i.e.,
|
||||
<tt>m + n</tt>.
|
||||
\n
|
||||
\a arg[1]
|
||||
is the number of subtraction variables in this cummulative summation; i.e.,
|
||||
\c m.
|
||||
\n
|
||||
<tt>parameter[ arg[2] ]</tt>
|
||||
is the parameter value \c q in this cummunative summation.
|
||||
\n
|
||||
<tt>arg[2+i]</tt>
|
||||
for <tt>i = 1 , ... , m</tt> is the value <tt>x(i)</tt>.
|
||||
\n
|
||||
<tt>arg[2+arg[1]+i]</tt>
|
||||
for <tt>i = 1 , ... , n</tt> is the value <tt>y(i)</tt>.
|
||||
|
||||
\param sparsity
|
||||
For <tt>i = 1 , ... , m</tt>,
|
||||
the set with index \a arg[2+i] in \a sparsity
|
||||
is the sparsity bit pattern for <tt>x(i)</tt>.
|
||||
This identifies which of the dependent variables depend on <tt>x(i)</tt>.
|
||||
On input, the sparsity patter corresponds to \c G,
|
||||
and on ouput it corresponds to \c H.
|
||||
\n
|
||||
For <tt>i = 1 , ... , m</tt>,
|
||||
the set with index \a arg[2+arg[0]+i] in \a sparsity
|
||||
is the sparsity bit pattern for <tt>y(i)</tt>.
|
||||
This identifies which of the dependent variables depend on <tt>y(i)</tt>.
|
||||
On input, the sparsity patter corresponds to \c G,
|
||||
and on ouput it corresponds to \c H.
|
||||
\n
|
||||
\b Input:
|
||||
The set with index \a i_z in \a sparsity
|
||||
is the sparsity bit pattern for z.
|
||||
On input it corresponds to \c G and on output it is undefined.
|
||||
*/
|
||||
|
||||
template <class Vector_set>
|
||||
inline void reverse_sparse_jacobian_csum_op(
|
||||
size_t i_z ,
|
||||
const addr_t* arg ,
|
||||
Vector_set& sparsity )
|
||||
{
|
||||
size_t i, j;
|
||||
i = arg[0] + arg[1];
|
||||
j = 2;
|
||||
while(i--)
|
||||
{ ++j;
|
||||
CPPAD_ASSERT_UNKNOWN( size_t(arg[j]) < i_z );
|
||||
sparsity.binary_union(
|
||||
arg[j] , // index in sparsity for result
|
||||
arg[j] , // index in sparsity for left operand
|
||||
i_z , // index for right operand
|
||||
sparsity // sparsity vector for right operand
|
||||
);
|
||||
}
|
||||
}
|
||||
/*!
|
||||
Reverse mode Hessian sparsity pattern for CSumOp operator.
|
||||
|
||||
This operation is
|
||||
\verbatim
|
||||
z = q + x(1) + ... + x(m) - y(1) - ... - y(n).
|
||||
H(y, x, w, ...) = G[ z(x, y), y, x, w, ... ]
|
||||
\endverbatim
|
||||
|
||||
\tparam Vector_set
|
||||
is the type used for vectors of sets. It can be either
|
||||
sparse_pack or sparse_list.
|
||||
|
||||
\param i_z
|
||||
variable index corresponding to the result for this operation;
|
||||
i.e. the index in \a sparsity corresponding to z.
|
||||
|
||||
\param arg
|
||||
\a arg[0]
|
||||
is the number of addition variables in this cummulative summation; i.e.,
|
||||
<tt>m + n</tt>.
|
||||
\n
|
||||
\a arg[1]
|
||||
is the number of subtraction variables in this cummulative summation; i.e.,
|
||||
\c m.
|
||||
\n
|
||||
<tt>parameter[ arg[2] ]</tt>
|
||||
is the parameter value \c q in this cummunative summation.
|
||||
\n
|
||||
<tt>arg[2+i]</tt>
|
||||
for <tt>i = 1 , ... , m</tt> is the value <tt>x(i)</tt>.
|
||||
\n
|
||||
<tt>arg[2+arg[0]+i]</tt>
|
||||
for <tt>i = 1 , ... , n</tt> is the value <tt>y(i)</tt>.
|
||||
|
||||
\param rev_jacobian
|
||||
<tt>rev_jacobian[i_z]</tt>
|
||||
is all false (true) if the Jabobian of G with respect to z must be zero
|
||||
(may be non-zero).
|
||||
\n
|
||||
\n
|
||||
For <tt>i = 1 , ... , m</tt>
|
||||
<tt>rev_jacobian[ arg[2+i] ]</tt>
|
||||
is all false (true) if the Jacobian with respect to <tt>x(i)</tt>
|
||||
is zero (may be non-zero).
|
||||
On input, it corresponds to the function G,
|
||||
and on output it corresponds to the function H.
|
||||
\n
|
||||
\n
|
||||
For <tt>i = 1 , ... , n</tt>
|
||||
<tt>rev_jacobian[ arg[2+arg[0]+i] ]</tt>
|
||||
is all false (true) if the Jacobian with respect to <tt>y(i)</tt>
|
||||
is zero (may be non-zero).
|
||||
On input, it corresponds to the function G,
|
||||
and on output it corresponds to the function H.
|
||||
|
||||
\param rev_hes_sparsity
|
||||
The set with index \a i_z in in \a rev_hes_sparsity
|
||||
is the Hessian sparsity pattern for the fucntion G
|
||||
where one of the partials derivative is with respect to z.
|
||||
\n
|
||||
\n
|
||||
For <tt>i = 1 , ... , m</tt>
|
||||
The set with index <tt>arg[2+i]</tt> in \a rev_hes_sparsity
|
||||
is the Hessian sparsity pattern
|
||||
where one of the partials derivative is with respect to <tt>x(i)</tt>.
|
||||
On input, it corresponds to the function G,
|
||||
and on output it corresponds to the function H.
|
||||
\n
|
||||
\n
|
||||
For <tt>i = 1 , ... , n</tt>
|
||||
The set with index <tt>arg[2+arg[0]+i]</tt> in \a rev_hes_sparsity
|
||||
is the Hessian sparsity pattern
|
||||
where one of the partials derivative is with respect to <tt>y(i)</tt>.
|
||||
On input, it corresponds to the function G,
|
||||
and on output it corresponds to the function H.
|
||||
*/
|
||||
|
||||
template <class Vector_set>
|
||||
inline void reverse_sparse_hessian_csum_op(
|
||||
size_t i_z ,
|
||||
const addr_t* arg ,
|
||||
bool* rev_jacobian ,
|
||||
Vector_set& rev_hes_sparsity )
|
||||
{
|
||||
size_t i, j;
|
||||
i = arg[0] + arg[1];
|
||||
j = 2;
|
||||
while(i--)
|
||||
{ ++j;
|
||||
CPPAD_ASSERT_UNKNOWN( size_t(arg[j]) < i_z );
|
||||
rev_hes_sparsity.binary_union(
|
||||
arg[j] , // index in sparsity for result
|
||||
arg[j] , // index in sparsity for left operand
|
||||
i_z , // index for right operand
|
||||
rev_hes_sparsity // sparsity vector for right operand
|
||||
);
|
||||
rev_jacobian[arg[j]] |= rev_jacobian[i_z];
|
||||
}
|
||||
}
|
||||
|
||||
} } // END_CPPAD_LOCAL_NAMESPACE
|
||||
# endif
|
||||
+177
@@ -0,0 +1,177 @@
|
||||
# ifndef CPPAD_LOCAL_DECLARE_AD_HPP
|
||||
# define CPPAD_LOCAL_DECLARE_AD_HPP
|
||||
|
||||
/* --------------------------------------------------------------------------
|
||||
CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-17 Bradley M. Bell
|
||||
|
||||
CppAD is distributed under multiple licenses. This distribution is under
|
||||
the terms of the
|
||||
Eclipse Public License Version 1.0.
|
||||
|
||||
A copy of this license is included in the COPYING file of this distribution.
|
||||
Please visit http://www.coin-or.org/CppAD/ for information on other licenses.
|
||||
-------------------------------------------------------------------------- */
|
||||
|
||||
# include <cppad/configure.hpp>
|
||||
# if CPPAD_USE_CPLUSPLUS_2011
|
||||
# include <cstdint>
|
||||
# endif
|
||||
|
||||
/*!
|
||||
\file declare_ad.hpp CppAD forward declarations; i.e., before definition
|
||||
*/
|
||||
|
||||
namespace CppAD { namespace local { // BEGIN_CPPAD_LOCAL_NAMESPACE
|
||||
|
||||
template <class Base> class ADTape;
|
||||
template <class Base> class player;
|
||||
template <class Base> class recorder;
|
||||
|
||||
} } // END_CPPAD_LOCAL_NAMESPACE
|
||||
|
||||
namespace CppAD {
|
||||
// The conditional expression operator enum type
|
||||
enum CompareOp
|
||||
{ CompareLt, // less than
|
||||
CompareLe, // less than or equal
|
||||
CompareEq, // equal
|
||||
CompareGe, // greater than or equal
|
||||
CompareGt, // greater than
|
||||
CompareNe // not equal
|
||||
};
|
||||
|
||||
// simple typedefs
|
||||
typedef CPPAD_TAPE_ADDR_TYPE addr_t;
|
||||
typedef CPPAD_TAPE_ID_TYPE tape_id_t;
|
||||
|
||||
// classes
|
||||
class sparse_hes_work;
|
||||
class sparse_jac_work;
|
||||
class sparse_jacobian_work;
|
||||
class sparse_hessian_work;
|
||||
template <class Base> class AD;
|
||||
template <class Base> class ADFun;
|
||||
template <class Base> class atomic_base;
|
||||
template <class Base> class discrete;
|
||||
template <class Base> class VecAD;
|
||||
template <class Base> class VecAD_reference;
|
||||
|
||||
// functions with one VecAD<Base> argument
|
||||
template <class Base> bool Parameter (const VecAD<Base> &u);
|
||||
template <class Base> bool Variable (const VecAD<Base> &u);
|
||||
|
||||
// functions with one AD<Base> argument
|
||||
template <class Base> int Integer (const AD<Base> &u);
|
||||
template <class Base> bool Parameter (const AD<Base> &u);
|
||||
template <class Base> bool Variable (const AD<Base> &u);
|
||||
template <class Base> bool IdenticalZero (const AD<Base> &u);
|
||||
template <class Base> bool IdenticalOne (const AD<Base> &u);
|
||||
template <class Base> bool IdenticalPar (const AD<Base> &u);
|
||||
template <class Base> bool LessThanZero (const AD<Base> &u);
|
||||
template <class Base> bool LessThanOrZero (const AD<Base> &u);
|
||||
template <class Base> bool GreaterThanZero (const AD<Base> &u);
|
||||
template <class Base> bool GreaterThanOrZero (const AD<Base> &u);
|
||||
template <class Base> AD<Base> Var2Par (const AD<Base> &u);
|
||||
template <class Base> AD<Base> abs (const AD<Base> &u);
|
||||
template <class Base> AD<Base> acos (const AD<Base> &u);
|
||||
template <class Base> AD<Base> asin (const AD<Base> &u);
|
||||
template <class Base> AD<Base> atan (const AD<Base> &u);
|
||||
template <class Base> AD<Base> cos (const AD<Base> &u);
|
||||
template <class Base> AD<Base> cosh (const AD<Base> &u);
|
||||
template <class Base> AD<Base> exp (const AD<Base> &u);
|
||||
template <class Base> AD<Base> log (const AD<Base> &u);
|
||||
template <class Base> AD<Base> log10 (const AD<Base> &u);
|
||||
template <class Base> AD<Base> sin (const AD<Base> &u);
|
||||
template <class Base> AD<Base> sinh (const AD<Base> &u);
|
||||
template <class Base> AD<Base> sqrt (const AD<Base> &u);
|
||||
template <class Base> AD<Base> tan (const AD<Base> &u);
|
||||
|
||||
// arithematic operators
|
||||
template <class Base> AD<Base> operator + (
|
||||
const AD<Base> &left, const AD<Base> &right);
|
||||
template <class Base> AD<Base> operator - (
|
||||
const AD<Base> &left, const AD<Base> &right);
|
||||
template <class Base> AD<Base> operator * (
|
||||
const AD<Base> &left, const AD<Base> &right);
|
||||
template <class Base> AD<Base> operator / (
|
||||
const AD<Base> &left, const AD<Base> &right);
|
||||
|
||||
// comparison operators
|
||||
template <class Base> bool operator < (
|
||||
const AD<Base> &left, const AD<Base> &right);
|
||||
template <class Base> bool operator <= (
|
||||
const AD<Base> &left, const AD<Base> &right);
|
||||
template <class Base> bool operator > (
|
||||
const AD<Base> &left, const AD<Base> &right);
|
||||
template <class Base> bool operator >= (
|
||||
const AD<Base> &left, const AD<Base> &right);
|
||||
template <class Base> bool operator == (
|
||||
const AD<Base> &left, const AD<Base> &right);
|
||||
template <class Base> bool operator != (
|
||||
const AD<Base> &left, const AD<Base> &right);
|
||||
|
||||
// pow
|
||||
template <class Base> AD<Base> pow (
|
||||
const AD<Base> &x, const AD<Base> &y);
|
||||
|
||||
// azmul
|
||||
template <class Base> AD<Base> azmul (
|
||||
const AD<Base> &x, const AD<Base> &y);
|
||||
|
||||
// NearEqual
|
||||
template <class Base> bool NearEqual(
|
||||
const AD<Base> &x, const AD<Base> &y, const Base &r, const Base &a);
|
||||
|
||||
template <class Base> bool NearEqual(
|
||||
const Base &x, const AD<Base> &y, const Base &r, const Base &a);
|
||||
|
||||
template <class Base> bool NearEqual(
|
||||
const AD<Base> &x, const Base &y, const Base &r, const Base &a);
|
||||
|
||||
// CondExpOp
|
||||
template <class Base> AD<Base> CondExpOp (
|
||||
enum CompareOp cop ,
|
||||
const AD<Base> &left ,
|
||||
const AD<Base> &right ,
|
||||
const AD<Base> &trueCase ,
|
||||
const AD<Base> &falseCase
|
||||
);
|
||||
|
||||
// IdenticalEqualPar
|
||||
template <class Base>
|
||||
bool IdenticalEqualPar (const AD<Base> &u, const AD<Base> &v);
|
||||
|
||||
// EqualOpSeq
|
||||
template <class Base>
|
||||
bool EqualOpSeq (const AD<Base> &u, const AD<Base> &v);
|
||||
|
||||
// PrintFor
|
||||
template <class Base>
|
||||
void PrintFor(
|
||||
const AD<Base>& flag ,
|
||||
const char* before ,
|
||||
const AD<Base>& var ,
|
||||
const char* after
|
||||
);
|
||||
|
||||
// Value
|
||||
template <class Base> Base Value(const AD<Base> &x);
|
||||
|
||||
// Pow function
|
||||
template <class Base> AD<Base> pow
|
||||
(const AD<Base> &x, const AD<Base> &y);
|
||||
|
||||
// input operator
|
||||
template <class Base> std::istream&
|
||||
operator >> (std::istream &is, AD<Base> &x);
|
||||
|
||||
// output operator
|
||||
template <class Base> std::ostream&
|
||||
operator << (std::ostream &os, const AD<Base> &x);
|
||||
template <class Base> std::ostream&
|
||||
operator << (std::ostream &os, const VecAD_reference<Base> &e);
|
||||
template <class Base> std::ostream&
|
||||
operator << (std::ostream &os, const VecAD<Base> &vec);
|
||||
}
|
||||
|
||||
# endif
|
||||
+121
@@ -0,0 +1,121 @@
|
||||
# ifndef CPPAD_LOCAL_DISCRETE_OP_HPP
|
||||
# define CPPAD_LOCAL_DISCRETE_OP_HPP
|
||||
|
||||
/* --------------------------------------------------------------------------
|
||||
CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-17 Bradley M. Bell
|
||||
|
||||
CppAD is distributed under multiple licenses. This distribution is under
|
||||
the terms of the
|
||||
Eclipse Public License Version 1.0.
|
||||
|
||||
A copy of this license is included in the COPYING file of this distribution.
|
||||
Please visit http://www.coin-or.org/CppAD/ for information on other licenses.
|
||||
-------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
namespace CppAD { namespace local { // BEGIN_CPPAD_LOCAL_NAMESPACE
|
||||
/*!
|
||||
\file discrete_op.hpp
|
||||
Forward mode for z = f(x) where f is piecewise constant.
|
||||
*/
|
||||
|
||||
|
||||
/*!
|
||||
forward mode Taylor coefficient for result of op = DisOp.
|
||||
|
||||
The C++ source code corresponding to this operation is
|
||||
\verbatim
|
||||
z = f(x)
|
||||
\endverbatim
|
||||
where f is a piecewise constant function (and it's derivative is always
|
||||
calculated as zero).
|
||||
|
||||
\tparam Base
|
||||
base type for the operator; i.e., this operation was recorded
|
||||
using AD< \a Base > and computations by this routine are done using type
|
||||
\a Base .
|
||||
|
||||
\param p
|
||||
is the lowest order Taylor coefficient that will be calculated.
|
||||
|
||||
\param q
|
||||
is the highest order Taylor coefficient that will be calculated.
|
||||
|
||||
\param r
|
||||
is the number of directions, for each order,
|
||||
that will be calculated (except for order zero wich only has one direction).
|
||||
|
||||
\param i_z
|
||||
variable index corresponding to the result for this operation;
|
||||
i.e. the row index in \a taylor corresponding to z.
|
||||
|
||||
\param arg
|
||||
\a arg[0]
|
||||
\n
|
||||
is the index, in the order of the discrete functions defined by the user,
|
||||
for this discrete function.
|
||||
\n
|
||||
\n
|
||||
\a arg[1]
|
||||
variable index corresponding to the argument for this operator;
|
||||
i.e. the row index in \a taylor corresponding to x.
|
||||
|
||||
\param cap_order
|
||||
maximum number of orders that will fit in the taylor array.
|
||||
|
||||
\par tpv
|
||||
We use the notation
|
||||
<code>tpv = (cap_order-1) * r + 1</code>
|
||||
which is the number of Taylor coefficients per variable
|
||||
|
||||
\param taylor
|
||||
\b Input: <code>taylor [ arg[1] * tpv + 0 ]</code>
|
||||
is the zero order Taylor coefficient corresponding to x.
|
||||
\n
|
||||
\b Output: if <code>p == 0</code>
|
||||
<code>taylor [ i_z * tpv + 0 ]</code>
|
||||
is the zero order Taylor coefficient corresponding to z.
|
||||
For k = max(p, 1), ... , q,
|
||||
<code>taylor [ i_z * tpv + (k-1)*r + 1 + ell ]</code>
|
||||
is the k-th order Taylor coefficient corresponding to z
|
||||
(which is zero).
|
||||
|
||||
\par Checked Assertions where op is the unary operator with one result:
|
||||
\li NumArg(op) == 2
|
||||
\li NumRes(op) == 1
|
||||
\li q < cap_order
|
||||
\li 0 < r
|
||||
*/
|
||||
template <class Base>
|
||||
inline void forward_dis_op(
|
||||
size_t p ,
|
||||
size_t q ,
|
||||
size_t r ,
|
||||
size_t i_z ,
|
||||
const addr_t* arg ,
|
||||
size_t cap_order ,
|
||||
Base* taylor )
|
||||
{
|
||||
// check assumptions
|
||||
CPPAD_ASSERT_UNKNOWN( NumArg(DisOp) == 2 );
|
||||
CPPAD_ASSERT_UNKNOWN( NumRes(DisOp) == 1 );
|
||||
CPPAD_ASSERT_UNKNOWN( q < cap_order );
|
||||
CPPAD_ASSERT_UNKNOWN( 0 < r );
|
||||
|
||||
// Taylor coefficients corresponding to argument and result
|
||||
size_t num_taylor_per_var = (cap_order-1) * r + 1;
|
||||
Base* x = taylor + arg[1] * num_taylor_per_var;
|
||||
Base* z = taylor + i_z * num_taylor_per_var;
|
||||
|
||||
if( p == 0 )
|
||||
{ z[0] = discrete<Base>::eval(arg[0], x[0]);
|
||||
p++;
|
||||
}
|
||||
for(size_t ell = 0; ell < r; ell++)
|
||||
for(size_t k = p; k <= q; k++)
|
||||
z[ (k-1) * r + 1 + ell ] = Base(0.0);
|
||||
}
|
||||
|
||||
|
||||
} } // END_CPPAD_LOCAL_NAMESPACE
|
||||
# endif
|
||||
+574
@@ -0,0 +1,574 @@
|
||||
# ifndef CPPAD_LOCAL_DIV_OP_HPP
|
||||
# define CPPAD_LOCAL_DIV_OP_HPP
|
||||
|
||||
/* --------------------------------------------------------------------------
|
||||
CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-17 Bradley M. Bell
|
||||
|
||||
CppAD is distributed under multiple licenses. This distribution is under
|
||||
the terms of the
|
||||
Eclipse Public License Version 1.0.
|
||||
|
||||
A copy of this license is included in the COPYING file of this distribution.
|
||||
Please visit http://www.coin-or.org/CppAD/ for information on other licenses.
|
||||
-------------------------------------------------------------------------- */
|
||||
|
||||
namespace CppAD { namespace local { // BEGIN_CPPAD_LOCAL_NAMESPACE
|
||||
/*!
|
||||
\file div_op.hpp
|
||||
Forward and reverse mode calculations for z = x / y.
|
||||
*/
|
||||
|
||||
// --------------------------- Divvv -----------------------------------------
|
||||
/*!
|
||||
Compute forward mode Taylor coefficients for result of op = DivvvOp.
|
||||
|
||||
The C++ source code corresponding to this operation is
|
||||
\verbatim
|
||||
z = x / y
|
||||
\endverbatim
|
||||
In the documentation below,
|
||||
this operations is for the case where both x and y are variables
|
||||
and the argument \a parameter is not used.
|
||||
|
||||
\copydetails CppAD::local::forward_binary_op
|
||||
*/
|
||||
|
||||
template <class Base>
|
||||
inline void forward_divvv_op(
|
||||
size_t p ,
|
||||
size_t q ,
|
||||
size_t i_z ,
|
||||
const addr_t* arg ,
|
||||
const Base* parameter ,
|
||||
size_t cap_order ,
|
||||
Base* taylor )
|
||||
{
|
||||
// check assumptions
|
||||
CPPAD_ASSERT_UNKNOWN( NumArg(DivvvOp) == 2 );
|
||||
CPPAD_ASSERT_UNKNOWN( NumRes(DivvvOp) == 1 );
|
||||
CPPAD_ASSERT_UNKNOWN( q < cap_order );
|
||||
CPPAD_ASSERT_UNKNOWN( p <= q );
|
||||
|
||||
// Taylor coefficients corresponding to arguments and result
|
||||
Base* x = taylor + arg[0] * cap_order;
|
||||
Base* y = taylor + arg[1] * cap_order;
|
||||
Base* z = taylor + i_z * cap_order;
|
||||
|
||||
|
||||
// Using CondExp, it can make sense to divide by zero,
|
||||
// so do not make it an error.
|
||||
size_t k;
|
||||
for(size_t d = p; d <= q; d++)
|
||||
{ z[d] = x[d];
|
||||
for(k = 1; k <= d; k++)
|
||||
z[d] -= z[d-k] * y[k];
|
||||
z[d] /= y[0];
|
||||
}
|
||||
}
|
||||
/*!
|
||||
Multiple directions forward mode Taylor coefficients for op = DivvvOp.
|
||||
|
||||
The C++ source code corresponding to this operation is
|
||||
\verbatim
|
||||
z = x / y
|
||||
\endverbatim
|
||||
In the documentation below,
|
||||
this operations is for the case where both x and y are variables
|
||||
and the argument \a parameter is not used.
|
||||
|
||||
\copydetails CppAD::local::forward_binary_op_dir
|
||||
*/
|
||||
|
||||
template <class Base>
|
||||
inline void forward_divvv_op_dir(
|
||||
size_t q ,
|
||||
size_t r ,
|
||||
size_t i_z ,
|
||||
const addr_t* arg ,
|
||||
const Base* parameter ,
|
||||
size_t cap_order ,
|
||||
Base* taylor )
|
||||
{
|
||||
// check assumptions
|
||||
CPPAD_ASSERT_UNKNOWN( NumArg(DivvvOp) == 2 );
|
||||
CPPAD_ASSERT_UNKNOWN( NumRes(DivvvOp) == 1 );
|
||||
CPPAD_ASSERT_UNKNOWN( 0 < q );
|
||||
CPPAD_ASSERT_UNKNOWN( q < cap_order );
|
||||
|
||||
// Taylor coefficients corresponding to arguments and result
|
||||
size_t num_taylor_per_var = (cap_order-1) * r + 1;
|
||||
Base* x = taylor + arg[0] * num_taylor_per_var;
|
||||
Base* y = taylor + arg[1] * num_taylor_per_var;
|
||||
Base* z = taylor + i_z * num_taylor_per_var;
|
||||
|
||||
|
||||
// Using CondExp, it can make sense to divide by zero,
|
||||
// so do not make it an error.
|
||||
size_t m = (q-1) * r + 1;
|
||||
for(size_t ell = 0; ell < r; ell++)
|
||||
{ z[m+ell] = x[m+ell] - z[0] * y[m+ell];
|
||||
for(size_t k = 1; k < q; k++)
|
||||
z[m+ell] -= z[(q-k-1)*r+1+ell] * y[(k-1)*r+1+ell];
|
||||
z[m+ell] /= y[0];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
Compute zero order forward mode Taylor coefficients for result of op = DivvvOp.
|
||||
|
||||
The C++ source code corresponding to this operation is
|
||||
\verbatim
|
||||
z = x / y
|
||||
\endverbatim
|
||||
In the documentation below,
|
||||
this operations is for the case where both x and y are variables
|
||||
and the argument \a parameter is not used.
|
||||
|
||||
\copydetails CppAD::local::forward_binary_op_0
|
||||
*/
|
||||
|
||||
template <class Base>
|
||||
inline void forward_divvv_op_0(
|
||||
size_t i_z ,
|
||||
const addr_t* arg ,
|
||||
const Base* parameter ,
|
||||
size_t cap_order ,
|
||||
Base* taylor )
|
||||
{
|
||||
// check assumptions
|
||||
CPPAD_ASSERT_UNKNOWN( NumArg(DivvvOp) == 2 );
|
||||
CPPAD_ASSERT_UNKNOWN( NumRes(DivvvOp) == 1 );
|
||||
|
||||
// Taylor coefficients corresponding to arguments and result
|
||||
Base* x = taylor + arg[0] * cap_order;
|
||||
Base* y = taylor + arg[1] * cap_order;
|
||||
Base* z = taylor + i_z * cap_order;
|
||||
|
||||
z[0] = x[0] / y[0];
|
||||
}
|
||||
|
||||
/*!
|
||||
Compute reverse mode partial derivatives for result of op = DivvvOp.
|
||||
|
||||
The C++ source code corresponding to this operation is
|
||||
\verbatim
|
||||
z = x / y
|
||||
\endverbatim
|
||||
In the documentation below,
|
||||
this operations is for the case where both x and y are variables
|
||||
and the argument \a parameter is not used.
|
||||
|
||||
\copydetails CppAD::local::reverse_binary_op
|
||||
*/
|
||||
|
||||
template <class Base>
|
||||
inline void reverse_divvv_op(
|
||||
size_t d ,
|
||||
size_t i_z ,
|
||||
const addr_t* arg ,
|
||||
const Base* parameter ,
|
||||
size_t cap_order ,
|
||||
const Base* taylor ,
|
||||
size_t nc_partial ,
|
||||
Base* partial )
|
||||
{
|
||||
// check assumptions
|
||||
CPPAD_ASSERT_UNKNOWN( NumArg(DivvvOp) == 2 );
|
||||
CPPAD_ASSERT_UNKNOWN( NumRes(DivvvOp) == 1 );
|
||||
CPPAD_ASSERT_UNKNOWN( d < cap_order );
|
||||
CPPAD_ASSERT_UNKNOWN( d < nc_partial );
|
||||
|
||||
// Arguments
|
||||
const Base* y = taylor + arg[1] * cap_order;
|
||||
const Base* z = taylor + i_z * cap_order;
|
||||
|
||||
// Partial derivatives corresponding to arguments and result
|
||||
Base* px = partial + arg[0] * nc_partial;
|
||||
Base* py = partial + arg[1] * nc_partial;
|
||||
Base* pz = partial + i_z * nc_partial;
|
||||
|
||||
// Using CondExp, it can make sense to divide by zero
|
||||
// so do not make it an error.
|
||||
Base inv_y0 = Base(1.0) / y[0];
|
||||
|
||||
size_t k;
|
||||
// number of indices to access
|
||||
size_t j = d + 1;
|
||||
while(j)
|
||||
{ --j;
|
||||
// scale partial w.r.t. z[j]
|
||||
pz[j] = azmul(pz[j], inv_y0);
|
||||
|
||||
px[j] += pz[j];
|
||||
for(k = 1; k <= j; k++)
|
||||
{ pz[j-k] -= azmul(pz[j], y[k] );
|
||||
py[k] -= azmul(pz[j], z[j-k]);
|
||||
}
|
||||
py[0] -= azmul(pz[j], z[j]);
|
||||
}
|
||||
}
|
||||
|
||||
// --------------------------- Divpv -----------------------------------------
|
||||
/*!
|
||||
Compute forward mode Taylor coefficients for result of op = DivpvOp.
|
||||
|
||||
The C++ source code corresponding to this operation is
|
||||
\verbatim
|
||||
z = x / y
|
||||
\endverbatim
|
||||
In the documentation below,
|
||||
this operations is for the case where x is a parameter and y is a variable.
|
||||
|
||||
\copydetails CppAD::local::forward_binary_op
|
||||
*/
|
||||
|
||||
template <class Base>
|
||||
inline void forward_divpv_op(
|
||||
size_t p ,
|
||||
size_t q ,
|
||||
size_t i_z ,
|
||||
const addr_t* arg ,
|
||||
const Base* parameter ,
|
||||
size_t cap_order ,
|
||||
Base* taylor )
|
||||
{
|
||||
// check assumptions
|
||||
CPPAD_ASSERT_UNKNOWN( NumArg(DivpvOp) == 2 );
|
||||
CPPAD_ASSERT_UNKNOWN( NumRes(DivpvOp) == 1 );
|
||||
CPPAD_ASSERT_UNKNOWN( q < cap_order );
|
||||
CPPAD_ASSERT_UNKNOWN( p <= q );
|
||||
|
||||
// Taylor coefficients corresponding to arguments and result
|
||||
Base* y = taylor + arg[1] * cap_order;
|
||||
Base* z = taylor + i_z * cap_order;
|
||||
|
||||
// Paraemter value
|
||||
Base x = parameter[ arg[0] ];
|
||||
|
||||
// Using CondExp, it can make sense to divide by zero,
|
||||
// so do not make it an error.
|
||||
size_t k;
|
||||
if( p == 0 )
|
||||
{ z[0] = x / y[0];
|
||||
p++;
|
||||
}
|
||||
for(size_t d = p; d <= q; d++)
|
||||
{ z[d] = Base(0.0);
|
||||
for(k = 1; k <= d; k++)
|
||||
z[d] -= z[d-k] * y[k];
|
||||
z[d] /= y[0];
|
||||
}
|
||||
}
|
||||
/*!
|
||||
Multiple directions forward mode Taylor coefficients for op = DivpvOp.
|
||||
|
||||
The C++ source code corresponding to this operation is
|
||||
\verbatim
|
||||
z = x / y
|
||||
\endverbatim
|
||||
In the documentation below,
|
||||
this operations is for the case where x is a parameter and y is a variable.
|
||||
|
||||
\copydetails CppAD::local::forward_binary_op_dir
|
||||
*/
|
||||
|
||||
template <class Base>
|
||||
inline void forward_divpv_op_dir(
|
||||
size_t q ,
|
||||
size_t r ,
|
||||
size_t i_z ,
|
||||
const addr_t* arg ,
|
||||
const Base* parameter ,
|
||||
size_t cap_order ,
|
||||
Base* taylor )
|
||||
{
|
||||
// check assumptions
|
||||
CPPAD_ASSERT_UNKNOWN( NumArg(DivpvOp) == 2 );
|
||||
CPPAD_ASSERT_UNKNOWN( NumRes(DivpvOp) == 1 );
|
||||
CPPAD_ASSERT_UNKNOWN( 0 < q );
|
||||
CPPAD_ASSERT_UNKNOWN( q < cap_order );
|
||||
|
||||
// Taylor coefficients corresponding to arguments and result
|
||||
size_t num_taylor_per_var = (cap_order-1) * r + 1;
|
||||
Base* y = taylor + arg[1] * num_taylor_per_var;
|
||||
Base* z = taylor + i_z * num_taylor_per_var;
|
||||
|
||||
// Using CondExp, it can make sense to divide by zero,
|
||||
// so do not make it an error.
|
||||
size_t m = (q-1) * r + 1;
|
||||
for(size_t ell = 0; ell < r; ell++)
|
||||
{ z[m+ell] = - z[0] * y[m+ell];
|
||||
for(size_t k = 1; k < q; k++)
|
||||
z[m+ell] -= z[(q-k-1)*r+1+ell] * y[(k-1)*r+1+ell];
|
||||
z[m+ell] /= y[0];
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
Compute zero order forward mode Taylor coefficient for result of op = DivpvOp.
|
||||
|
||||
The C++ source code corresponding to this operation is
|
||||
\verbatim
|
||||
z = x / y
|
||||
\endverbatim
|
||||
In the documentation below,
|
||||
this operations is for the case where x is a parameter and y is a variable.
|
||||
|
||||
\copydetails CppAD::local::forward_binary_op_0
|
||||
*/
|
||||
|
||||
template <class Base>
|
||||
inline void forward_divpv_op_0(
|
||||
size_t i_z ,
|
||||
const addr_t* arg ,
|
||||
const Base* parameter ,
|
||||
size_t cap_order ,
|
||||
Base* taylor )
|
||||
{
|
||||
// check assumptions
|
||||
CPPAD_ASSERT_UNKNOWN( NumArg(DivpvOp) == 2 );
|
||||
CPPAD_ASSERT_UNKNOWN( NumRes(DivpvOp) == 1 );
|
||||
|
||||
// Paraemter value
|
||||
Base x = parameter[ arg[0] ];
|
||||
|
||||
// Taylor coefficients corresponding to arguments and result
|
||||
Base* y = taylor + arg[1] * cap_order;
|
||||
Base* z = taylor + i_z * cap_order;
|
||||
|
||||
z[0] = x / y[0];
|
||||
}
|
||||
|
||||
/*!
|
||||
Compute reverse mode partial derivative for result of op = DivpvOp.
|
||||
|
||||
The C++ source code corresponding to this operation is
|
||||
\verbatim
|
||||
z = x / y
|
||||
\endverbatim
|
||||
In the documentation below,
|
||||
this operations is for the case where x is a parameter and y is a variable.
|
||||
|
||||
\copydetails CppAD::local::reverse_binary_op
|
||||
*/
|
||||
|
||||
template <class Base>
|
||||
inline void reverse_divpv_op(
|
||||
size_t d ,
|
||||
size_t i_z ,
|
||||
const addr_t* arg ,
|
||||
const Base* parameter ,
|
||||
size_t cap_order ,
|
||||
const Base* taylor ,
|
||||
size_t nc_partial ,
|
||||
Base* partial )
|
||||
{
|
||||
// check assumptions
|
||||
CPPAD_ASSERT_UNKNOWN( NumArg(DivvvOp) == 2 );
|
||||
CPPAD_ASSERT_UNKNOWN( NumRes(DivvvOp) == 1 );
|
||||
CPPAD_ASSERT_UNKNOWN( d < cap_order );
|
||||
CPPAD_ASSERT_UNKNOWN( d < nc_partial );
|
||||
|
||||
// Arguments
|
||||
const Base* y = taylor + arg[1] * cap_order;
|
||||
const Base* z = taylor + i_z * cap_order;
|
||||
|
||||
// Partial derivatives corresponding to arguments and result
|
||||
Base* py = partial + arg[1] * nc_partial;
|
||||
Base* pz = partial + i_z * nc_partial;
|
||||
|
||||
// Using CondExp, it can make sense to divide by zero so do not
|
||||
// make it an error.
|
||||
Base inv_y0 = Base(1.0) / y[0];
|
||||
|
||||
size_t k;
|
||||
// number of indices to access
|
||||
size_t j = d + 1;
|
||||
while(j)
|
||||
{ --j;
|
||||
// scale partial w.r.t z[j]
|
||||
pz[j] = azmul(pz[j], inv_y0);
|
||||
|
||||
for(k = 1; k <= j; k++)
|
||||
{ pz[j-k] -= azmul(pz[j], y[k] );
|
||||
py[k] -= azmul(pz[j], z[j-k] );
|
||||
}
|
||||
py[0] -= azmul(pz[j], z[j]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// --------------------------- Divvp -----------------------------------------
|
||||
/*!
|
||||
Compute forward mode Taylor coefficients for result of op = DivvvOp.
|
||||
|
||||
The C++ source code corresponding to this operation is
|
||||
\verbatim
|
||||
z = x / y
|
||||
\endverbatim
|
||||
In the documentation below,
|
||||
this operations is for the case where x is a variable and y is a parameter.
|
||||
|
||||
\copydetails CppAD::local::forward_binary_op
|
||||
*/
|
||||
|
||||
template <class Base>
|
||||
inline void forward_divvp_op(
|
||||
size_t p ,
|
||||
size_t q ,
|
||||
size_t i_z ,
|
||||
const addr_t* arg ,
|
||||
const Base* parameter ,
|
||||
size_t cap_order ,
|
||||
Base* taylor )
|
||||
{
|
||||
// check assumptions
|
||||
CPPAD_ASSERT_UNKNOWN( NumArg(DivvpOp) == 2 );
|
||||
CPPAD_ASSERT_UNKNOWN( NumRes(DivvpOp) == 1 );
|
||||
CPPAD_ASSERT_UNKNOWN( q < cap_order );
|
||||
CPPAD_ASSERT_UNKNOWN( p <= q );
|
||||
|
||||
// Taylor coefficients corresponding to arguments and result
|
||||
Base* x = taylor + arg[0] * cap_order;
|
||||
Base* z = taylor + i_z * cap_order;
|
||||
|
||||
// Parameter value
|
||||
Base y = parameter[ arg[1] ];
|
||||
|
||||
// Using CondExp and multiple levels of AD, it can make sense
|
||||
// to divide by zero so do not make it an error.
|
||||
for(size_t d = p; d <= q; d++)
|
||||
z[d] = x[d] / y;
|
||||
}
|
||||
/*!
|
||||
Multiple direction forward mode Taylor coefficients for op = DivvvOp.
|
||||
|
||||
The C++ source code corresponding to this operation is
|
||||
\verbatim
|
||||
z = x / y
|
||||
\endverbatim
|
||||
In the documentation below,
|
||||
this operations is for the case where x is a variable and y is a parameter.
|
||||
|
||||
\copydetails CppAD::local::forward_binary_op_dir
|
||||
*/
|
||||
|
||||
template <class Base>
|
||||
inline void forward_divvp_op_dir(
|
||||
size_t q ,
|
||||
size_t r ,
|
||||
size_t i_z ,
|
||||
const addr_t* arg ,
|
||||
const Base* parameter ,
|
||||
size_t cap_order ,
|
||||
Base* taylor )
|
||||
{
|
||||
// check assumptions
|
||||
CPPAD_ASSERT_UNKNOWN( NumArg(DivvpOp) == 2 );
|
||||
CPPAD_ASSERT_UNKNOWN( NumRes(DivvpOp) == 1 );
|
||||
CPPAD_ASSERT_UNKNOWN( q < cap_order );
|
||||
CPPAD_ASSERT_UNKNOWN( 0 < q );
|
||||
|
||||
// Taylor coefficients corresponding to arguments and result
|
||||
size_t num_taylor_per_var = (cap_order-1) * r + 1;
|
||||
Base* x = taylor + arg[0] * num_taylor_per_var;
|
||||
Base* z = taylor + i_z * num_taylor_per_var;
|
||||
|
||||
// Parameter value
|
||||
Base y = parameter[ arg[1] ];
|
||||
|
||||
// Using CondExp and multiple levels of AD, it can make sense
|
||||
// to divide by zero so do not make it an error.
|
||||
size_t m = (q-1)*r + 1;
|
||||
for(size_t ell = 0; ell < r; ell++)
|
||||
z[m + ell] = x[m + ell] / y;
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
Compute zero order forward mode Taylor coefficients for result of op = DivvvOp.
|
||||
|
||||
The C++ source code corresponding to this operation is
|
||||
\verbatim
|
||||
z = x / y
|
||||
\endverbatim
|
||||
In the documentation below,
|
||||
this operations is for the case where x is a variable and y is a parameter.
|
||||
|
||||
\copydetails CppAD::local::forward_binary_op_0
|
||||
*/
|
||||
|
||||
template <class Base>
|
||||
inline void forward_divvp_op_0(
|
||||
size_t i_z ,
|
||||
const addr_t* arg ,
|
||||
const Base* parameter ,
|
||||
size_t cap_order ,
|
||||
Base* taylor )
|
||||
{
|
||||
// check assumptions
|
||||
CPPAD_ASSERT_UNKNOWN( NumArg(DivvpOp) == 2 );
|
||||
CPPAD_ASSERT_UNKNOWN( NumRes(DivvpOp) == 1 );
|
||||
|
||||
// Parameter value
|
||||
Base y = parameter[ arg[1] ];
|
||||
|
||||
// Taylor coefficients corresponding to arguments and result
|
||||
Base* x = taylor + arg[0] * cap_order;
|
||||
Base* z = taylor + i_z * cap_order;
|
||||
|
||||
z[0] = x[0] / y;
|
||||
}
|
||||
|
||||
/*!
|
||||
Compute reverse mode partial derivative for result of op = DivvpOp.
|
||||
|
||||
The C++ source code corresponding to this operation is
|
||||
\verbatim
|
||||
z = x / y
|
||||
\endverbatim
|
||||
In the documentation below,
|
||||
this operations is for the case where x is a variable and y is a parameter.
|
||||
|
||||
\copydetails CppAD::local::reverse_binary_op
|
||||
*/
|
||||
|
||||
template <class Base>
|
||||
inline void reverse_divvp_op(
|
||||
size_t d ,
|
||||
size_t i_z ,
|
||||
const addr_t* arg ,
|
||||
const Base* parameter ,
|
||||
size_t cap_order ,
|
||||
const Base* taylor ,
|
||||
size_t nc_partial ,
|
||||
Base* partial )
|
||||
{
|
||||
// check assumptions
|
||||
CPPAD_ASSERT_UNKNOWN( NumArg(DivvpOp) == 2 );
|
||||
CPPAD_ASSERT_UNKNOWN( NumRes(DivvpOp) == 1 );
|
||||
CPPAD_ASSERT_UNKNOWN( d < cap_order );
|
||||
CPPAD_ASSERT_UNKNOWN( d < nc_partial );
|
||||
|
||||
// Argument values
|
||||
Base y = parameter[ arg[1] ];
|
||||
|
||||
// Partial derivatives corresponding to arguments and result
|
||||
Base* px = partial + arg[0] * nc_partial;
|
||||
Base* pz = partial + i_z * nc_partial;
|
||||
|
||||
// Using CondExp, it can make sense to divide by zero
|
||||
// so do not make it an error.
|
||||
Base inv_y = Base(1.0) / y;
|
||||
|
||||
// number of indices to access
|
||||
size_t j = d + 1;
|
||||
while(j)
|
||||
{ --j;
|
||||
px[j] += azmul(pz[j], inv_y);
|
||||
}
|
||||
}
|
||||
|
||||
} } // END_CPPAD_LOCAL_NAMESPACE
|
||||
# endif
|
||||
+564
@@ -0,0 +1,564 @@
|
||||
# ifndef CPPAD_LOCAL_ERF_OP_HPP
|
||||
# define CPPAD_LOCAL_ERF_OP_HPP
|
||||
# if CPPAD_USE_CPLUSPLUS_2011
|
||||
|
||||
/* --------------------------------------------------------------------------
|
||||
CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-17 Bradley M. Bell
|
||||
|
||||
CppAD is distributed under multiple licenses. This distribution is under
|
||||
the terms of the
|
||||
Eclipse Public License Version 1.0.
|
||||
|
||||
A copy of this license is included in the COPYING file of this distribution.
|
||||
Please visit http://www.coin-or.org/CppAD/ for information on other licenses.
|
||||
-------------------------------------------------------------------------- */
|
||||
|
||||
# include <cppad/local/mul_op.hpp>
|
||||
# include <cppad/local/sub_op.hpp>
|
||||
# include <cppad/local/exp_op.hpp>
|
||||
|
||||
|
||||
namespace CppAD { namespace local { // BEGIN_CPPAD_LOCAL_NAMESPACE
|
||||
/*!
|
||||
\file erf_op.hpp
|
||||
Forward and reverse mode calculations for z = erf(x).
|
||||
*/
|
||||
|
||||
/*!
|
||||
Forward mode Taylor coefficient for result of op = ErfOp.
|
||||
|
||||
The C++ source code corresponding to this operation is
|
||||
\verbatim
|
||||
z = erf(x)
|
||||
\endverbatim
|
||||
|
||||
\tparam Base
|
||||
base type for the operator; i.e., this operation was recorded
|
||||
using AD< \a Base > and computations by this routine are done using type
|
||||
\a Base.
|
||||
|
||||
\param p
|
||||
lowest order of the Taylor coefficients that we are computing.
|
||||
|
||||
\param q
|
||||
highest order of the Taylor coefficients that we are computing.
|
||||
|
||||
\param i_z
|
||||
variable index corresponding to the last (primary) result for this operation;
|
||||
i.e. the row index in \a taylor corresponding to z.
|
||||
The auxillary results are called y_j have index \a i_z - j.
|
||||
|
||||
\param arg
|
||||
arg[0]: is the variable index corresponding to x.
|
||||
\n
|
||||
arg[1]: is the parameter index corresponding to the value zero.
|
||||
\n
|
||||
\arg[2]: is the parameter index correspodning to the value 2 / sqrt(pi).
|
||||
|
||||
\param parameter
|
||||
parameter[ arg[1] ] is the value zero,
|
||||
and parameter[ arg[2] ] is the value 2 / sqrt(pi).
|
||||
|
||||
\param cap_order
|
||||
maximum number of orders that will fit in the \c taylor array.
|
||||
|
||||
\param taylor
|
||||
\b Input:
|
||||
taylor [ arg[0] * cap_order + k ]
|
||||
for k = 0 , ... , q,
|
||||
is the k-th order Taylor coefficient corresponding to x.
|
||||
\n
|
||||
\b Input:
|
||||
taylor [ i_z * cap_order + k ]
|
||||
for k = 0 , ... , p - 1,
|
||||
is the k-th order Taylor coefficient corresponding to z.
|
||||
\n
|
||||
\b Input:
|
||||
taylor [ ( i_z - j) * cap_order + k ]
|
||||
for k = 0 , ... , p-1,
|
||||
and j = 0 , ... , 4,
|
||||
is the k-th order Taylor coefficient corresponding to the j-th result for z.
|
||||
\n
|
||||
\b Output:
|
||||
taylor [ (i_z-j) * cap_order + k ],
|
||||
for k = p , ... , q,
|
||||
and j = 0 , ... , 4,
|
||||
is the k-th order Taylor coefficient corresponding to the j-th result for z.
|
||||
|
||||
\par Checked Assertions
|
||||
\li NumArg(op) == 3
|
||||
\li NumRes(op) == 5
|
||||
\li q < cap_order
|
||||
\li p <= q
|
||||
\li std::numeric_limits<addr_t>::max() >= i_z + 2
|
||||
*/
|
||||
template <class Base>
|
||||
inline void forward_erf_op(
|
||||
size_t p ,
|
||||
size_t q ,
|
||||
size_t i_z ,
|
||||
const addr_t* arg ,
|
||||
const Base* parameter ,
|
||||
size_t cap_order ,
|
||||
Base* taylor )
|
||||
{
|
||||
// check assumptions
|
||||
CPPAD_ASSERT_UNKNOWN( NumArg(ErfOp) == 3 );
|
||||
CPPAD_ASSERT_UNKNOWN( NumRes(ErfOp) == 5 );
|
||||
CPPAD_ASSERT_UNKNOWN( q < cap_order );
|
||||
CPPAD_ASSERT_UNKNOWN( p <= q );
|
||||
CPPAD_ASSERT_UNKNOWN( std::numeric_limits<addr_t>::max() >= i_z + 2 );
|
||||
|
||||
// array used to pass parameter values for sub-operations
|
||||
addr_t addr[2];
|
||||
|
||||
// convert from final result to first result
|
||||
i_z -= 4; // 4 = NumRes(ErfOp) - 1;
|
||||
|
||||
// z_0 = x * x
|
||||
addr[0] = arg[0]; // x
|
||||
addr[1] = arg[0]; // x
|
||||
forward_mulvv_op(p, q, i_z+0, addr, parameter, cap_order, taylor);
|
||||
|
||||
// z_1 = - x * x
|
||||
addr[0] = arg[1]; // zero
|
||||
addr[1] = addr_t( i_z ); // z_0
|
||||
forward_subpv_op(p, q, i_z+1, addr, parameter, cap_order, taylor);
|
||||
|
||||
// z_2 = exp( - x * x )
|
||||
forward_exp_op(p, q, i_z+2, i_z+1, cap_order, taylor);
|
||||
|
||||
// z_3 = (2 / sqrt(pi)) * exp( - x * x )
|
||||
addr[0] = arg[2]; // 2 / sqrt(pi)
|
||||
addr[1] = addr_t( i_z + 2 ); // z_2
|
||||
forward_mulpv_op(p, q, i_z+3, addr, parameter, cap_order, taylor);
|
||||
|
||||
// pointers to taylor coefficients for x , z_3, and z_4
|
||||
Base* x = taylor + arg[0] * cap_order;
|
||||
Base* z_3 = taylor + (i_z+3) * cap_order;
|
||||
Base* z_4 = taylor + (i_z+4) * cap_order;
|
||||
|
||||
// calculte z_4 coefficients
|
||||
if( p == 0 )
|
||||
{ // z4 (t) = erf[x(t)]
|
||||
z_4[0] = erf(x[0]);
|
||||
p++;
|
||||
}
|
||||
for(size_t j = p; j <= q; j++)
|
||||
{ // z_4' (t) = erf'[x(t)] * x'(t) = z3(t) * x'(t)
|
||||
// z_4[1] + 2 * z_4[2] * t + ... =
|
||||
// (z_3[0] + z_3[1] * t + ...) * (x[1] + 2 * x[2] * t + ...)
|
||||
Base base_j = static_cast<Base>(double(j));
|
||||
z_4[j] = static_cast<Base>(0);
|
||||
for(size_t k = 1; k <= j; k++)
|
||||
z_4[j] += (Base(double(k)) / base_j) * x[k] * z_3[j-k];
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
Zero order Forward mode Taylor coefficient for result of op = ErfOp.
|
||||
|
||||
The C++ source code corresponding to this operation is
|
||||
\verbatim
|
||||
z = erf(x)
|
||||
\endverbatim
|
||||
|
||||
\tparam Base
|
||||
base type for the operator; i.e., this operation was recorded
|
||||
using AD< \a Base > and computations by this routine are done using type
|
||||
\a Base.
|
||||
|
||||
\param i_z
|
||||
variable index corresponding to the last (primary) result for this operation;
|
||||
i.e. the row index in \a taylor corresponding to z.
|
||||
The auxillary results are called y_j have index \a i_z - j.
|
||||
|
||||
\param arg
|
||||
arg[0]: is the variable index corresponding to x.
|
||||
\n
|
||||
arg[1]: is the parameter index corresponding to the value zero.
|
||||
\n
|
||||
\arg[2]: is the parameter index correspodning to the value 2 / sqrt(pi).
|
||||
|
||||
\param parameter
|
||||
parameter[ arg[1] ] is the value zero,
|
||||
and parameter[ arg[2] ] is the value 2 / sqrt(pi).
|
||||
|
||||
\param cap_order
|
||||
maximum number of orders that will fit in the \c taylor array.
|
||||
|
||||
\param taylor
|
||||
\b Input:
|
||||
taylor [ arg[0] * cap_order + 0 ]
|
||||
is the zero order Taylor coefficient corresponding to x.
|
||||
\n
|
||||
\b Input:
|
||||
taylor [ i_z * cap_order + 0 ]
|
||||
is the zero order Taylor coefficient corresponding to z.
|
||||
\n
|
||||
\b Output:
|
||||
taylor [ (i_z-j) * cap_order + 0 ],
|
||||
for j = 0 , ... , 4,
|
||||
is the zero order Taylor coefficient for j-th result corresponding to z.
|
||||
|
||||
\par Checked Assertions
|
||||
\li NumArg(op) == 3
|
||||
\li NumRes(op) == 5
|
||||
\li q < cap_order
|
||||
\li p <= q
|
||||
\li std::numeric_limits<addr_t>::max() >= i_z + 2
|
||||
*/
|
||||
template <class Base>
|
||||
inline void forward_erf_op_0(
|
||||
size_t i_z ,
|
||||
const addr_t* arg ,
|
||||
const Base* parameter ,
|
||||
size_t cap_order ,
|
||||
Base* taylor )
|
||||
{
|
||||
// check assumptions
|
||||
CPPAD_ASSERT_UNKNOWN( NumArg(ErfOp) == 3 );
|
||||
CPPAD_ASSERT_UNKNOWN( NumRes(ErfOp) == 5 );
|
||||
CPPAD_ASSERT_UNKNOWN( 0 < cap_order );
|
||||
CPPAD_ASSERT_UNKNOWN( std::numeric_limits<addr_t>::max() >= i_z + 2 );
|
||||
|
||||
// array used to pass parameter values for sub-operations
|
||||
addr_t addr[2];
|
||||
|
||||
// convert from final result to first result
|
||||
i_z -= 4; // 4 = NumRes(ErfOp) - 1;
|
||||
|
||||
// z_0 = x * x
|
||||
addr[0] = arg[0]; // x
|
||||
addr[1] = arg[0]; // x
|
||||
forward_mulvv_op_0(i_z+0, addr, parameter, cap_order, taylor);
|
||||
|
||||
// z_1 = - x * x
|
||||
addr[0] = arg[1]; // zero
|
||||
addr[1] = addr_t(i_z); // z_0
|
||||
forward_subpv_op_0(i_z+1, addr, parameter, cap_order, taylor);
|
||||
|
||||
// z_2 = exp( - x * x )
|
||||
forward_exp_op_0(i_z+2, i_z+1, cap_order, taylor);
|
||||
|
||||
// z_3 = (2 / sqrt(pi)) * exp( - x * x )
|
||||
addr[0] = arg[2]; // 2 / sqrt(pi)
|
||||
addr[1] = addr_t(i_z + 2); // z_2
|
||||
forward_mulpv_op_0(i_z+3, addr, parameter, cap_order, taylor);
|
||||
|
||||
// zero order Taylor coefficient for z_4
|
||||
Base* x = taylor + arg[0] * cap_order;
|
||||
Base* z_4 = taylor + (i_z + 4) * cap_order;
|
||||
z_4[0] = erf(x[0]);
|
||||
}
|
||||
/*!
|
||||
Forward mode Taylor coefficient for result of op = ErfOp.
|
||||
|
||||
The C++ source code corresponding to this operation is
|
||||
\verbatim
|
||||
z = erf(x)
|
||||
\endverbatim
|
||||
|
||||
\tparam Base
|
||||
base type for the operator; i.e., this operation was recorded
|
||||
using AD< \a Base > and computations by this routine are done using type
|
||||
\a Base.
|
||||
|
||||
\param q
|
||||
order of the Taylor coefficients that we are computing.
|
||||
|
||||
\param r
|
||||
number of directions for the Taylor coefficients that we afre computing.
|
||||
|
||||
\param i_z
|
||||
variable index corresponding to the last (primary) result for this operation;
|
||||
i.e. the row index in \a taylor corresponding to z.
|
||||
The auxillary results have index i_z - j for j = 0 , ... , 4
|
||||
(and include z).
|
||||
|
||||
\param arg
|
||||
arg[0]: is the variable index corresponding to x.
|
||||
\n
|
||||
arg[1]: is the parameter index corresponding to the value zero.
|
||||
\n
|
||||
\arg[2]: is the parameter index correspodning to the value 2 / sqrt(pi).
|
||||
|
||||
\param parameter
|
||||
parameter[ arg[1] ] is the value zero,
|
||||
and parameter[ arg[2] ] is the value 2 / sqrt(pi).
|
||||
|
||||
\param cap_order
|
||||
maximum number of orders that will fit in the \c taylor array.
|
||||
|
||||
\par tpv
|
||||
We use the notation
|
||||
<code>tpv = (cap_order-1) * r + 1</code>
|
||||
which is the number of Taylor coefficients per variable
|
||||
|
||||
\param taylor
|
||||
\b Input: If x is a variable,
|
||||
<code>taylor [ arg[0] * tpv + 0 ]</code>,
|
||||
is the zero order Taylor coefficient for all directions and
|
||||
<code>taylor [ arg[0] * tpv + (k-1)*r + ell + 1 ]</code>,
|
||||
for k = 1 , ... , q,
|
||||
ell = 0, ..., r-1,
|
||||
is the k-th order Taylor coefficient
|
||||
corresponding to x and the ell-th direction.
|
||||
\n
|
||||
\b Input:
|
||||
taylor [ (i_z - j) * tpv + 0 ]
|
||||
is the zero order Taylor coefficient for all directions and the
|
||||
j-th result for z.
|
||||
for k = 1 , ... , q-1,
|
||||
ell = 0, ... , r-1,
|
||||
<code>
|
||||
taylor[ (i_z - j) * tpv + (k-1)*r + ell + 1]
|
||||
</code>
|
||||
is the Taylor coefficient for the k-th order, ell-th direction,
|
||||
and j-th auzillary result.
|
||||
\n
|
||||
\b Output:
|
||||
taylor [ (i_z-j) * tpv + (q-1)*r + ell + 1 ],
|
||||
for ell = 0 , ... , r-1,
|
||||
is the Taylor coefficient for the q-th order, ell-th direction,
|
||||
and j-th auzillary result.
|
||||
|
||||
\par Checked Assertions
|
||||
\li NumArg(op) == 3
|
||||
\li NumRes(op) == 5
|
||||
\li 0 < q < cap_order
|
||||
*/
|
||||
template <class Base>
|
||||
inline void forward_erf_op_dir(
|
||||
size_t q ,
|
||||
size_t r ,
|
||||
size_t i_z ,
|
||||
const addr_t* arg ,
|
||||
const Base* parameter ,
|
||||
size_t cap_order ,
|
||||
Base* taylor )
|
||||
{
|
||||
// check assumptions
|
||||
CPPAD_ASSERT_UNKNOWN( NumArg(ErfOp) == 3 );
|
||||
CPPAD_ASSERT_UNKNOWN( NumRes(ErfOp) == 5 );
|
||||
CPPAD_ASSERT_UNKNOWN( q < cap_order );
|
||||
CPPAD_ASSERT_UNKNOWN( 0 < q );
|
||||
CPPAD_ASSERT_UNKNOWN( std::numeric_limits<addr_t>::max() >= i_z + 2 );
|
||||
|
||||
// array used to pass parameter values for sub-operations
|
||||
addr_t addr[2];
|
||||
|
||||
// convert from final result to first result
|
||||
i_z -= 4; // 4 = NumRes(ErfOp) - 1;
|
||||
|
||||
// z_0 = x * x
|
||||
addr[0] = arg[0]; // x
|
||||
addr[1] = arg[0]; // x
|
||||
forward_mulvv_op_dir(q, r, i_z+0, addr, parameter, cap_order, taylor);
|
||||
|
||||
// z_1 = - x * x
|
||||
addr[0] = arg[1]; // zero
|
||||
addr[1] = addr_t( i_z ); // z_0
|
||||
forward_subpv_op_dir(q, r, i_z+1, addr, parameter, cap_order, taylor);
|
||||
|
||||
// z_2 = exp( - x * x )
|
||||
forward_exp_op_dir(q, r, i_z+2, i_z+1, cap_order, taylor);
|
||||
|
||||
// z_3 = (2 / sqrt(pi)) * exp( - x * x )
|
||||
addr[0] = arg[2]; // 2 / sqrt(pi)
|
||||
addr[1] = addr_t( i_z + 2 ); // z_2
|
||||
forward_mulpv_op_dir(q, r, i_z+3, addr, parameter, cap_order, taylor);
|
||||
|
||||
// pointers to taylor coefficients for x , z_3, and z_4
|
||||
size_t num_taylor_per_var = (cap_order - 1) * r + 1;
|
||||
Base* x = taylor + arg[0] * num_taylor_per_var;
|
||||
Base* z_3 = taylor + (i_z+3) * num_taylor_per_var;
|
||||
Base* z_4 = taylor + (i_z+4) * num_taylor_per_var;
|
||||
|
||||
// z_4' (t) = erf'[x(t)] * x'(t) = z3(t) * x'(t)
|
||||
// z_4[1] + 2 * z_4[2] * t + ... =
|
||||
// (z_3[0] + z_3[1] * t + ...) * (x[1] + 2 * x[2] * t + ...)
|
||||
Base base_q = static_cast<Base>(double(q));
|
||||
for(size_t ell = 0; ell < r; ell++)
|
||||
{ // index in z_4 and x for q-th order term
|
||||
size_t m = (q-1)*r + ell + 1;
|
||||
// initialize q-th order term summation
|
||||
z_4[m] = z_3[0] * x[m];
|
||||
for(size_t k = 1; k < q; k++)
|
||||
{ size_t x_index = (k-1)*r + ell + 1;
|
||||
size_t z3_index = (q-k-1)*r + ell + 1;
|
||||
z_4[m] += (Base(double(k)) / base_q) * x[x_index] * z_3[z3_index];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
Compute reverse mode partial derivatives for result of op = ErfOp.
|
||||
|
||||
The C++ source code corresponding to this operation is
|
||||
\verbatim
|
||||
z = erf(x)
|
||||
\endverbatim
|
||||
|
||||
\tparam Base
|
||||
base type for the operator; i.e., this operation was recorded
|
||||
using AD< \a Base > and computations by this routine are done using type
|
||||
\a Base.
|
||||
|
||||
\param d
|
||||
highest order Taylor of the Taylor coefficients that we are computing
|
||||
the partial derivatives with respect to.
|
||||
|
||||
\param i_z
|
||||
variable index corresponding to the last (primary) result for this operation;
|
||||
i.e. the row index in \a taylor corresponding to z.
|
||||
The auxillary results are called y_j have index \a i_z - j.
|
||||
|
||||
\param arg
|
||||
arg[0]: is the variable index corresponding to x.
|
||||
\n
|
||||
arg[1]: is the parameter index corresponding to the value zero.
|
||||
\n
|
||||
\arg[2]: is the parameter index correspodning to the value 2 / sqrt(pi).
|
||||
|
||||
\param parameter
|
||||
parameter[ arg[1] ] is the value zero,
|
||||
and parameter[ arg[2] ] is the value 2 / sqrt(pi).
|
||||
|
||||
\param cap_order
|
||||
maximum number of orders that will fit in the \c taylor array.
|
||||
|
||||
\param taylor
|
||||
\b Input:
|
||||
taylor [ arg[0] * cap_order + k ]
|
||||
for k = 0 , ... , d,
|
||||
is the k-th order Taylor coefficient corresponding to x.
|
||||
\n
|
||||
taylor [ (i_z - j) * cap_order + k ]
|
||||
for k = 0 , ... , d,
|
||||
and for j = 0 , ... , 4,
|
||||
is the k-th order Taylor coefficient corresponding to the j-th result
|
||||
for this operation.
|
||||
|
||||
\param nc_partial
|
||||
number of columns in the matrix containing all the partial derivatives
|
||||
|
||||
\param partial
|
||||
\b Input:
|
||||
partial [ arg[0] * nc_partial + k ]
|
||||
for k = 0 , ... , d,
|
||||
is the partial derivative of G( z , x , w , u , ... ) with respect to
|
||||
the k-th order Taylor coefficient for x.
|
||||
\n
|
||||
\b Input:
|
||||
partial [ (i_z - j) * nc_partial + k ]
|
||||
for k = 0 , ... , d,
|
||||
and for j = 0 , ... , 4,
|
||||
is the partial derivative of G( z , x , w , u , ... ) with respect to
|
||||
the k-th order Taylor coefficient for the j-th result of this operation.
|
||||
\n
|
||||
\b Output:
|
||||
partial [ arg[0] * nc_partial + k ]
|
||||
for k = 0 , ... , d,
|
||||
is the partial derivative of H( x , w , u , ... ) with respect to
|
||||
the k-th order Taylor coefficient for x.
|
||||
\n
|
||||
\b Output:
|
||||
partial [ (i_z-j) * nc_partial + k ]
|
||||
for k = 0 , ... , d,
|
||||
and for j = 0 , ... , 4,
|
||||
may be used as work space; i.e., may change in an unspecified manner.
|
||||
|
||||
\par Checked Assertions
|
||||
\li NumArg(op) == 3
|
||||
\li NumRes(op) == 5
|
||||
\li q < cap_order
|
||||
\li p <= q
|
||||
*/
|
||||
template <class Base>
|
||||
inline void reverse_erf_op(
|
||||
size_t d ,
|
||||
size_t i_z ,
|
||||
const addr_t* arg ,
|
||||
const Base* parameter ,
|
||||
size_t cap_order ,
|
||||
const Base* taylor ,
|
||||
size_t nc_partial ,
|
||||
Base* partial )
|
||||
{
|
||||
// check assumptions
|
||||
CPPAD_ASSERT_UNKNOWN( NumArg(ErfOp) == 3 );
|
||||
CPPAD_ASSERT_UNKNOWN( NumRes(ErfOp) == 5 );
|
||||
CPPAD_ASSERT_UNKNOWN( d < cap_order );
|
||||
CPPAD_ASSERT_UNKNOWN( std::numeric_limits<addr_t>::max() >= i_z + 2 );
|
||||
|
||||
// array used to pass parameter values for sub-operations
|
||||
addr_t addr[2];
|
||||
|
||||
// If pz is zero, make sure this operation has no effect
|
||||
// (zero times infinity or nan would be non-zero).
|
||||
Base* pz = partial + i_z * nc_partial;
|
||||
bool skip(true);
|
||||
for(size_t i_d = 0; i_d <= d; i_d++)
|
||||
skip &= IdenticalZero(pz[i_d]);
|
||||
if( skip )
|
||||
return;
|
||||
|
||||
// convert from final result to first result
|
||||
i_z -= 4; // 4 = NumRes(ErfOp) - 1;
|
||||
|
||||
// Taylor coefficients and partials corresponding to x
|
||||
const Base* x = taylor + arg[0] * cap_order;
|
||||
Base* px = partial + arg[0] * nc_partial;
|
||||
|
||||
// Taylor coefficients and partials corresponding to z_3
|
||||
const Base* z_3 = taylor + (i_z+3) * cap_order;
|
||||
Base* pz_3 = partial + (i_z+3) * nc_partial;
|
||||
|
||||
// Taylor coefficients and partials corresponding to z_4
|
||||
Base* pz_4 = partial + (i_z+4) * nc_partial;
|
||||
|
||||
// Reverse z_4
|
||||
size_t j = d;
|
||||
while(j)
|
||||
{ pz_4[j] /= Base(double(j));
|
||||
for(size_t k = 1; k <= j; k++)
|
||||
{ px[k] += azmul(pz_4[j], z_3[j-k]) * Base(double(k));
|
||||
pz_3[j-k] += azmul(pz_4[j], x[k]) * Base(double(k));
|
||||
}
|
||||
j--;
|
||||
}
|
||||
px[0] += azmul(pz_4[0], z_3[0]);
|
||||
|
||||
// z_3 = (2 / sqrt(pi)) * exp( - x * x )
|
||||
addr[0] = arg[2]; // 2 / sqrt(pi)
|
||||
addr[1] = addr_t( i_z + 2 ); // z_2
|
||||
reverse_mulpv_op(
|
||||
d, i_z+3, addr, parameter, cap_order, taylor, nc_partial, partial
|
||||
);
|
||||
|
||||
// z_2 = exp( - x * x )
|
||||
reverse_exp_op(
|
||||
d, i_z+2, i_z+1, cap_order, taylor, nc_partial, partial
|
||||
);
|
||||
|
||||
// z_1 = - x * x
|
||||
addr[0] = arg[1]; // zero
|
||||
addr[1] = addr_t( i_z ); // z_0
|
||||
reverse_subpv_op(
|
||||
d, i_z+1, addr, parameter, cap_order, taylor, nc_partial, partial
|
||||
);
|
||||
|
||||
// z_0 = x * x
|
||||
addr[0] = arg[0]; // x
|
||||
addr[1] = arg[0]; // x
|
||||
reverse_mulvv_op(
|
||||
d, i_z+0, addr, parameter, cap_order, taylor, nc_partial, partial
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
|
||||
} } // END_CPPAD_LOCAL_NAMESPACE
|
||||
# endif // CPPAD_USE_CPLUSPLUS_2011
|
||||
# endif // CPPAD_ERF_OP_INCLUDED
|
||||
+194
@@ -0,0 +1,194 @@
|
||||
# ifndef CPPAD_LOCAL_EXP_OP_HPP
|
||||
# define CPPAD_LOCAL_EXP_OP_HPP
|
||||
|
||||
/* --------------------------------------------------------------------------
|
||||
CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-17 Bradley M. Bell
|
||||
|
||||
CppAD is distributed under multiple licenses. This distribution is under
|
||||
the terms of the
|
||||
Eclipse Public License Version 1.0.
|
||||
|
||||
A copy of this license is included in the COPYING file of this distribution.
|
||||
Please visit http://www.coin-or.org/CppAD/ for information on other licenses.
|
||||
-------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
namespace CppAD { namespace local { // BEGIN_CPPAD_LOCAL_NAMESPACE
|
||||
/*!
|
||||
\file exp_op.hpp
|
||||
Forward and reverse mode calculations for z = exp(x).
|
||||
*/
|
||||
|
||||
|
||||
/*!
|
||||
Forward mode Taylor coefficient for result of op = ExpOp.
|
||||
|
||||
The C++ source code corresponding to this operation is
|
||||
\verbatim
|
||||
z = exp(x)
|
||||
\endverbatim
|
||||
|
||||
\copydetails CppAD::local::forward_unary1_op
|
||||
*/
|
||||
template <class Base>
|
||||
inline void forward_exp_op(
|
||||
size_t p ,
|
||||
size_t q ,
|
||||
size_t i_z ,
|
||||
size_t i_x ,
|
||||
size_t cap_order ,
|
||||
Base* taylor )
|
||||
{
|
||||
// check assumptions
|
||||
CPPAD_ASSERT_UNKNOWN( NumArg(ExpOp) == 1 );
|
||||
CPPAD_ASSERT_UNKNOWN( NumRes(ExpOp) == 1 );
|
||||
CPPAD_ASSERT_UNKNOWN( q < cap_order );
|
||||
CPPAD_ASSERT_UNKNOWN( p <= q );
|
||||
|
||||
// Taylor coefficients corresponding to argument and result
|
||||
Base* x = taylor + i_x * cap_order;
|
||||
Base* z = taylor + i_z * cap_order;
|
||||
|
||||
size_t k;
|
||||
if( p == 0 )
|
||||
{ z[0] = exp( x[0] );
|
||||
p++;
|
||||
}
|
||||
for(size_t j = p; j <= q; j++)
|
||||
{
|
||||
z[j] = x[1] * z[j-1];
|
||||
for(k = 2; k <= j; k++)
|
||||
z[j] += Base(double(k)) * x[k] * z[j-k];
|
||||
z[j] /= Base(double(j));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
Multiple direction forward mode Taylor coefficient for op = ExpOp.
|
||||
|
||||
The C++ source code corresponding to this operation is
|
||||
\verbatim
|
||||
z = exp(x)
|
||||
\endverbatim
|
||||
|
||||
\copydetails CppAD::local::forward_unary1_op_dir
|
||||
*/
|
||||
template <class Base>
|
||||
inline void forward_exp_op_dir(
|
||||
size_t q ,
|
||||
size_t r ,
|
||||
size_t i_z ,
|
||||
size_t i_x ,
|
||||
size_t cap_order ,
|
||||
Base* taylor )
|
||||
{
|
||||
// check assumptions
|
||||
CPPAD_ASSERT_UNKNOWN( NumArg(ExpOp) == 1 );
|
||||
CPPAD_ASSERT_UNKNOWN( NumRes(ExpOp) == 1 );
|
||||
CPPAD_ASSERT_UNKNOWN( q < cap_order );
|
||||
CPPAD_ASSERT_UNKNOWN( 0 < q );
|
||||
|
||||
// Taylor coefficients corresponding to argument and result
|
||||
size_t num_taylor_per_var = (cap_order-1) * r + 1;
|
||||
Base* x = taylor + i_x * num_taylor_per_var;
|
||||
Base* z = taylor + i_z * num_taylor_per_var;
|
||||
|
||||
size_t m = (q-1)*r + 1;
|
||||
for(size_t ell = 0; ell < r; ell++)
|
||||
{ z[m+ell] = Base(double(q)) * x[m+ell] * z[0];
|
||||
for(size_t k = 1; k < q; k++)
|
||||
z[m+ell] += Base(double(k)) * x[(k-1)*r+ell+1] * z[(q-k-1)*r+ell+1];
|
||||
z[m+ell] /= Base(double(q));
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
Zero order forward mode Taylor coefficient for result of op = ExpOp.
|
||||
|
||||
The C++ source code corresponding to this operation is
|
||||
\verbatim
|
||||
z = exp(x)
|
||||
\endverbatim
|
||||
|
||||
\copydetails CppAD::local::forward_unary1_op_0
|
||||
*/
|
||||
template <class Base>
|
||||
inline void forward_exp_op_0(
|
||||
size_t i_z ,
|
||||
size_t i_x ,
|
||||
size_t cap_order ,
|
||||
Base* taylor )
|
||||
{
|
||||
// check assumptions
|
||||
CPPAD_ASSERT_UNKNOWN( NumArg(ExpOp) == 1 );
|
||||
CPPAD_ASSERT_UNKNOWN( NumRes(ExpOp) == 1 );
|
||||
CPPAD_ASSERT_UNKNOWN( 0 < cap_order );
|
||||
|
||||
// Taylor coefficients corresponding to argument and result
|
||||
Base* x = taylor + i_x * cap_order;
|
||||
Base* z = taylor + i_z * cap_order;
|
||||
|
||||
z[0] = exp( x[0] );
|
||||
}
|
||||
/*!
|
||||
Reverse mode partial derivatives for result of op = ExpOp.
|
||||
|
||||
The C++ source code corresponding to this operation is
|
||||
\verbatim
|
||||
z = exp(x)
|
||||
\endverbatim
|
||||
|
||||
\copydetails CppAD::local::reverse_unary1_op
|
||||
*/
|
||||
|
||||
template <class Base>
|
||||
inline void reverse_exp_op(
|
||||
size_t d ,
|
||||
size_t i_z ,
|
||||
size_t i_x ,
|
||||
size_t cap_order ,
|
||||
const Base* taylor ,
|
||||
size_t nc_partial ,
|
||||
Base* partial )
|
||||
{
|
||||
// check assumptions
|
||||
CPPAD_ASSERT_UNKNOWN( NumArg(ExpOp) == 1 );
|
||||
CPPAD_ASSERT_UNKNOWN( NumRes(ExpOp) == 1 );
|
||||
CPPAD_ASSERT_UNKNOWN( d < cap_order );
|
||||
CPPAD_ASSERT_UNKNOWN( d < nc_partial );
|
||||
|
||||
// Taylor coefficients and partials corresponding to argument
|
||||
const Base* x = taylor + i_x * cap_order;
|
||||
Base* px = partial + i_x * nc_partial;
|
||||
|
||||
// Taylor coefficients and partials corresponding to result
|
||||
const Base* z = taylor + i_z * cap_order;
|
||||
Base* pz = partial + i_z * nc_partial;
|
||||
|
||||
// If pz is zero, make sure this operation has no effect
|
||||
// (zero times infinity or nan would be non-zero).
|
||||
bool skip(true);
|
||||
for(size_t i_d = 0; i_d <= d; i_d++)
|
||||
skip &= IdenticalZero(pz[i_d]);
|
||||
if( skip )
|
||||
return;
|
||||
|
||||
// loop through orders in reverse
|
||||
size_t j, k;
|
||||
j = d;
|
||||
while(j)
|
||||
{ // scale partial w.r.t z[j]
|
||||
pz[j] /= Base(double(j));
|
||||
|
||||
for(k = 1; k <= j; k++)
|
||||
{ px[k] += Base(double(k)) * azmul(pz[j], z[j-k]);
|
||||
pz[j-k] += Base(double(k)) * azmul(pz[j], x[k]);
|
||||
}
|
||||
--j;
|
||||
}
|
||||
px[0] += azmul(pz[0], z[0]);
|
||||
}
|
||||
|
||||
} } // END_CPPAD_LOCAL_NAMESPACE
|
||||
# endif
|
||||
+200
@@ -0,0 +1,200 @@
|
||||
# ifndef CPPAD_LOCAL_EXPM1_OP_HPP
|
||||
# define CPPAD_LOCAL_EXPM1_OP_HPP
|
||||
# if CPPAD_USE_CPLUSPLUS_2011
|
||||
|
||||
/* --------------------------------------------------------------------------
|
||||
CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-17 Bradley M. Bell
|
||||
|
||||
CppAD is distributed under multiple licenses. This distribution is under
|
||||
the terms of the
|
||||
Eclipse Public License Version 1.0.
|
||||
|
||||
A copy of this license is included in the COPYING file of this distribution.
|
||||
Please visit http://www.coin-or.org/CppAD/ for information on other licenses.
|
||||
-------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
namespace CppAD { namespace local { // BEGIN_CPPAD_LOCAL_NAMESPACE
|
||||
/*!
|
||||
\file expm1_op.hpp
|
||||
Forward and reverse mode calculations for z = expm1(x).
|
||||
*/
|
||||
|
||||
|
||||
/*!
|
||||
Forward mode Taylor coefficient for result of op = Expm1Op.
|
||||
|
||||
The C++ source code corresponding to this operation is
|
||||
\verbatim
|
||||
z = expm1(x)
|
||||
\endverbatim
|
||||
|
||||
\copydetails CppAD::local::forward_unary1_op
|
||||
*/
|
||||
template <class Base>
|
||||
inline void forward_expm1_op(
|
||||
size_t p ,
|
||||
size_t q ,
|
||||
size_t i_z ,
|
||||
size_t i_x ,
|
||||
size_t cap_order ,
|
||||
Base* taylor )
|
||||
{
|
||||
// check assumptions
|
||||
CPPAD_ASSERT_UNKNOWN( NumArg(Expm1Op) == 1 );
|
||||
CPPAD_ASSERT_UNKNOWN( NumRes(Expm1Op) == 1 );
|
||||
CPPAD_ASSERT_UNKNOWN( q < cap_order );
|
||||
CPPAD_ASSERT_UNKNOWN( p <= q );
|
||||
|
||||
// Taylor coefficients corresponding to argument and result
|
||||
Base* x = taylor + i_x * cap_order;
|
||||
Base* z = taylor + i_z * cap_order;
|
||||
|
||||
size_t k;
|
||||
if( p == 0 )
|
||||
{ z[0] = expm1( x[0] );
|
||||
p++;
|
||||
}
|
||||
for(size_t j = p; j <= q; j++)
|
||||
{
|
||||
z[j] = x[1] * z[j-1];
|
||||
for(k = 2; k <= j; k++)
|
||||
z[j] += Base(double(k)) * x[k] * z[j-k];
|
||||
z[j] /= Base(double(j));
|
||||
z[j] += x[j];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
Multiple direction forward mode Taylor coefficient for op = Expm1Op.
|
||||
|
||||
The C++ source code corresponding to this operation is
|
||||
\verbatim
|
||||
z = expm1(x)
|
||||
\endverbatim
|
||||
|
||||
\copydetails CppAD::local::forward_unary1_op_dir
|
||||
*/
|
||||
template <class Base>
|
||||
inline void forward_expm1_op_dir(
|
||||
size_t q ,
|
||||
size_t r ,
|
||||
size_t i_z ,
|
||||
size_t i_x ,
|
||||
size_t cap_order ,
|
||||
Base* taylor )
|
||||
{
|
||||
// check assumptions
|
||||
CPPAD_ASSERT_UNKNOWN( NumArg(Expm1Op) == 1 );
|
||||
CPPAD_ASSERT_UNKNOWN( NumRes(Expm1Op) == 1 );
|
||||
CPPAD_ASSERT_UNKNOWN( q < cap_order );
|
||||
CPPAD_ASSERT_UNKNOWN( 0 < q );
|
||||
|
||||
// Taylor coefficients corresponding to argument and result
|
||||
size_t num_taylor_per_var = (cap_order-1) * r + 1;
|
||||
Base* x = taylor + i_x * num_taylor_per_var;
|
||||
Base* z = taylor + i_z * num_taylor_per_var;
|
||||
|
||||
size_t m = (q-1)*r + 1;
|
||||
for(size_t ell = 0; ell < r; ell++)
|
||||
{ z[m+ell] = Base(double(q)) * x[m+ell] * z[0];
|
||||
for(size_t k = 1; k < q; k++)
|
||||
z[m+ell] += Base(double(k)) * x[(k-1)*r+ell+1] * z[(q-k-1)*r+ell+1];
|
||||
z[m+ell] /= Base(double(q));
|
||||
z[m+ell] += x[m+ell];
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
Zero order forward mode Taylor coefficient for result of op = Expm1Op.
|
||||
|
||||
The C++ source code corresponding to this operation is
|
||||
\verbatim
|
||||
z = expm1(x)
|
||||
\endverbatim
|
||||
|
||||
\copydetails CppAD::local::forward_unary1_op_0
|
||||
*/
|
||||
template <class Base>
|
||||
inline void forward_expm1_op_0(
|
||||
size_t i_z ,
|
||||
size_t i_x ,
|
||||
size_t cap_order ,
|
||||
Base* taylor )
|
||||
{
|
||||
// check assumptions
|
||||
CPPAD_ASSERT_UNKNOWN( NumArg(Expm1Op) == 1 );
|
||||
CPPAD_ASSERT_UNKNOWN( NumRes(Expm1Op) == 1 );
|
||||
CPPAD_ASSERT_UNKNOWN( 0 < cap_order );
|
||||
|
||||
// Taylor coefficients corresponding to argument and result
|
||||
Base* x = taylor + i_x * cap_order;
|
||||
Base* z = taylor + i_z * cap_order;
|
||||
|
||||
z[0] = expm1( x[0] );
|
||||
}
|
||||
/*!
|
||||
Reverse mode partial derivatives for result of op = Expm1Op.
|
||||
|
||||
The C++ source code corresponding to this operation is
|
||||
\verbatim
|
||||
z = expm1(x)
|
||||
\endverbatim
|
||||
|
||||
\copydetails CppAD::local::reverse_unary1_op
|
||||
*/
|
||||
|
||||
template <class Base>
|
||||
inline void reverse_expm1_op(
|
||||
size_t d ,
|
||||
size_t i_z ,
|
||||
size_t i_x ,
|
||||
size_t cap_order ,
|
||||
const Base* taylor ,
|
||||
size_t nc_partial ,
|
||||
Base* partial )
|
||||
{
|
||||
// check assumptions
|
||||
CPPAD_ASSERT_UNKNOWN( NumArg(Expm1Op) == 1 );
|
||||
CPPAD_ASSERT_UNKNOWN( NumRes(Expm1Op) == 1 );
|
||||
CPPAD_ASSERT_UNKNOWN( d < cap_order );
|
||||
CPPAD_ASSERT_UNKNOWN( d < nc_partial );
|
||||
|
||||
// Taylor coefficients and partials corresponding to argument
|
||||
const Base* x = taylor + i_x * cap_order;
|
||||
Base* px = partial + i_x * nc_partial;
|
||||
|
||||
// Taylor coefficients and partials corresponding to result
|
||||
const Base* z = taylor + i_z * cap_order;
|
||||
Base* pz = partial + i_z * nc_partial;
|
||||
|
||||
// If pz is zero, make sure this operation has no effect
|
||||
// (zero times infinity or nan would be non-zero).
|
||||
bool skip(true);
|
||||
for(size_t i_d = 0; i_d <= d; i_d++)
|
||||
skip &= IdenticalZero(pz[i_d]);
|
||||
if( skip )
|
||||
return;
|
||||
|
||||
// loop through orders in reverse
|
||||
size_t j, k;
|
||||
j = d;
|
||||
while(j)
|
||||
{ px[j] += pz[j];
|
||||
|
||||
// scale partial w.r.t z[j]
|
||||
pz[j] /= Base(double(j));
|
||||
|
||||
for(k = 1; k <= j; k++)
|
||||
{ px[k] += Base(double(k)) * azmul(pz[j], z[j-k]);
|
||||
pz[j-k] += Base(double(k)) * azmul(pz[j], x[k]);
|
||||
}
|
||||
--j;
|
||||
}
|
||||
px[0] += pz[0] + azmul(pz[0], z[0]);
|
||||
}
|
||||
|
||||
} } // END_CPPAD_LOCAL_NAMESPACE
|
||||
# endif
|
||||
# endif
|
||||
@@ -0,0 +1,572 @@
|
||||
# ifndef CPPAD_LOCAL_FOR_HES_SWEEP_HPP
|
||||
# define CPPAD_LOCAL_FOR_HES_SWEEP_HPP
|
||||
|
||||
/* --------------------------------------------------------------------------
|
||||
CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-17 Bradley M. Bell
|
||||
|
||||
CppAD is distributed under multiple licenses. This distribution is under
|
||||
the terms of the
|
||||
Eclipse Public License Version 1.0.
|
||||
|
||||
A copy of this license is included in the COPYING file of this distribution.
|
||||
Please visit http://www.coin-or.org/CppAD/ for information on other licenses.
|
||||
-------------------------------------------------------------------------- */
|
||||
|
||||
namespace CppAD { namespace local { // BEGIN_CPPAD_LOCAL_NAMESPACE
|
||||
/*!
|
||||
\file for_hes_sweep.hpp
|
||||
Compute Forward mode Hessian sparsity patterns.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\def CPPAD_FOR_HES_SWEEP_TRACE
|
||||
This value is either zero or one.
|
||||
Zero is the normal operational value.
|
||||
If it is one, a trace of every rev_hes_sweep computation is printed.
|
||||
*/
|
||||
# define CPPAD_FOR_HES_SWEEP_TRACE 0
|
||||
|
||||
/*!
|
||||
Given the forward Jacobian sparsity pattern for all the variables,
|
||||
and the reverse Jacobian sparsity pattern for the dependent variables,
|
||||
ForHesSweep computes the Hessian sparsity pattern for all the independent
|
||||
variables.
|
||||
|
||||
\tparam Base
|
||||
base type for the operator; i.e., this operation sequence was recorded
|
||||
using AD< \a Base > and computations by this routine are done using type
|
||||
\a Base.
|
||||
|
||||
\tparam Vector_set
|
||||
is the type used for vectors of sets. It can be either
|
||||
sparse_pack or sparse_list.
|
||||
|
||||
\param n
|
||||
is the number of independent variables on the tape.
|
||||
|
||||
\param numvar
|
||||
is the total number of variables on the tape; i.e.,
|
||||
\a play->num_var_rec().
|
||||
This is also the number of rows in the entire sparsity pattern
|
||||
\a for_hes_sparse.
|
||||
|
||||
\param play
|
||||
The information stored in \a play
|
||||
is a recording of the operations corresponding to a function
|
||||
\f[
|
||||
F : {\bf R}^n \rightarrow {\bf R}^m
|
||||
\f]
|
||||
where \f$ n \f$ is the number of independent variables
|
||||
and \f$ m \f$ is the number of dependent variables.
|
||||
The object \a play is effectly constant.
|
||||
It is not declared const because while playing back the tape
|
||||
the object \a play holds information about the current location
|
||||
with in the tape and this changes during playback.
|
||||
|
||||
\param for_jac_sparse
|
||||
For i = 0 , ... , \a numvar - 1,
|
||||
(for all the variables on the tape),
|
||||
the forward Jacobian sparsity pattern for the variable with index i
|
||||
corresponds to the set with index i in \a for_jac_sparse.
|
||||
|
||||
\param rev_jac_sparse
|
||||
\b Input:
|
||||
For i = 0, ... , \a numvar - 1
|
||||
the if the function we are computing the Hessian for has a non-zero
|
||||
derivative w.r.t. variable with index i,
|
||||
the set with index i has element zero.
|
||||
Otherwise it has no elements.
|
||||
|
||||
\param for_hes_sparse
|
||||
The forward Hessian sparsity pattern for the variable with index i
|
||||
corresponds to the set with index i in \a for_hes_sparse.
|
||||
The number of rows in this sparsity patter is n+1 and the row
|
||||
with index zero is not used.
|
||||
\n
|
||||
\n
|
||||
\b Input: For i = 1 , ... , \a n
|
||||
the forward Hessian sparsity pattern for the variable with index i is empty.
|
||||
\n
|
||||
\n
|
||||
\b Output: For j = 1 , ... , \a n,
|
||||
the forward Hessian sparsity pattern for the independent dependent variable
|
||||
with index (j-1) is given by the set with index j
|
||||
in \a for_hes_sparse.
|
||||
*/
|
||||
|
||||
template <class Base, class Vector_set>
|
||||
void ForHesSweep(
|
||||
size_t n,
|
||||
size_t numvar,
|
||||
local::player<Base>* play,
|
||||
const Vector_set& for_jac_sparse,
|
||||
const Vector_set& rev_jac_sparse,
|
||||
Vector_set& for_hes_sparse
|
||||
)
|
||||
{
|
||||
OpCode op;
|
||||
size_t i_op;
|
||||
size_t i_var;
|
||||
|
||||
const addr_t* arg = CPPAD_NULL;
|
||||
|
||||
// length of the parameter vector (used by CppAD assert macros)
|
||||
const size_t num_par = play->num_par_rec();
|
||||
|
||||
size_t i, j, k;
|
||||
|
||||
// check numvar argument
|
||||
size_t limit = n+1;
|
||||
CPPAD_ASSERT_UNKNOWN( play->num_var_rec() == numvar );
|
||||
CPPAD_ASSERT_UNKNOWN( for_jac_sparse.n_set() == numvar );
|
||||
CPPAD_ASSERT_UNKNOWN( for_hes_sparse.n_set() == limit );
|
||||
CPPAD_ASSERT_UNKNOWN( numvar > 0 );
|
||||
|
||||
// upper limit exclusive for set elements
|
||||
CPPAD_ASSERT_UNKNOWN( for_jac_sparse.end() == limit );
|
||||
CPPAD_ASSERT_UNKNOWN( for_hes_sparse.end() == limit );
|
||||
|
||||
// vecad_sparsity contains a sparsity pattern for each VecAD object.
|
||||
// vecad_ind maps a VecAD index (beginning of the VecAD object)
|
||||
// to the index for the corresponding set in vecad_sparsity.
|
||||
size_t num_vecad_ind = play->num_vec_ind_rec();
|
||||
size_t num_vecad_vec = play->num_vecad_vec_rec();
|
||||
Vector_set vecad_sparse;
|
||||
vecad_sparse.resize(num_vecad_vec, limit);
|
||||
pod_vector<size_t> vecad_ind;
|
||||
pod_vector<bool> vecad_jac;
|
||||
if( num_vecad_vec > 0 )
|
||||
{ size_t length;
|
||||
vecad_ind.extend(num_vecad_ind);
|
||||
vecad_jac.extend(num_vecad_vec);
|
||||
j = 0;
|
||||
for(i = 0; i < num_vecad_vec; i++)
|
||||
{ // length of this VecAD
|
||||
length = play->GetVecInd(j);
|
||||
// set vecad_ind to proper index for this VecAD
|
||||
vecad_ind[j] = i;
|
||||
// make all other values for this vector invalid
|
||||
for(k = 1; k <= length; k++)
|
||||
vecad_ind[j+k] = num_vecad_vec;
|
||||
// start of next VecAD
|
||||
j += length + 1;
|
||||
// initialize this vector's reverse jacobian value
|
||||
vecad_jac[i] = false;
|
||||
}
|
||||
CPPAD_ASSERT_UNKNOWN( j == play->num_vec_ind_rec() );
|
||||
}
|
||||
// ------------------------------------------------------------------------
|
||||
// user's atomic op calculator
|
||||
atomic_base<Base>* user_atom = CPPAD_NULL; // user's atomic op calculator
|
||||
//
|
||||
// work space used by UserOp.
|
||||
vector<Base> user_x; // value of parameter arguments to function
|
||||
vector<size_t> user_ix; // variable index (on tape) for each argument
|
||||
vector<size_t> user_iy; // variable index (on tape) for each result
|
||||
//
|
||||
// information set by forward_user (initialization to avoid warnings)
|
||||
size_t user_old=0, user_m=0, user_n=0, user_i=0, user_j=0;
|
||||
// information set by forward_user (necessary initialization)
|
||||
enum_user_state user_state = start_user;
|
||||
// -------------------------------------------------------------------------
|
||||
//
|
||||
// pointer to the beginning of the parameter vector
|
||||
// (used by user atomic functions)
|
||||
const Base* parameter = CPPAD_NULL;
|
||||
if( num_par > 0 )
|
||||
parameter = play->GetPar();
|
||||
|
||||
// Initialize
|
||||
play->forward_start(op, arg, i_op, i_var);
|
||||
CPPAD_ASSERT_UNKNOWN( op == BeginOp );
|
||||
bool more_operators = true;
|
||||
# if CPPAD_FOR_HES_SWEEP_TRACE
|
||||
vector<size_t> user_usrrp; // parameter index for UsrrpOp operators
|
||||
std::cout << std::endl;
|
||||
CppAD::vectorBool zf_value(limit);
|
||||
CppAD::vectorBool zh_value(limit * limit);
|
||||
# endif
|
||||
bool flag; // temporary for use in switch cases below
|
||||
while(more_operators)
|
||||
{
|
||||
// next op
|
||||
play->forward_next(op, arg, i_op, i_var);
|
||||
# ifndef NDEBUG
|
||||
if( i_op <= n )
|
||||
{ CPPAD_ASSERT_UNKNOWN((op == InvOp) | (op == BeginOp));
|
||||
}
|
||||
else CPPAD_ASSERT_UNKNOWN((op != InvOp) & (op != BeginOp));
|
||||
# endif
|
||||
|
||||
// does the Hessian in question have a non-zero derivative
|
||||
// with respect to this variable
|
||||
bool include = rev_jac_sparse.is_element(i_var, 0);
|
||||
//
|
||||
// operators to include even if derivative is zero
|
||||
include |= op == EndOp;
|
||||
include |= op == CSkipOp;
|
||||
include |= op == CSumOp;
|
||||
include |= op == UserOp;
|
||||
include |= op == UsrapOp;
|
||||
include |= op == UsravOp;
|
||||
include |= op == UsrrpOp;
|
||||
include |= op == UsrrvOp;
|
||||
//
|
||||
if( include ) switch( op )
|
||||
{ // operators that should not occurr
|
||||
// case BeginOp
|
||||
// -------------------------------------------------
|
||||
|
||||
// operators that do not affect hessian
|
||||
case AbsOp:
|
||||
case AddvvOp:
|
||||
case AddpvOp:
|
||||
case CExpOp:
|
||||
case DisOp:
|
||||
case DivvpOp:
|
||||
case InvOp:
|
||||
case LdpOp:
|
||||
case LdvOp:
|
||||
case MulpvOp:
|
||||
case ParOp:
|
||||
case PriOp:
|
||||
case SignOp:
|
||||
case StppOp:
|
||||
case StpvOp:
|
||||
case StvpOp:
|
||||
case StvvOp:
|
||||
case SubvvOp:
|
||||
case SubpvOp:
|
||||
case SubvpOp:
|
||||
case ZmulpvOp:
|
||||
case ZmulvpOp:
|
||||
break;
|
||||
// -------------------------------------------------
|
||||
|
||||
// nonlinear unary operators
|
||||
case AcosOp:
|
||||
case AsinOp:
|
||||
case AtanOp:
|
||||
case CosOp:
|
||||
case CoshOp:
|
||||
case ExpOp:
|
||||
case LogOp:
|
||||
case SinOp:
|
||||
case SinhOp:
|
||||
case SqrtOp:
|
||||
case TanOp:
|
||||
case TanhOp:
|
||||
# if CPPAD_USE_CPLUSPLUS_2011
|
||||
case AcoshOp:
|
||||
case AsinhOp:
|
||||
case AtanhOp:
|
||||
case Expm1Op:
|
||||
case Log1pOp:
|
||||
# endif
|
||||
CPPAD_ASSERT_UNKNOWN( NumArg(op) == 1 )
|
||||
forward_sparse_hessian_nonlinear_unary_op(
|
||||
arg[0], for_jac_sparse, for_hes_sparse
|
||||
);
|
||||
break;
|
||||
// -------------------------------------------------
|
||||
|
||||
case CSkipOp:
|
||||
// CSkipOp has a variable number of arguments and
|
||||
// reverse_next thinks it one has one argument.
|
||||
// We must inform reverse_next of this special case.
|
||||
play->forward_cskip(op, arg, i_op, i_var);
|
||||
break;
|
||||
// -------------------------------------------------
|
||||
|
||||
case CSumOp:
|
||||
// CSumOp has a variable number of arguments and
|
||||
// reverse_next thinks it one has one argument.
|
||||
// We must inform reverse_next of this special case.
|
||||
play->forward_csum(op, arg, i_op, i_var);
|
||||
break;
|
||||
// -------------------------------------------------
|
||||
|
||||
case DivvvOp:
|
||||
CPPAD_ASSERT_NARG_NRES(op, 2, 1)
|
||||
forward_sparse_hessian_div_op(
|
||||
arg, for_jac_sparse, for_hes_sparse
|
||||
);
|
||||
break;
|
||||
// -------------------------------------------------
|
||||
|
||||
case DivpvOp:
|
||||
CPPAD_ASSERT_NARG_NRES(op, 2, 1)
|
||||
forward_sparse_hessian_nonlinear_unary_op(
|
||||
arg[1], for_jac_sparse, for_hes_sparse
|
||||
);
|
||||
break;
|
||||
// -------------------------------------------------
|
||||
|
||||
case EndOp:
|
||||
CPPAD_ASSERT_NARG_NRES(op, 0, 0);
|
||||
more_operators = false;
|
||||
break;
|
||||
// -------------------------------------------------
|
||||
|
||||
case ErfOp:
|
||||
// arg[1] is always the parameter 0
|
||||
// arg[2] is always the parameter 2 / sqrt(pi)
|
||||
CPPAD_ASSERT_NARG_NRES(op, 3, 5);
|
||||
forward_sparse_hessian_nonlinear_unary_op(
|
||||
arg[0], for_jac_sparse, for_hes_sparse
|
||||
);
|
||||
break;
|
||||
// -------------------------------------------------
|
||||
|
||||
// -------------------------------------------------
|
||||
// logical comparision operators
|
||||
case EqpvOp:
|
||||
case EqvvOp:
|
||||
case LtpvOp:
|
||||
case LtvpOp:
|
||||
case LtvvOp:
|
||||
case LepvOp:
|
||||
case LevpOp:
|
||||
case LevvOp:
|
||||
case NepvOp:
|
||||
case NevvOp:
|
||||
CPPAD_ASSERT_NARG_NRES(op, 2, 0);
|
||||
break;
|
||||
// -------------------------------------------------
|
||||
|
||||
case MulvvOp:
|
||||
CPPAD_ASSERT_NARG_NRES(op, 2, 1)
|
||||
forward_sparse_hessian_mul_op(
|
||||
arg, for_jac_sparse, for_hes_sparse
|
||||
);
|
||||
break;
|
||||
// -------------------------------------------------
|
||||
|
||||
case PowpvOp:
|
||||
CPPAD_ASSERT_NARG_NRES(op, 2, 3)
|
||||
forward_sparse_hessian_nonlinear_unary_op(
|
||||
arg[1], for_jac_sparse, for_hes_sparse
|
||||
);
|
||||
break;
|
||||
// -------------------------------------------------
|
||||
|
||||
case PowvpOp:
|
||||
CPPAD_ASSERT_NARG_NRES(op, 2, 3)
|
||||
forward_sparse_hessian_nonlinear_unary_op(
|
||||
arg[0], for_jac_sparse, for_hes_sparse
|
||||
);
|
||||
break;
|
||||
// -------------------------------------------------
|
||||
|
||||
case PowvvOp:
|
||||
CPPAD_ASSERT_NARG_NRES(op, 2, 3)
|
||||
forward_sparse_hessian_pow_op(
|
||||
arg, for_jac_sparse, for_hes_sparse
|
||||
);
|
||||
break;
|
||||
// -------------------------------------------------
|
||||
|
||||
case UserOp:
|
||||
CPPAD_ASSERT_UNKNOWN(
|
||||
user_state == start_user || user_state == end_user
|
||||
);
|
||||
flag = user_state == start_user;
|
||||
user_atom = play->forward_user(op, user_state,
|
||||
user_old, user_m, user_n, user_i, user_j
|
||||
);
|
||||
if( flag )
|
||||
{ // start of user atomic operation sequence
|
||||
user_x.resize( user_n );
|
||||
user_ix.resize( user_n );
|
||||
user_iy.resize( user_m );
|
||||
# if CPPAD_FOR_HES_SWEEP_TRACE
|
||||
user_usrrp.resize( user_m );
|
||||
# endif
|
||||
}
|
||||
else
|
||||
{ // end of user atomic operation sequence
|
||||
user_atom->set_old(user_old);
|
||||
user_atom->for_sparse_hes(
|
||||
user_x, user_ix, user_iy,
|
||||
for_jac_sparse, rev_jac_sparse, for_hes_sparse
|
||||
);
|
||||
}
|
||||
break;
|
||||
|
||||
case UsrapOp:
|
||||
CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < num_par );
|
||||
// argument parameter value
|
||||
user_x[user_j] = parameter[arg[0]];
|
||||
// special variable user for parameters
|
||||
user_ix[user_j] = 0;
|
||||
//
|
||||
play->forward_user(op, user_state,
|
||||
user_old, user_m, user_n, user_i, user_j
|
||||
);
|
||||
break;
|
||||
|
||||
case UsravOp:
|
||||
CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) <= i_var );
|
||||
CPPAD_ASSERT_UNKNOWN( 0 < arg[0] );
|
||||
// arguemnt varialbes not avaialbe during sparisty calculations
|
||||
user_x[user_j] = CppAD::numeric_limits<Base>::quiet_NaN();
|
||||
// varialbe index for this argument
|
||||
user_ix[user_j] = arg[0];
|
||||
//
|
||||
play->forward_user(op, user_state,
|
||||
user_old, user_m, user_n, user_i, user_j
|
||||
);
|
||||
break;
|
||||
|
||||
case UsrrpOp:
|
||||
CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < num_par );
|
||||
// special variable index user for parameters
|
||||
user_iy[user_i] = 0;
|
||||
# if CPPAD_FOR_HES_SWEEP_TRACE
|
||||
// remember argument for delayed tracing
|
||||
user_usrrp[user_i] = arg[0];
|
||||
# endif
|
||||
//
|
||||
play->forward_user(op, user_state,
|
||||
user_old, user_m, user_n, user_i, user_j
|
||||
);
|
||||
break;
|
||||
|
||||
case UsrrvOp:
|
||||
// variable index for this result
|
||||
user_iy[user_i] = i_var;
|
||||
//
|
||||
play->forward_user(op, user_state,
|
||||
user_old, user_m, user_n, user_i, user_j
|
||||
);
|
||||
break;
|
||||
// -------------------------------------------------
|
||||
|
||||
case ZmulvvOp:
|
||||
CPPAD_ASSERT_NARG_NRES(op, 2, 1)
|
||||
forward_sparse_hessian_mul_op(
|
||||
arg, for_jac_sparse, for_hes_sparse
|
||||
);
|
||||
break;
|
||||
|
||||
// -------------------------------------------------
|
||||
|
||||
default:
|
||||
CPPAD_ASSERT_UNKNOWN(0);
|
||||
}
|
||||
# if CPPAD_FOR_HES_SWEEP_TRACE
|
||||
typedef typename Vector_set::const_iterator const_iterator;
|
||||
if( op == UserOp && user_state == start_user )
|
||||
{ // print operators that have been delayed
|
||||
CPPAD_ASSERT_UNKNOWN( user_m == user_iy.size() );
|
||||
CPPAD_ASSERT_UNKNOWN( i_op > user_m );
|
||||
CPPAD_ASSERT_NARG_NRES(UsrrpOp, 1, 0);
|
||||
CPPAD_ASSERT_NARG_NRES(UsrrvOp, 0, 1);
|
||||
addr_t arg_tmp[1];
|
||||
for(k = 0; k < user_m; k++)
|
||||
{ size_t k_var = user_iy[k];
|
||||
// value for this variable
|
||||
for(i = 0; i < limit; i++)
|
||||
{ zf_value[i] = false;
|
||||
for(j = 0; j < limit; j++)
|
||||
zh_value[i * limit + j] = false;
|
||||
}
|
||||
const_iterator itr_1(for_jac_sparse, i_var);
|
||||
j = *itr_1;
|
||||
while( j < limit )
|
||||
{ zf_value[j] = true;
|
||||
j = *(++itr_1);
|
||||
}
|
||||
for(i = 0; i < limit; i++)
|
||||
{ const_iterator itr_2(for_hes_sparse, i);
|
||||
j = *itr_2;
|
||||
while( j < limit )
|
||||
{ zh_value[i * limit + j] = true;
|
||||
j = *(++itr_2);
|
||||
}
|
||||
}
|
||||
OpCode op_tmp = UsrrvOp;
|
||||
if( k_var == 0 )
|
||||
{ op_tmp = UsrrpOp;
|
||||
arg_tmp[0] = user_usrrp[k];
|
||||
}
|
||||
// k_var is zero when there is no result
|
||||
printOp(
|
||||
std::cout,
|
||||
play,
|
||||
i_op - user_m + k,
|
||||
k_var,
|
||||
op_tmp,
|
||||
arg_tmp
|
||||
);
|
||||
if( k_var > 0 ) printOpResult(
|
||||
std::cout,
|
||||
1,
|
||||
&zf_value,
|
||||
1,
|
||||
&zh_value
|
||||
);
|
||||
std::cout << std::endl;
|
||||
}
|
||||
}
|
||||
const addr_t* arg_tmp = arg;
|
||||
if( op == CSumOp )
|
||||
arg_tmp = arg - arg[-1] - 4;
|
||||
if( op == CSkipOp )
|
||||
arg_tmp = arg - arg[-1] - 7;
|
||||
for(i = 0; i < limit; i++)
|
||||
{ zf_value[i] = false;
|
||||
for(j = 0; j < limit; j++)
|
||||
zh_value[i * limit + j] = false;
|
||||
}
|
||||
const_iterator itr_1(for_jac_sparse, i_var);
|
||||
j = *itr_1;
|
||||
while( j < limit )
|
||||
{ zf_value[j] = true;
|
||||
j = *(++itr_1);
|
||||
}
|
||||
for(i = 0; i < limit; i++)
|
||||
{ const_iterator itr_2(for_hes_sparse, i);
|
||||
j = *itr_2;
|
||||
while( j < limit )
|
||||
{ zh_value[i * limit + j] = true;
|
||||
j = *(++itr_2);
|
||||
}
|
||||
}
|
||||
// must delay print for these cases till after atomic user call
|
||||
bool delay_print = op == UsrrpOp;
|
||||
delay_print |= op == UsrrvOp;
|
||||
if( ! delay_print )
|
||||
{ printOp(
|
||||
std::cout,
|
||||
play,
|
||||
i_op,
|
||||
i_var,
|
||||
op,
|
||||
arg_tmp
|
||||
);
|
||||
if( NumRes(op) > 0 && (! delay_print) ) printOpResult(
|
||||
std::cout,
|
||||
1,
|
||||
&zf_value,
|
||||
1,
|
||||
&zh_value
|
||||
);
|
||||
std::cout << std::endl;
|
||||
}
|
||||
}
|
||||
std::cout << std::endl;
|
||||
# else
|
||||
}
|
||||
# endif
|
||||
// value corresponding to EndOp
|
||||
CPPAD_ASSERT_UNKNOWN( i_var + 1 == play->num_var_rec() );
|
||||
|
||||
return;
|
||||
}
|
||||
} } // END_CPPAD_LOCAL_NAMESPACE
|
||||
|
||||
// preprocessor symbols that are local to this file
|
||||
# undef CPPAD_FOR_HES_SWEEP_TRACE
|
||||
|
||||
# endif
|
||||
@@ -0,0 +1,815 @@
|
||||
# ifndef CPPAD_LOCAL_FOR_JAC_SWEEP_HPP
|
||||
# define CPPAD_LOCAL_FOR_JAC_SWEEP_HPP
|
||||
/* --------------------------------------------------------------------------
|
||||
CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-17 Bradley M. Bell
|
||||
|
||||
CppAD is distributed under multiple licenses. This distribution is under
|
||||
the terms of the
|
||||
Eclipse Public License Version 1.0.
|
||||
|
||||
A copy of this license is included in the COPYING file of this distribution.
|
||||
Please visit http://www.coin-or.org/CppAD/ for information on other licenses.
|
||||
-------------------------------------------------------------------------- */
|
||||
|
||||
# include <set>
|
||||
# include <cppad/local/pod_vector.hpp>
|
||||
|
||||
namespace CppAD { namespace local { // BEGIN_CPPAD_LOCAL_NAMESPACE
|
||||
/*!
|
||||
\file for_jac_sweep.hpp
|
||||
Compute Forward mode Jacobian sparsity patterns.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\def CPPAD_FOR_JAC_SWEEP_TRACE
|
||||
This value is either zero or one.
|
||||
Zero is the normal operational value.
|
||||
If it is one, a trace of every for_jac_sweep computation is printed.
|
||||
*/
|
||||
# define CPPAD_FOR_JAC_SWEEP_TRACE 0
|
||||
|
||||
/*!
|
||||
Given the sparsity pattern for the independent variables,
|
||||
ForJacSweep computes the sparsity pattern for all the other variables.
|
||||
|
||||
\tparam Base
|
||||
base type for the operator; i.e., this operation sequence was recorded
|
||||
using AD< \a Base > and computations by this routine are done using type
|
||||
\a Base.
|
||||
|
||||
\tparam Vector_set
|
||||
is the type used for vectors of sets. It can be either
|
||||
sparse_pack or sparse_list.
|
||||
|
||||
\param dependency
|
||||
Are the derivatives with respect to left and right of the expression below
|
||||
considered to be non-zero:
|
||||
\code
|
||||
CondExpRel(left, right, if_true, if_false)
|
||||
\endcode
|
||||
This is used by the optimizer to obtain the correct dependency relations.
|
||||
|
||||
\param n
|
||||
is the number of independent variables on the tape.
|
||||
|
||||
\param numvar
|
||||
is the total number of variables on the tape; i.e.,
|
||||
\a play->num_var_rec().
|
||||
|
||||
\param play
|
||||
The information stored in \a play
|
||||
is a recording of the operations corresponding to a function
|
||||
\f[
|
||||
F : {\bf R}^n \rightarrow {\bf R}^m
|
||||
\f]
|
||||
where \f$ n \f$ is the number of independent variables
|
||||
and \f$ m \f$ is the number of dependent variables.
|
||||
The object \a play is effectly constant.
|
||||
It is not declared const because while playing back the tape
|
||||
the object \a play holds information about the current location
|
||||
with in the tape and this changes during playback.
|
||||
|
||||
\param var_sparsity
|
||||
\b Input: For j = 1 , ... , \a n,
|
||||
the sparsity pattern for the independent variable with index (j-1)
|
||||
corresponds to the set with index j in \a var_sparsity.
|
||||
\n
|
||||
\n
|
||||
\b Output: For i = \a n + 1 , ... , \a numvar - 1,
|
||||
the sparsity pattern for the variable with index i on the tape
|
||||
corresponds to the set with index i in \a var_sparsity.
|
||||
|
||||
\par Checked Assertions:
|
||||
\li numvar == var_sparsity.n_set()
|
||||
\li numvar == play->num_var_rec()
|
||||
*/
|
||||
|
||||
template <class Base, class Vector_set>
|
||||
void ForJacSweep(
|
||||
bool dependency ,
|
||||
size_t n ,
|
||||
size_t numvar ,
|
||||
local::player<Base>* play ,
|
||||
Vector_set& var_sparsity )
|
||||
{
|
||||
OpCode op;
|
||||
size_t i_op;
|
||||
size_t i_var;
|
||||
|
||||
const addr_t* arg = CPPAD_NULL;
|
||||
|
||||
size_t i, j, k;
|
||||
|
||||
// check numvar argument
|
||||
CPPAD_ASSERT_UNKNOWN( play->num_var_rec() == numvar );
|
||||
CPPAD_ASSERT_UNKNOWN( var_sparsity.n_set() == numvar );
|
||||
|
||||
// length of the parameter vector (used by CppAD assert macros)
|
||||
const size_t num_par = play->num_par_rec();
|
||||
|
||||
// cum_sparsity accumulates sparsity pattern a cummulative sum
|
||||
size_t limit = var_sparsity.end();
|
||||
|
||||
// vecad_sparsity contains a sparsity pattern from each VecAD object
|
||||
// to all the other variables.
|
||||
// vecad_ind maps a VecAD index (the beginning of the
|
||||
// VecAD object) to its from index in vecad_sparsity
|
||||
size_t num_vecad_ind = play->num_vec_ind_rec();
|
||||
size_t num_vecad_vec = play->num_vecad_vec_rec();
|
||||
Vector_set vecad_sparsity;
|
||||
vecad_sparsity.resize(num_vecad_vec, limit);
|
||||
pod_vector<size_t> vecad_ind;
|
||||
if( num_vecad_vec > 0 )
|
||||
{ size_t length;
|
||||
vecad_ind.extend(num_vecad_ind);
|
||||
j = 0;
|
||||
for(i = 0; i < num_vecad_vec; i++)
|
||||
{ // length of this VecAD
|
||||
length = play->GetVecInd(j);
|
||||
// set to proper index for this VecAD
|
||||
vecad_ind[j] = i;
|
||||
for(k = 1; k <= length; k++)
|
||||
vecad_ind[j+k] = num_vecad_vec; // invalid index
|
||||
// start of next VecAD
|
||||
j += length + 1;
|
||||
}
|
||||
CPPAD_ASSERT_UNKNOWN( j == play->num_vec_ind_rec() );
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------
|
||||
// user's atomic op calculator
|
||||
atomic_base<Base>* user_atom = CPPAD_NULL;
|
||||
//
|
||||
// work space used by UserOp.
|
||||
vector<Base> user_x; // value of parameter arguments to function
|
||||
vector<size_t> user_ix; // variable index (on tape) for each argument
|
||||
vector<size_t> user_iy; // variable index (on tape) for each result
|
||||
//
|
||||
// information set by forward_user (initialization to avoid warnings)
|
||||
size_t user_old=0, user_m=0, user_n=0, user_i=0, user_j=0;
|
||||
// information set by forward_user (necessary initialization)
|
||||
enum_user_state user_state = start_user;
|
||||
// --------------------------------------------------------------
|
||||
//
|
||||
// pointer to the beginning of the parameter vector
|
||||
// (used by user atomic functions)
|
||||
const Base* parameter = CPPAD_NULL;
|
||||
if( num_par > 0 )
|
||||
parameter = play->GetPar();
|
||||
|
||||
# if CPPAD_FOR_JAC_SWEEP_TRACE
|
||||
vector<size_t> user_usrrp; // parameter index for UsrrpOp operators
|
||||
std::cout << std::endl;
|
||||
CppAD::vectorBool z_value(limit);
|
||||
# endif
|
||||
|
||||
// skip the BeginOp at the beginning of the recording
|
||||
play->forward_start(op, arg, i_op, i_var);
|
||||
CPPAD_ASSERT_UNKNOWN( op == BeginOp );
|
||||
bool more_operators = true;
|
||||
while(more_operators)
|
||||
{ bool flag; // temporary for use in switch cases.
|
||||
|
||||
// this op
|
||||
play->forward_next(op, arg, i_op, i_var);
|
||||
CPPAD_ASSERT_UNKNOWN( (i_op > n) | (op == InvOp) );
|
||||
CPPAD_ASSERT_UNKNOWN( (i_op <= n) | (op != InvOp) );
|
||||
CPPAD_ASSERT_ARG_BEFORE_RESULT(op, arg, i_var);
|
||||
|
||||
// rest of information depends on the case
|
||||
switch( op )
|
||||
{
|
||||
case AbsOp:
|
||||
CPPAD_ASSERT_NARG_NRES(op, 1, 1);
|
||||
forward_sparse_jacobian_unary_op(
|
||||
i_var, arg[0], var_sparsity
|
||||
);
|
||||
break;
|
||||
// -------------------------------------------------
|
||||
|
||||
case AddvvOp:
|
||||
CPPAD_ASSERT_NARG_NRES(op, 2, 1);
|
||||
forward_sparse_jacobian_binary_op(
|
||||
i_var, arg, var_sparsity
|
||||
);
|
||||
break;
|
||||
// -------------------------------------------------
|
||||
|
||||
case AddpvOp:
|
||||
CPPAD_ASSERT_NARG_NRES(op, 2, 1);
|
||||
forward_sparse_jacobian_unary_op(
|
||||
i_var, arg[1], var_sparsity
|
||||
);
|
||||
break;
|
||||
// -------------------------------------------------
|
||||
|
||||
case AcosOp:
|
||||
// sqrt(1 - x * x), acos(x)
|
||||
CPPAD_ASSERT_NARG_NRES(op, 1, 2);
|
||||
forward_sparse_jacobian_unary_op(
|
||||
i_var, arg[0], var_sparsity
|
||||
);
|
||||
break;
|
||||
// -------------------------------------------------
|
||||
|
||||
# if CPPAD_USE_CPLUSPLUS_2011
|
||||
case AcoshOp:
|
||||
// sqrt(x * x - 1), acosh(x)
|
||||
CPPAD_ASSERT_NARG_NRES(op, 1, 2);
|
||||
forward_sparse_jacobian_unary_op(
|
||||
i_var, arg[0], var_sparsity
|
||||
);
|
||||
break;
|
||||
# endif
|
||||
// -------------------------------------------------
|
||||
|
||||
case AsinOp:
|
||||
// sqrt(1 - x * x), asin(x)
|
||||
CPPAD_ASSERT_NARG_NRES(op, 1, 2);
|
||||
forward_sparse_jacobian_unary_op(
|
||||
i_var, arg[0], var_sparsity
|
||||
);
|
||||
break;
|
||||
// -------------------------------------------------
|
||||
|
||||
# if CPPAD_USE_CPLUSPLUS_2011
|
||||
case AsinhOp:
|
||||
// sqrt(1 + x * x), asinh(x)
|
||||
CPPAD_ASSERT_NARG_NRES(op, 1, 2);
|
||||
forward_sparse_jacobian_unary_op(
|
||||
i_var, arg[0], var_sparsity
|
||||
);
|
||||
break;
|
||||
# endif
|
||||
// -------------------------------------------------
|
||||
|
||||
case AtanOp:
|
||||
// 1 + x * x, atan(x)
|
||||
CPPAD_ASSERT_NARG_NRES(op, 1, 2);
|
||||
forward_sparse_jacobian_unary_op(
|
||||
i_var, arg[0], var_sparsity
|
||||
);
|
||||
break;
|
||||
// -------------------------------------------------
|
||||
|
||||
# if CPPAD_USE_CPLUSPLUS_2011
|
||||
case AtanhOp:
|
||||
// 1 - x * x, atanh(x)
|
||||
CPPAD_ASSERT_NARG_NRES(op, 1, 2);
|
||||
forward_sparse_jacobian_unary_op(
|
||||
i_var, arg[0], var_sparsity
|
||||
);
|
||||
break;
|
||||
# endif
|
||||
// -------------------------------------------------
|
||||
|
||||
case CSkipOp:
|
||||
// CSipOp has a variable number of arguments and
|
||||
// forward_next thinks it has no arguments.
|
||||
// we must inform forward_next of this special case.
|
||||
play->forward_cskip(op, arg, i_op, i_var);
|
||||
break;
|
||||
// -------------------------------------------------
|
||||
|
||||
case CSumOp:
|
||||
// CSumOp has a variable number of arguments and
|
||||
// forward_next thinks it has no arguments.
|
||||
// we must inform forward_next of this special case.
|
||||
forward_sparse_jacobian_csum_op(
|
||||
i_var, arg, var_sparsity
|
||||
);
|
||||
play->forward_csum(op, arg, i_op, i_var);
|
||||
break;
|
||||
// -------------------------------------------------
|
||||
|
||||
case CExpOp:
|
||||
forward_sparse_jacobian_cond_op(
|
||||
dependency, i_var, arg, num_par, var_sparsity
|
||||
);
|
||||
break;
|
||||
// --------------------------------------------------
|
||||
|
||||
case CosOp:
|
||||
// sin(x), cos(x)
|
||||
CPPAD_ASSERT_NARG_NRES(op, 1, 2);
|
||||
forward_sparse_jacobian_unary_op(
|
||||
i_var, arg[0], var_sparsity
|
||||
);
|
||||
break;
|
||||
// ---------------------------------------------------
|
||||
|
||||
case CoshOp:
|
||||
// sinh(x), cosh(x)
|
||||
CPPAD_ASSERT_NARG_NRES(op, 1, 2);
|
||||
forward_sparse_jacobian_unary_op(
|
||||
i_var, arg[0], var_sparsity
|
||||
);
|
||||
break;
|
||||
// -------------------------------------------------
|
||||
|
||||
case DisOp:
|
||||
CPPAD_ASSERT_NARG_NRES(op, 2, 1);
|
||||
// derivative is identically zero but dependency is not
|
||||
if( dependency ) forward_sparse_jacobian_unary_op(
|
||||
i_var, arg[1], var_sparsity
|
||||
);
|
||||
else
|
||||
var_sparsity.clear(i_var);
|
||||
break;
|
||||
// -------------------------------------------------
|
||||
|
||||
case DivvvOp:
|
||||
CPPAD_ASSERT_NARG_NRES(op, 2, 1);
|
||||
forward_sparse_jacobian_binary_op(
|
||||
i_var, arg, var_sparsity
|
||||
);
|
||||
break;
|
||||
// -------------------------------------------------
|
||||
|
||||
case DivpvOp:
|
||||
CPPAD_ASSERT_NARG_NRES(op, 2, 1);
|
||||
forward_sparse_jacobian_unary_op(
|
||||
i_var, arg[1], var_sparsity
|
||||
);
|
||||
break;
|
||||
// -------------------------------------------------
|
||||
|
||||
case DivvpOp:
|
||||
CPPAD_ASSERT_NARG_NRES(op, 2, 1);
|
||||
forward_sparse_jacobian_unary_op(
|
||||
i_var, arg[0], var_sparsity
|
||||
);
|
||||
break;
|
||||
// -------------------------------------------------
|
||||
|
||||
case EndOp:
|
||||
CPPAD_ASSERT_NARG_NRES(op, 0, 0);
|
||||
more_operators = false;
|
||||
break;
|
||||
// -------------------------------------------------
|
||||
|
||||
case ErfOp:
|
||||
// arg[1] is always the parameter 0
|
||||
// arg[0] is always the parameter 2 / sqrt(pi)
|
||||
CPPAD_ASSERT_NARG_NRES(op, 3, 5);
|
||||
forward_sparse_jacobian_unary_op(
|
||||
i_var, arg[0], var_sparsity
|
||||
);
|
||||
break;
|
||||
// -------------------------------------------------
|
||||
|
||||
case ExpOp:
|
||||
CPPAD_ASSERT_NARG_NRES(op, 1, 1);
|
||||
forward_sparse_jacobian_unary_op(
|
||||
i_var, arg[0], var_sparsity
|
||||
);
|
||||
break;
|
||||
// -------------------------------------------------
|
||||
|
||||
# if CPPAD_USE_CPLUSPLUS_2011
|
||||
case Expm1Op:
|
||||
CPPAD_ASSERT_NARG_NRES(op, 1, 1);
|
||||
forward_sparse_jacobian_unary_op(
|
||||
i_var, arg[0], var_sparsity
|
||||
);
|
||||
break;
|
||||
# endif
|
||||
// -------------------------------------------------
|
||||
|
||||
case InvOp:
|
||||
CPPAD_ASSERT_NARG_NRES(op, 0, 1);
|
||||
// sparsity pattern is already defined
|
||||
break;
|
||||
// -------------------------------------------------
|
||||
|
||||
case LdpOp:
|
||||
forward_sparse_load_op(
|
||||
dependency,
|
||||
op,
|
||||
i_var,
|
||||
arg,
|
||||
num_vecad_ind,
|
||||
vecad_ind.data(),
|
||||
var_sparsity,
|
||||
vecad_sparsity
|
||||
);
|
||||
break;
|
||||
// -------------------------------------------------
|
||||
|
||||
case LdvOp:
|
||||
forward_sparse_load_op(
|
||||
dependency,
|
||||
op,
|
||||
i_var,
|
||||
arg,
|
||||
num_vecad_ind,
|
||||
vecad_ind.data(),
|
||||
var_sparsity,
|
||||
vecad_sparsity
|
||||
);
|
||||
break;
|
||||
// -------------------------------------------------
|
||||
|
||||
case EqpvOp:
|
||||
case EqvvOp:
|
||||
case LtpvOp:
|
||||
case LtvpOp:
|
||||
case LtvvOp:
|
||||
case LepvOp:
|
||||
case LevpOp:
|
||||
case LevvOp:
|
||||
case NepvOp:
|
||||
case NevvOp:
|
||||
CPPAD_ASSERT_NARG_NRES(op, 2, 0);
|
||||
break;
|
||||
// -------------------------------------------------
|
||||
|
||||
case LogOp:
|
||||
CPPAD_ASSERT_NARG_NRES(op, 1, 1);
|
||||
forward_sparse_jacobian_unary_op(
|
||||
i_var, arg[0], var_sparsity
|
||||
);
|
||||
break;
|
||||
// -------------------------------------------------
|
||||
|
||||
# if CPPAD_USE_CPLUSPLUS_2011
|
||||
case Log1pOp:
|
||||
CPPAD_ASSERT_NARG_NRES(op, 1, 1);
|
||||
forward_sparse_jacobian_unary_op(
|
||||
i_var, arg[0], var_sparsity
|
||||
);
|
||||
break;
|
||||
# endif
|
||||
// -------------------------------------------------
|
||||
|
||||
case MulpvOp:
|
||||
CPPAD_ASSERT_NARG_NRES(op, 2, 1);
|
||||
forward_sparse_jacobian_unary_op(
|
||||
i_var, arg[1], var_sparsity
|
||||
);
|
||||
break;
|
||||
// -------------------------------------------------
|
||||
|
||||
case MulvvOp:
|
||||
CPPAD_ASSERT_NARG_NRES(op, 2, 1);
|
||||
forward_sparse_jacobian_binary_op(
|
||||
i_var, arg, var_sparsity
|
||||
);
|
||||
break;
|
||||
// -------------------------------------------------
|
||||
|
||||
case ParOp:
|
||||
CPPAD_ASSERT_NARG_NRES(op, 1, 1);
|
||||
var_sparsity.clear(i_var);
|
||||
break;
|
||||
// -------------------------------------------------
|
||||
|
||||
case PowvpOp:
|
||||
CPPAD_ASSERT_NARG_NRES(op, 2, 3);
|
||||
forward_sparse_jacobian_unary_op(
|
||||
i_var, arg[0], var_sparsity
|
||||
);
|
||||
break;
|
||||
// -------------------------------------------------
|
||||
|
||||
case PowpvOp:
|
||||
CPPAD_ASSERT_NARG_NRES(op, 2, 3);
|
||||
forward_sparse_jacobian_unary_op(
|
||||
i_var, arg[1], var_sparsity
|
||||
);
|
||||
break;
|
||||
// -------------------------------------------------
|
||||
|
||||
case PowvvOp:
|
||||
CPPAD_ASSERT_NARG_NRES(op, 2, 3);
|
||||
forward_sparse_jacobian_binary_op(
|
||||
i_var, arg, var_sparsity
|
||||
);
|
||||
break;
|
||||
// -------------------------------------------------
|
||||
|
||||
case PriOp:
|
||||
CPPAD_ASSERT_NARG_NRES(op, 5, 0);
|
||||
break;
|
||||
// -------------------------------------------------
|
||||
|
||||
case SignOp:
|
||||
CPPAD_ASSERT_NARG_NRES(op, 1, 1);
|
||||
// derivative is identically zero but dependency is not
|
||||
if( dependency ) forward_sparse_jacobian_unary_op(
|
||||
i_var, arg[0], var_sparsity
|
||||
);
|
||||
else
|
||||
var_sparsity.clear(i_var);
|
||||
break;
|
||||
// -------------------------------------------------
|
||||
|
||||
case SinOp:
|
||||
// cos(x), sin(x)
|
||||
CPPAD_ASSERT_NARG_NRES(op, 1, 2);
|
||||
forward_sparse_jacobian_unary_op(
|
||||
i_var, arg[0], var_sparsity
|
||||
);
|
||||
break;
|
||||
// -------------------------------------------------
|
||||
|
||||
case SinhOp:
|
||||
// cosh(x), sinh(x)
|
||||
CPPAD_ASSERT_NARG_NRES(op, 1, 2);
|
||||
forward_sparse_jacobian_unary_op(
|
||||
i_var, arg[0], var_sparsity
|
||||
);
|
||||
break;
|
||||
// -------------------------------------------------
|
||||
|
||||
case SqrtOp:
|
||||
CPPAD_ASSERT_NARG_NRES(op, 1, 1);
|
||||
forward_sparse_jacobian_unary_op(
|
||||
i_var, arg[0], var_sparsity
|
||||
);
|
||||
break;
|
||||
// -------------------------------------------------
|
||||
|
||||
case StppOp:
|
||||
CPPAD_ASSERT_NARG_NRES(op, 3, 0);
|
||||
// if both arguments are parameters does not affect sparsity
|
||||
// or dependency
|
||||
break;
|
||||
// -------------------------------------------------
|
||||
|
||||
case StpvOp:
|
||||
forward_sparse_store_op(
|
||||
dependency,
|
||||
op,
|
||||
arg,
|
||||
num_vecad_ind,
|
||||
vecad_ind.data(),
|
||||
var_sparsity,
|
||||
vecad_sparsity
|
||||
);
|
||||
break;
|
||||
// -------------------------------------------------
|
||||
|
||||
case StvpOp:
|
||||
CPPAD_ASSERT_NARG_NRES(op, 3, 0);
|
||||
forward_sparse_store_op(
|
||||
dependency,
|
||||
op,
|
||||
arg,
|
||||
num_vecad_ind,
|
||||
vecad_ind.data(),
|
||||
var_sparsity,
|
||||
vecad_sparsity
|
||||
);
|
||||
break;
|
||||
// -------------------------------------------------
|
||||
|
||||
case StvvOp:
|
||||
forward_sparse_store_op(
|
||||
dependency,
|
||||
op,
|
||||
arg,
|
||||
num_vecad_ind,
|
||||
vecad_ind.data(),
|
||||
var_sparsity,
|
||||
vecad_sparsity
|
||||
);
|
||||
break;
|
||||
// -------------------------------------------------
|
||||
|
||||
case SubvvOp:
|
||||
CPPAD_ASSERT_NARG_NRES(op, 2, 1);
|
||||
forward_sparse_jacobian_binary_op(
|
||||
i_var, arg, var_sparsity
|
||||
);
|
||||
break;
|
||||
// -------------------------------------------------
|
||||
|
||||
case SubpvOp:
|
||||
CPPAD_ASSERT_NARG_NRES(op, 2, 1);
|
||||
forward_sparse_jacobian_unary_op(
|
||||
i_var, arg[1], var_sparsity
|
||||
);
|
||||
break;
|
||||
// -------------------------------------------------
|
||||
|
||||
case SubvpOp:
|
||||
CPPAD_ASSERT_NARG_NRES(op, 2, 1);
|
||||
forward_sparse_jacobian_unary_op(
|
||||
i_var, arg[0], var_sparsity
|
||||
);
|
||||
break;
|
||||
// -------------------------------------------------
|
||||
|
||||
case TanOp:
|
||||
// tan(x)^2, tan(x)
|
||||
CPPAD_ASSERT_NARG_NRES(op, 1, 2);
|
||||
forward_sparse_jacobian_unary_op(
|
||||
i_var, arg[0], var_sparsity
|
||||
);
|
||||
break;
|
||||
// -------------------------------------------------
|
||||
|
||||
case TanhOp:
|
||||
// tanh(x)^2, tanh(x)
|
||||
CPPAD_ASSERT_NARG_NRES(op, 1, 2);
|
||||
forward_sparse_jacobian_unary_op(
|
||||
i_var, arg[0], var_sparsity
|
||||
);
|
||||
break;
|
||||
// -------------------------------------------------
|
||||
|
||||
case UserOp:
|
||||
CPPAD_ASSERT_UNKNOWN(
|
||||
user_state == start_user || user_state == end_user
|
||||
);
|
||||
flag = user_state == start_user;
|
||||
user_atom = play->forward_user(op, user_state,
|
||||
user_old, user_m, user_n, user_i, user_j
|
||||
);
|
||||
if( flag )
|
||||
{ // start of user atomic operation sequence
|
||||
user_x.resize( user_n );
|
||||
user_ix.resize( user_n );
|
||||
user_iy.resize( user_m );
|
||||
# if CPPAD_FOR_JAC_SWEEP_TRACE
|
||||
user_usrrp.resize( user_m );
|
||||
# endif
|
||||
}
|
||||
else
|
||||
{ // end of user atomic operation sequence
|
||||
user_atom->set_old(user_old);
|
||||
user_atom->for_sparse_jac(
|
||||
user_x, user_ix, user_iy, var_sparsity
|
||||
);
|
||||
}
|
||||
break;
|
||||
|
||||
case UsrapOp:
|
||||
CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < num_par );
|
||||
// argument parameter value
|
||||
user_x[user_j] = parameter[arg[0]];
|
||||
// special variable index used for parameters
|
||||
user_ix[user_j] = 0;
|
||||
//
|
||||
play->forward_user(op, user_state,
|
||||
user_old, user_m, user_n, user_i, user_j
|
||||
);
|
||||
break;
|
||||
|
||||
case UsravOp:
|
||||
CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) <= i_var );
|
||||
CPPAD_ASSERT_UNKNOWN( 0 < arg[0] );
|
||||
// argument variables not avaiable during sparsity calculations
|
||||
user_x[user_j] = CppAD::numeric_limits<Base>::quiet_NaN();
|
||||
// variable index for this argument
|
||||
user_ix[user_j] = arg[0];
|
||||
//
|
||||
play->forward_user(op, user_state,
|
||||
user_old, user_m, user_n, user_i, user_j
|
||||
);
|
||||
break;
|
||||
|
||||
case UsrrpOp:
|
||||
// special variable index used for parameters
|
||||
user_iy[user_i] = 0;
|
||||
# if CPPAD_FOR_JAC_SWEEP_TRACE
|
||||
// remember argument for delayed tracing
|
||||
user_usrrp[user_i] = arg[0];
|
||||
# endif
|
||||
play->forward_user(op, user_state,
|
||||
user_old, user_m, user_n, user_i, user_j
|
||||
);
|
||||
break;
|
||||
|
||||
case UsrrvOp:
|
||||
// variable index for this result
|
||||
user_iy[user_i] = i_var;
|
||||
play->forward_user(op, user_state,
|
||||
user_old, user_m, user_n, user_i, user_j
|
||||
);
|
||||
break;
|
||||
// -------------------------------------------------
|
||||
|
||||
case ZmulpvOp:
|
||||
CPPAD_ASSERT_NARG_NRES(op, 2, 1);
|
||||
forward_sparse_jacobian_unary_op(
|
||||
i_var, arg[1], var_sparsity
|
||||
);
|
||||
break;
|
||||
// -------------------------------------------------
|
||||
|
||||
case ZmulvpOp:
|
||||
CPPAD_ASSERT_NARG_NRES(op, 2, 1);
|
||||
forward_sparse_jacobian_unary_op(
|
||||
i_var, arg[0], var_sparsity
|
||||
);
|
||||
break;
|
||||
// -------------------------------------------------
|
||||
|
||||
case ZmulvvOp:
|
||||
CPPAD_ASSERT_NARG_NRES(op, 2, 1);
|
||||
forward_sparse_jacobian_binary_op(
|
||||
i_var, arg, var_sparsity
|
||||
);
|
||||
break;
|
||||
// -------------------------------------------------
|
||||
|
||||
default:
|
||||
CPPAD_ASSERT_UNKNOWN(0);
|
||||
}
|
||||
# if CPPAD_FOR_JAC_SWEEP_TRACE
|
||||
if( op == UserOp && user_state == start_user )
|
||||
{ // print operators that have been delayed
|
||||
CPPAD_ASSERT_UNKNOWN( user_m == user_iy.size() );
|
||||
CPPAD_ASSERT_UNKNOWN( i_op > user_m );
|
||||
CPPAD_ASSERT_NARG_NRES(UsrrpOp, 1, 0);
|
||||
CPPAD_ASSERT_NARG_NRES(UsrrvOp, 0, 1);
|
||||
addr_t arg_tmp[1];
|
||||
for(i = 0; i < user_m; i++)
|
||||
{ size_t j_var = user_iy[i];
|
||||
// value for this variable
|
||||
for(j = 0; j < limit; j++)
|
||||
z_value[j] = false;
|
||||
typename Vector_set::const_iterator itr(var_sparsity, j_var);
|
||||
j = *itr;
|
||||
while( j < limit )
|
||||
{ z_value[j] = true;
|
||||
j = *(++itr);
|
||||
}
|
||||
OpCode op_tmp = UsrrvOp;
|
||||
if( j_var == 0 )
|
||||
{ op_tmp = UsrrpOp;
|
||||
arg_tmp[0] = user_usrrp[i];
|
||||
}
|
||||
// j_var is zero when there is no result.
|
||||
printOp(
|
||||
std::cout,
|
||||
play,
|
||||
i_op - user_m + i,
|
||||
j_var,
|
||||
op_tmp,
|
||||
arg_tmp
|
||||
);
|
||||
if( j_var > 0 ) printOpResult(
|
||||
std::cout,
|
||||
1,
|
||||
&z_value,
|
||||
0,
|
||||
(CppAD::vectorBool *) CPPAD_NULL
|
||||
);
|
||||
std::cout << std::endl;
|
||||
}
|
||||
}
|
||||
const addr_t* arg_tmp = arg;
|
||||
if( op == CSumOp )
|
||||
arg_tmp = arg - arg[-1] - 4;
|
||||
if( op == CSkipOp )
|
||||
arg_tmp = arg - arg[-1] - 7;
|
||||
//
|
||||
// value for this variable
|
||||
for(j = 0; j < limit; j++)
|
||||
z_value[j] = false;
|
||||
typename Vector_set::const_iterator itr(var_sparsity, i_var);
|
||||
j = *itr;
|
||||
while( j < limit )
|
||||
{ z_value[j] = true;
|
||||
j = *(++itr);
|
||||
}
|
||||
// must delay print for these cases till after atomic user call
|
||||
bool delay_print = op == UsrrpOp;
|
||||
delay_print |= op == UsrrvOp;
|
||||
if( ! delay_print )
|
||||
{ printOp(
|
||||
std::cout,
|
||||
play,
|
||||
i_op,
|
||||
i_var,
|
||||
op,
|
||||
arg_tmp
|
||||
);
|
||||
if( NumRes(op) > 0 && (! delay_print) ) printOpResult(
|
||||
std::cout,
|
||||
1,
|
||||
&z_value,
|
||||
0,
|
||||
(CppAD::vectorBool *) CPPAD_NULL
|
||||
);
|
||||
std::cout << std::endl;
|
||||
}
|
||||
}
|
||||
std::cout << std::endl;
|
||||
# else
|
||||
}
|
||||
# endif
|
||||
CPPAD_ASSERT_UNKNOWN( i_var + 1 == play->num_var_rec() );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
} } // END_CPPAD_LOCAL_NAMESPACE
|
||||
|
||||
// preprocessor symbols that are local to this file
|
||||
# undef CPPAD_FOR_JAC_SWEEP_TRACE
|
||||
|
||||
# endif
|
||||
@@ -0,0 +1,955 @@
|
||||
# ifndef CPPAD_LOCAL_FORWARD0SWEEP_HPP
|
||||
# define CPPAD_LOCAL_FORWARD0SWEEP_HPP
|
||||
|
||||
/* --------------------------------------------------------------------------
|
||||
CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-17 Bradley M. Bell
|
||||
|
||||
CppAD is distributed under multiple licenses. This distribution is under
|
||||
the terms of the
|
||||
Eclipse Public License Version 1.0.
|
||||
|
||||
A copy of this license is included in the COPYING file of this distribution.
|
||||
Please visit http://www.coin-or.org/CppAD/ for information on other licenses.
|
||||
-------------------------------------------------------------------------- */
|
||||
|
||||
namespace CppAD { namespace local { // BEGIN_CPPAD_LOCAL_NAMESPACE
|
||||
/*!
|
||||
\file forward0sweep.hpp
|
||||
Compute zero order forward mode Taylor coefficients.
|
||||
*/
|
||||
|
||||
/*
|
||||
\def CPPAD_ATOMIC_CALL
|
||||
This avoids warnings when NDEBUG is defined and user_ok is not used.
|
||||
If NDEBUG is defined, this resolves to
|
||||
\code
|
||||
user_atom->forward
|
||||
\endcode
|
||||
otherwise, it respolves to
|
||||
\code
|
||||
user_ok = user_atom->forward
|
||||
\endcode
|
||||
This maco is undefined at the end of this file to facillitate is
|
||||
use with a different definition in other files.
|
||||
*/
|
||||
# ifdef NDEBUG
|
||||
# define CPPAD_ATOMIC_CALL user_atom->forward
|
||||
# else
|
||||
# define CPPAD_ATOMIC_CALL user_ok = user_atom->forward
|
||||
# endif
|
||||
|
||||
/*!
|
||||
\def CPPAD_FORWARD0SWEEP_TRACE
|
||||
This value is either zero or one.
|
||||
Zero is the normal operational value.
|
||||
If it is one, a trace of every forward0sweep computation is printed.
|
||||
(Note that forward0sweep is not used if CPPAD_USE_FORWARD0SWEEP is zero).
|
||||
*/
|
||||
# define CPPAD_FORWARD0SWEEP_TRACE 0
|
||||
|
||||
/*!
|
||||
Compute zero order forward mode Taylor coefficients.
|
||||
|
||||
<!-- define forward0sweep_doc_define -->
|
||||
\tparam Base
|
||||
The type used during the forward mode computations; i.e., the corresponding
|
||||
recording of operations used the type AD<Base>.
|
||||
|
||||
\param s_out
|
||||
Is the stream where output corresponding to PriOp operations will
|
||||
be written.
|
||||
|
||||
\param print
|
||||
If print is false,
|
||||
suppress the output that is otherwise generated by the c PriOp instructions.
|
||||
|
||||
\param n
|
||||
is the number of independent variables on the tape.
|
||||
|
||||
\param numvar
|
||||
is the total number of variables on the tape.
|
||||
This is also equal to the number of rows in the matrix taylor; i.e.,
|
||||
play->num_var_rec().
|
||||
|
||||
\param play
|
||||
The information stored in play
|
||||
is a recording of the operations corresponding to the function
|
||||
\f[
|
||||
F : {\bf R}^n \rightarrow {\bf R}^m
|
||||
\f]
|
||||
where \f$ n \f$ is the number of independent variables and
|
||||
\f$ m \f$ is the number of dependent variables.
|
||||
\n
|
||||
\n
|
||||
The object play is effectly constant.
|
||||
The exception to this is that while palying back the tape
|
||||
the object play holds information about the current location
|
||||
with in the tape and this changes during palyback.
|
||||
|
||||
\param J
|
||||
Is the number of columns in the coefficient matrix taylor.
|
||||
This must be greater than or equal one.
|
||||
|
||||
<!-- end forward0sweep_doc_define -->
|
||||
|
||||
\param taylor
|
||||
\n
|
||||
\b Input:
|
||||
For i = 1 , ... , n,
|
||||
<code>taylor [i * J + 0]</code>
|
||||
variable with index j on the tape
|
||||
(these are the independent variables).
|
||||
\n
|
||||
\n
|
||||
\b Output:
|
||||
For i = n + 1, ... , numvar - 1,
|
||||
<code>taylor [i * J + 0]</code>
|
||||
is the zero order Taylor coefficient for the variable with
|
||||
index i on the tape.
|
||||
|
||||
\param cskip_op
|
||||
Is a vector with size play->num_op_rec().
|
||||
The input value of the elements does not matter.
|
||||
Upon return, if cskip_op[i] is true, the operator index i
|
||||
does not affect any of the dependent variable
|
||||
(given the value of the independent variables).
|
||||
|
||||
\param var_by_load_op
|
||||
Is a vector with size play->num_load_op_rec().
|
||||
The input value of the elements does not matter.
|
||||
Upon return,
|
||||
it is the variable index corresponding the result for each load operator.
|
||||
In the case where the index is zero,
|
||||
the load operator results in a parameter (not a variable).
|
||||
Note that the is no variable with index zero on the tape.
|
||||
|
||||
\param compare_change_count
|
||||
Is the count value for changing number and op_index during
|
||||
zero order foward mode.
|
||||
|
||||
\param compare_change_number
|
||||
If compare_change_count is zero, this value is set to zero.
|
||||
Otherwise, the return value is the number of comparision operations
|
||||
that have a different result from when the information in
|
||||
play was recorded.
|
||||
|
||||
\param compare_change_op_index
|
||||
If compare_change_count is zero, this value is set to zero.
|
||||
Otherwise it is the operator index (see forward_next) for the count-th
|
||||
comparision operation that has a different result from when the information in
|
||||
play was recorded.
|
||||
*/
|
||||
|
||||
template <class Base>
|
||||
void forward0sweep(
|
||||
std::ostream& s_out,
|
||||
bool print,
|
||||
size_t n,
|
||||
size_t numvar,
|
||||
local::player<Base>* play,
|
||||
size_t J,
|
||||
Base* taylor,
|
||||
bool* cskip_op,
|
||||
pod_vector<addr_t>& var_by_load_op,
|
||||
size_t compare_change_count,
|
||||
size_t& compare_change_number,
|
||||
size_t& compare_change_op_index
|
||||
)
|
||||
{ CPPAD_ASSERT_UNKNOWN( J >= 1 );
|
||||
CPPAD_ASSERT_UNKNOWN( play->num_var_rec() == numvar );
|
||||
|
||||
// use p, q, r so other forward sweeps can use code defined here
|
||||
size_t p = 0;
|
||||
size_t q = 0;
|
||||
size_t r = 1;
|
||||
/*
|
||||
<!-- define forward0sweep_code_define -->
|
||||
*/
|
||||
// op code for current instruction
|
||||
OpCode op;
|
||||
|
||||
// index for current instruction
|
||||
size_t i_op;
|
||||
|
||||
// next variables
|
||||
size_t i_var;
|
||||
|
||||
// operation argument indices
|
||||
const addr_t* arg = CPPAD_NULL;
|
||||
|
||||
// initialize the comparision operator counter
|
||||
if( p == 0 )
|
||||
{ compare_change_number = 0;
|
||||
compare_change_op_index = 0;
|
||||
}
|
||||
|
||||
// If this includes a zero calculation, initialize this information
|
||||
pod_vector<bool> isvar_by_ind;
|
||||
pod_vector<size_t> index_by_ind;
|
||||
if( p == 0 )
|
||||
{ size_t i;
|
||||
|
||||
// this includes order zero calculation, initialize vector indices
|
||||
size_t num = play->num_vec_ind_rec();
|
||||
if( num > 0 )
|
||||
{ isvar_by_ind.extend(num);
|
||||
index_by_ind.extend(num);
|
||||
for(i = 0; i < num; i++)
|
||||
{ index_by_ind[i] = play->GetVecInd(i);
|
||||
isvar_by_ind[i] = false;
|
||||
}
|
||||
}
|
||||
// includes zero order, so initialize conditional skip flags
|
||||
num = play->num_op_rec();
|
||||
for(i = 0; i < num; i++)
|
||||
cskip_op[i] = false;
|
||||
}
|
||||
|
||||
// work space used by UserOp.
|
||||
vector<bool> user_vx; // empty vecotor
|
||||
vector<bool> user_vy; // empty vecotor
|
||||
vector<Base> user_tx; // argument vector Taylor coefficients
|
||||
vector<Base> user_ty; // result vector Taylor coefficients
|
||||
//
|
||||
atomic_base<Base>* user_atom = CPPAD_NULL; // user's atomic op calculator
|
||||
# ifndef NDEBUG
|
||||
bool user_ok = false; // atomic op return value
|
||||
# endif
|
||||
//
|
||||
// information defined by forward_user
|
||||
size_t user_old=0, user_m=0, user_n=0, user_i=0, user_j=0;
|
||||
enum_user_state user_state = start_user; // proper initialization
|
||||
|
||||
// length of the parameter vector (used by CppAD assert macros)
|
||||
const size_t num_par = play->num_par_rec();
|
||||
|
||||
// pointer to the beginning of the parameter vector
|
||||
const Base* parameter = CPPAD_NULL;
|
||||
if( num_par > 0 )
|
||||
parameter = play->GetPar();
|
||||
|
||||
// length of the text vector (used by CppAD assert macros)
|
||||
const size_t num_text = play->num_text_rec();
|
||||
|
||||
// pointer to the beginning of the text vector
|
||||
const char* text = CPPAD_NULL;
|
||||
if( num_text > 0 )
|
||||
text = play->GetTxt(0);
|
||||
/*
|
||||
<!-- end forward0sweep_code_define -->
|
||||
*/
|
||||
|
||||
# if CPPAD_FORWARD0SWEEP_TRACE
|
||||
// flag as to when to trace user function values
|
||||
bool user_trace = false;
|
||||
|
||||
// variable indices for results vector
|
||||
// (done differently for order zero).
|
||||
vector<size_t> user_iy;
|
||||
# endif
|
||||
|
||||
// skip the BeginOp at the beginning of the recording
|
||||
play->forward_start(op, arg, i_op, i_var);
|
||||
CPPAD_ASSERT_UNKNOWN( op == BeginOp );
|
||||
# if CPPAD_FORWARD0SWEEP_TRACE
|
||||
std::cout << std::endl;
|
||||
# endif
|
||||
bool flag; // a temporary flag to use in switch cases
|
||||
bool more_operators = true;
|
||||
while(more_operators)
|
||||
{
|
||||
// this op
|
||||
play->forward_next(op, arg, i_op, i_var);
|
||||
CPPAD_ASSERT_UNKNOWN( (i_op > n) | (op == InvOp) );
|
||||
CPPAD_ASSERT_UNKNOWN( (i_op <= n) | (op != InvOp) );
|
||||
CPPAD_ASSERT_UNKNOWN( i_op < play->num_op_rec() );
|
||||
CPPAD_ASSERT_ARG_BEFORE_RESULT(op, arg, i_var);
|
||||
|
||||
// check if we are skipping this operation
|
||||
while( cskip_op[i_op] )
|
||||
{ switch(op)
|
||||
{ case CSumOp:
|
||||
// CSumOp has a variable number of arguments
|
||||
play->forward_csum(op, arg, i_op, i_var);
|
||||
break;
|
||||
|
||||
case CSkipOp:
|
||||
// CSkip has a variable number of arguments
|
||||
play->forward_cskip(op, arg, i_op, i_var);
|
||||
break;
|
||||
|
||||
case UserOp:
|
||||
{ // skip all operations in this user atomic call
|
||||
CPPAD_ASSERT_UNKNOWN( user_state == start_user );
|
||||
play->forward_user(op, user_state,
|
||||
user_old, user_m, user_n, user_i, user_j
|
||||
);
|
||||
size_t n_skip = user_m + user_n + 1;
|
||||
for(size_t i = 0; i < n_skip; i++)
|
||||
{ play->forward_next(op, arg, i_op, i_var);
|
||||
play->forward_user(op, user_state,
|
||||
user_old, user_m, user_n, user_i, user_j
|
||||
);
|
||||
}
|
||||
CPPAD_ASSERT_UNKNOWN( user_state == start_user );
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
play->forward_next(op, arg, i_op, i_var);
|
||||
CPPAD_ASSERT_UNKNOWN( i_op < play->num_op_rec() );
|
||||
}
|
||||
|
||||
// action to take depends on the case
|
||||
switch( op )
|
||||
{
|
||||
case AbsOp:
|
||||
forward_abs_op_0(i_var, arg[0], J, taylor);
|
||||
break;
|
||||
// -------------------------------------------------
|
||||
|
||||
case AddvvOp:
|
||||
forward_addvv_op_0(i_var, arg, parameter, J, taylor);
|
||||
break;
|
||||
// -------------------------------------------------
|
||||
|
||||
case AddpvOp:
|
||||
CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < num_par );
|
||||
forward_addpv_op_0(i_var, arg, parameter, J, taylor);
|
||||
break;
|
||||
// -------------------------------------------------
|
||||
|
||||
case AcosOp:
|
||||
// sqrt(1 - x * x), acos(x)
|
||||
CPPAD_ASSERT_UNKNOWN( i_var < numvar );
|
||||
forward_acos_op_0(i_var, arg[0], J, taylor);
|
||||
break;
|
||||
// -------------------------------------------------
|
||||
|
||||
# if CPPAD_USE_CPLUSPLUS_2011
|
||||
case AcoshOp:
|
||||
// sqrt(x * x - 1), acosh(x)
|
||||
CPPAD_ASSERT_UNKNOWN( i_var < numvar );
|
||||
forward_acosh_op_0(i_var, arg[0], J, taylor);
|
||||
break;
|
||||
# endif
|
||||
// -------------------------------------------------
|
||||
|
||||
case AsinOp:
|
||||
// sqrt(1 - x * x), asin(x)
|
||||
CPPAD_ASSERT_UNKNOWN( i_var < numvar );
|
||||
forward_asin_op_0(i_var, arg[0], J, taylor);
|
||||
break;
|
||||
// -------------------------------------------------
|
||||
|
||||
# if CPPAD_USE_CPLUSPLUS_2011
|
||||
case AsinhOp:
|
||||
// sqrt(1 + x * x), asinh(x)
|
||||
CPPAD_ASSERT_UNKNOWN( i_var < numvar );
|
||||
forward_asinh_op_0(i_var, arg[0], J, taylor);
|
||||
break;
|
||||
# endif
|
||||
// -------------------------------------------------
|
||||
|
||||
case AtanOp:
|
||||
// 1 + x * x, atan(x)
|
||||
CPPAD_ASSERT_UNKNOWN( i_var < numvar );
|
||||
forward_atan_op_0(i_var, arg[0], J, taylor);
|
||||
break;
|
||||
// -------------------------------------------------
|
||||
|
||||
# if CPPAD_USE_CPLUSPLUS_2011
|
||||
case AtanhOp:
|
||||
// 1 - x * x, atanh(x)
|
||||
CPPAD_ASSERT_UNKNOWN( i_var < numvar );
|
||||
forward_atanh_op_0(i_var, arg[0], J, taylor);
|
||||
break;
|
||||
# endif
|
||||
// -------------------------------------------------
|
||||
|
||||
case CExpOp:
|
||||
// Use the general case with d == 0
|
||||
// (could create an optimzied verison for this case)
|
||||
forward_cond_op_0(
|
||||
i_var, arg, num_par, parameter, J, taylor
|
||||
);
|
||||
break;
|
||||
// ---------------------------------------------------
|
||||
|
||||
case CosOp:
|
||||
// sin(x), cos(x)
|
||||
CPPAD_ASSERT_UNKNOWN( i_var < numvar );
|
||||
forward_cos_op_0(i_var, arg[0], J, taylor);
|
||||
break;
|
||||
// ---------------------------------------------------
|
||||
|
||||
case CoshOp:
|
||||
// sinh(x), cosh(x)
|
||||
CPPAD_ASSERT_UNKNOWN( i_var < numvar );
|
||||
forward_cosh_op_0(i_var, arg[0], J, taylor);
|
||||
break;
|
||||
// -------------------------------------------------
|
||||
|
||||
case CSkipOp:
|
||||
// CSkipOp has a variable number of arguments and
|
||||
// forward_next thinks it has no arguments.
|
||||
// we must inform forward_next of this special case.
|
||||
forward_cskip_op_0(
|
||||
i_var, arg, num_par, parameter, J, taylor, cskip_op
|
||||
);
|
||||
play->forward_cskip(op, arg, i_op, i_var);
|
||||
break;
|
||||
// -------------------------------------------------
|
||||
|
||||
case CSumOp:
|
||||
// CSumOp has a variable number of arguments and
|
||||
// forward_next thinks it has no arguments.
|
||||
// we must inform forward_next of this special case.
|
||||
forward_csum_op(
|
||||
0, 0, i_var, arg, num_par, parameter, J, taylor
|
||||
);
|
||||
play->forward_csum(op, arg, i_op, i_var);
|
||||
break;
|
||||
// -------------------------------------------------
|
||||
|
||||
case DisOp:
|
||||
forward_dis_op(p, q, r, i_var, arg, J, taylor);
|
||||
break;
|
||||
// -------------------------------------------------
|
||||
|
||||
case DivvvOp:
|
||||
forward_divvv_op_0(i_var, arg, parameter, J, taylor);
|
||||
break;
|
||||
// -------------------------------------------------
|
||||
|
||||
case DivpvOp:
|
||||
CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < num_par );
|
||||
forward_divpv_op_0(i_var, arg, parameter, J, taylor);
|
||||
break;
|
||||
// -------------------------------------------------
|
||||
|
||||
case DivvpOp:
|
||||
CPPAD_ASSERT_UNKNOWN( size_t(arg[1]) < num_par );
|
||||
forward_divvp_op_0(i_var, arg, parameter, J, taylor);
|
||||
break;
|
||||
// -------------------------------------------------
|
||||
|
||||
case EndOp:
|
||||
CPPAD_ASSERT_NARG_NRES(op, 0, 0);
|
||||
more_operators = false;
|
||||
break;
|
||||
// -------------------------------------------------
|
||||
|
||||
case EqpvOp:
|
||||
if( compare_change_count )
|
||||
{ forward_eqpv_op_0(
|
||||
compare_change_number, arg, parameter, J, taylor
|
||||
);
|
||||
{ if( compare_change_count == compare_change_number )
|
||||
compare_change_op_index = i_op;
|
||||
}
|
||||
}
|
||||
break;
|
||||
// -------------------------------------------------
|
||||
|
||||
case EqvvOp:
|
||||
if( compare_change_count )
|
||||
{ forward_eqvv_op_0(
|
||||
compare_change_number, arg, parameter, J, taylor
|
||||
);
|
||||
{ if( compare_change_count == compare_change_number )
|
||||
compare_change_op_index = i_op;
|
||||
}
|
||||
}
|
||||
break;
|
||||
// -------------------------------------------------
|
||||
|
||||
# if CPPAD_USE_CPLUSPLUS_2011
|
||||
case ErfOp:
|
||||
forward_erf_op_0(i_var, arg, parameter, J, taylor);
|
||||
break;
|
||||
# endif
|
||||
// -------------------------------------------------
|
||||
|
||||
case ExpOp:
|
||||
forward_exp_op_0(i_var, arg[0], J, taylor);
|
||||
break;
|
||||
// -------------------------------------------------
|
||||
|
||||
# if CPPAD_USE_CPLUSPLUS_2011
|
||||
case Expm1Op:
|
||||
forward_expm1_op_0(i_var, arg[0], J, taylor);
|
||||
break;
|
||||
# endif
|
||||
// -------------------------------------------------
|
||||
|
||||
case InvOp:
|
||||
CPPAD_ASSERT_NARG_NRES(op, 0, 1);
|
||||
break;
|
||||
// ---------------------------------------------------
|
||||
|
||||
case LdpOp:
|
||||
forward_load_p_op_0(
|
||||
play,
|
||||
i_var,
|
||||
arg,
|
||||
parameter,
|
||||
J,
|
||||
taylor,
|
||||
isvar_by_ind.data(),
|
||||
index_by_ind.data(),
|
||||
var_by_load_op.data()
|
||||
);
|
||||
break;
|
||||
// -------------------------------------------------
|
||||
|
||||
case LdvOp:
|
||||
forward_load_v_op_0(
|
||||
play,
|
||||
i_var,
|
||||
arg,
|
||||
parameter,
|
||||
J,
|
||||
taylor,
|
||||
isvar_by_ind.data(),
|
||||
index_by_ind.data(),
|
||||
var_by_load_op.data()
|
||||
);
|
||||
break;
|
||||
// -------------------------------------------------
|
||||
|
||||
case LepvOp:
|
||||
if( compare_change_count )
|
||||
{ forward_lepv_op_0(
|
||||
compare_change_number, arg, parameter, J, taylor
|
||||
);
|
||||
{ if( compare_change_count == compare_change_number )
|
||||
compare_change_op_index = i_op;
|
||||
}
|
||||
}
|
||||
break;
|
||||
// -------------------------------------------------
|
||||
|
||||
case LevpOp:
|
||||
if( compare_change_count )
|
||||
{ forward_levp_op_0(
|
||||
compare_change_number, arg, parameter, J, taylor
|
||||
);
|
||||
{ if( compare_change_count == compare_change_number )
|
||||
compare_change_op_index = i_op;
|
||||
}
|
||||
}
|
||||
break;
|
||||
// -------------------------------------------------
|
||||
|
||||
case LevvOp:
|
||||
if( compare_change_count )
|
||||
{ forward_levv_op_0(
|
||||
compare_change_number, arg, parameter, J, taylor
|
||||
);
|
||||
{ if( compare_change_count == compare_change_number )
|
||||
compare_change_op_index = i_op;
|
||||
}
|
||||
}
|
||||
break;
|
||||
// -------------------------------------------------
|
||||
|
||||
case LogOp:
|
||||
forward_log_op_0(i_var, arg[0], J, taylor);
|
||||
break;
|
||||
// -------------------------------------------------
|
||||
|
||||
# if CPPAD_USE_CPLUSPLUS_2011
|
||||
case Log1pOp:
|
||||
forward_log1p_op_0(i_var, arg[0], J, taylor);
|
||||
break;
|
||||
# endif
|
||||
// -------------------------------------------------
|
||||
|
||||
case LtpvOp:
|
||||
if( compare_change_count )
|
||||
{ forward_ltpv_op_0(
|
||||
compare_change_number, arg, parameter, J, taylor
|
||||
);
|
||||
{ if( compare_change_count == compare_change_number )
|
||||
compare_change_op_index = i_op;
|
||||
}
|
||||
}
|
||||
break;
|
||||
// -------------------------------------------------
|
||||
|
||||
case LtvpOp:
|
||||
if( compare_change_count )
|
||||
{ forward_ltvp_op_0(
|
||||
compare_change_number, arg, parameter, J, taylor
|
||||
);
|
||||
{ if( compare_change_count == compare_change_number )
|
||||
compare_change_op_index = i_op;
|
||||
}
|
||||
}
|
||||
break;
|
||||
// -------------------------------------------------
|
||||
|
||||
case LtvvOp:
|
||||
if( compare_change_count )
|
||||
{ forward_ltvv_op_0(
|
||||
compare_change_number, arg, parameter, J, taylor
|
||||
);
|
||||
{ if( compare_change_count == compare_change_number )
|
||||
compare_change_op_index = i_op;
|
||||
}
|
||||
}
|
||||
break;
|
||||
// -------------------------------------------------
|
||||
|
||||
case MulpvOp:
|
||||
CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < num_par );
|
||||
forward_mulpv_op_0(i_var, arg, parameter, J, taylor);
|
||||
break;
|
||||
// -------------------------------------------------
|
||||
|
||||
case MulvvOp:
|
||||
forward_mulvv_op_0(i_var, arg, parameter, J, taylor);
|
||||
break;
|
||||
// -------------------------------------------------
|
||||
|
||||
case NepvOp:
|
||||
if( compare_change_count )
|
||||
{ forward_nepv_op_0(
|
||||
compare_change_number, arg, parameter, J, taylor
|
||||
);
|
||||
{ if( compare_change_count == compare_change_number )
|
||||
compare_change_op_index = i_op;
|
||||
}
|
||||
}
|
||||
break;
|
||||
// -------------------------------------------------
|
||||
|
||||
case NevvOp:
|
||||
if( compare_change_count )
|
||||
{ forward_nevv_op_0(
|
||||
compare_change_number, arg, parameter, J, taylor
|
||||
);
|
||||
{ if( compare_change_count == compare_change_number )
|
||||
compare_change_op_index = i_op;
|
||||
}
|
||||
}
|
||||
break;
|
||||
// -------------------------------------------------
|
||||
|
||||
case ParOp:
|
||||
forward_par_op_0(
|
||||
i_var, arg, num_par, parameter, J, taylor
|
||||
);
|
||||
break;
|
||||
// -------------------------------------------------
|
||||
|
||||
case PowvpOp:
|
||||
CPPAD_ASSERT_UNKNOWN( size_t(arg[1]) < num_par );
|
||||
forward_powvp_op_0(i_var, arg, parameter, J, taylor);
|
||||
break;
|
||||
// -------------------------------------------------
|
||||
|
||||
case PowpvOp:
|
||||
CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < num_par );
|
||||
forward_powpv_op_0(i_var, arg, parameter, J, taylor);
|
||||
break;
|
||||
// -------------------------------------------------
|
||||
|
||||
case PowvvOp:
|
||||
forward_powvv_op_0(i_var, arg, parameter, J, taylor);
|
||||
break;
|
||||
// -------------------------------------------------
|
||||
|
||||
case PriOp:
|
||||
if( print ) forward_pri_0(s_out,
|
||||
arg, num_text, text, num_par, parameter, J, taylor
|
||||
);
|
||||
break;
|
||||
// -------------------------------------------------
|
||||
|
||||
case SignOp:
|
||||
// cos(x), sin(x)
|
||||
CPPAD_ASSERT_UNKNOWN( i_var < numvar );
|
||||
forward_sign_op_0(i_var, arg[0], J, taylor);
|
||||
break;
|
||||
// -------------------------------------------------
|
||||
|
||||
case SinOp:
|
||||
// cos(x), sin(x)
|
||||
CPPAD_ASSERT_UNKNOWN( i_var < numvar );
|
||||
forward_sin_op_0(i_var, arg[0], J, taylor);
|
||||
break;
|
||||
// -------------------------------------------------
|
||||
|
||||
case SinhOp:
|
||||
// cosh(x), sinh(x)
|
||||
CPPAD_ASSERT_UNKNOWN( i_var < numvar );
|
||||
forward_sinh_op_0(i_var, arg[0], J, taylor);
|
||||
break;
|
||||
// -------------------------------------------------
|
||||
|
||||
case SqrtOp:
|
||||
forward_sqrt_op_0(i_var, arg[0], J, taylor);
|
||||
break;
|
||||
// -------------------------------------------------
|
||||
|
||||
case StppOp:
|
||||
forward_store_pp_op_0(
|
||||
i_var,
|
||||
arg,
|
||||
num_par,
|
||||
J,
|
||||
taylor,
|
||||
isvar_by_ind.data(),
|
||||
index_by_ind.data()
|
||||
);
|
||||
break;
|
||||
// -------------------------------------------------
|
||||
|
||||
case StpvOp:
|
||||
forward_store_pv_op_0(
|
||||
i_var,
|
||||
arg,
|
||||
num_par,
|
||||
J,
|
||||
taylor,
|
||||
isvar_by_ind.data(),
|
||||
index_by_ind.data()
|
||||
);
|
||||
break;
|
||||
// -------------------------------------------------
|
||||
|
||||
case StvpOp:
|
||||
forward_store_vp_op_0(
|
||||
i_var,
|
||||
arg,
|
||||
num_par,
|
||||
J,
|
||||
taylor,
|
||||
isvar_by_ind.data(),
|
||||
index_by_ind.data()
|
||||
);
|
||||
break;
|
||||
// -------------------------------------------------
|
||||
|
||||
case StvvOp:
|
||||
forward_store_vv_op_0(
|
||||
i_var,
|
||||
arg,
|
||||
num_par,
|
||||
J,
|
||||
taylor,
|
||||
isvar_by_ind.data(),
|
||||
index_by_ind.data()
|
||||
);
|
||||
break;
|
||||
// -------------------------------------------------
|
||||
|
||||
case SubvvOp:
|
||||
forward_subvv_op_0(i_var, arg, parameter, J, taylor);
|
||||
break;
|
||||
// -------------------------------------------------
|
||||
|
||||
case SubpvOp:
|
||||
CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < num_par );
|
||||
forward_subpv_op_0(i_var, arg, parameter, J, taylor);
|
||||
break;
|
||||
// -------------------------------------------------
|
||||
|
||||
case SubvpOp:
|
||||
CPPAD_ASSERT_UNKNOWN( size_t(arg[1]) < num_par );
|
||||
forward_subvp_op_0(i_var, arg, parameter, J, taylor);
|
||||
break;
|
||||
// -------------------------------------------------
|
||||
|
||||
case TanOp:
|
||||
// tan(x)^2, tan(x)
|
||||
CPPAD_ASSERT_UNKNOWN( i_var < numvar );
|
||||
forward_tan_op_0(i_var, arg[0], J, taylor);
|
||||
break;
|
||||
// -------------------------------------------------
|
||||
|
||||
case TanhOp:
|
||||
// tanh(x)^2, tanh(x)
|
||||
CPPAD_ASSERT_UNKNOWN( i_var < numvar );
|
||||
forward_tanh_op_0(i_var, arg[0], J, taylor);
|
||||
break;
|
||||
// -------------------------------------------------
|
||||
|
||||
case UserOp:
|
||||
// start or end an atomic operation sequence
|
||||
flag = user_state == start_user;
|
||||
user_atom = play->forward_user(op, user_state,
|
||||
user_old, user_m, user_n, user_i, user_j
|
||||
);
|
||||
if( flag )
|
||||
{ user_tx.resize(user_n);
|
||||
user_ty.resize(user_m);
|
||||
# if CPPAD_FORWARD0SWEEP_TRACE
|
||||
user_iy.resize(user_m);
|
||||
# endif
|
||||
}
|
||||
else
|
||||
{
|
||||
# ifndef NDEBUG
|
||||
if( ! user_ok )
|
||||
{ std::string msg =
|
||||
user_atom->afun_name()
|
||||
+ ": atomic_base.forward: returned false";
|
||||
CPPAD_ASSERT_KNOWN(false, msg.c_str() );
|
||||
}
|
||||
# endif
|
||||
# if CPPAD_FORWARD0SWEEP_TRACE
|
||||
user_trace = true;
|
||||
# endif
|
||||
}
|
||||
break;
|
||||
|
||||
case UsrapOp:
|
||||
// parameter argument in an atomic operation sequence
|
||||
CPPAD_ASSERT_UNKNOWN( size_t( arg[0] ) < num_par );
|
||||
user_tx[user_j] = parameter[ arg[0] ];
|
||||
play->forward_user(op, user_state,
|
||||
user_old, user_m, user_n, user_i, user_j
|
||||
);
|
||||
if( user_j == user_n )
|
||||
{ // call users function for this operation
|
||||
user_atom->set_old(user_old);
|
||||
CPPAD_ATOMIC_CALL(p, q,
|
||||
user_vx, user_vy, user_tx, user_ty
|
||||
);
|
||||
}
|
||||
break;
|
||||
|
||||
case UsravOp:
|
||||
// variable argument in an atomic operation sequence
|
||||
CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) <= i_var );
|
||||
user_tx[user_j] = taylor[ arg[0] * J + 0 ];
|
||||
play->forward_user(op, user_state,
|
||||
user_old, user_m, user_n, user_i, user_j
|
||||
);
|
||||
if( user_j == user_n )
|
||||
{ // call users function for this operation
|
||||
user_atom->set_old(user_old);
|
||||
CPPAD_ATOMIC_CALL(p, q,
|
||||
user_vx, user_vy, user_tx, user_ty
|
||||
);
|
||||
}
|
||||
break;
|
||||
|
||||
case UsrrpOp:
|
||||
// parameter result in an atomic operation sequence
|
||||
# if CPPAD_FORWARD0SWEEP_TRACE
|
||||
user_iy[user_i] = 0;
|
||||
# endif
|
||||
play->forward_user(op, user_state,
|
||||
user_old, user_m, user_n, user_i, user_j
|
||||
);
|
||||
break;
|
||||
|
||||
case UsrrvOp:
|
||||
// variable result in an atomic operation sequence
|
||||
# if CPPAD_FORWARD0SWEEP_TRACE
|
||||
user_iy[user_i] = i_var;
|
||||
# endif
|
||||
taylor[ i_var * J + 0 ] = user_ty[user_i];
|
||||
play->forward_user(op, user_state,
|
||||
user_old, user_m, user_n, user_i, user_j
|
||||
);
|
||||
break;
|
||||
// -------------------------------------------------
|
||||
|
||||
case ZmulpvOp:
|
||||
CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < num_par );
|
||||
forward_zmulpv_op_0(i_var, arg, parameter, J, taylor);
|
||||
break;
|
||||
// -------------------------------------------------
|
||||
|
||||
case ZmulvpOp:
|
||||
CPPAD_ASSERT_UNKNOWN( size_t(arg[1]) < num_par );
|
||||
forward_zmulvp_op_0(i_var, arg, parameter, J, taylor);
|
||||
break;
|
||||
// -------------------------------------------------
|
||||
|
||||
case ZmulvvOp:
|
||||
forward_zmulvv_op_0(i_var, arg, parameter, J, taylor);
|
||||
break;
|
||||
// -------------------------------------------------
|
||||
|
||||
default:
|
||||
CPPAD_ASSERT_UNKNOWN(false);
|
||||
}
|
||||
# if CPPAD_FORWARD0SWEEP_TRACE
|
||||
size_t d = 0;
|
||||
if( user_trace )
|
||||
{ user_trace = false;
|
||||
|
||||
CPPAD_ASSERT_UNKNOWN( op == UserOp );
|
||||
CPPAD_ASSERT_UNKNOWN( NumArg(UsrrvOp) == 0 );
|
||||
for(size_t i = 0; i < user_m; i++) if( user_iy[i] > 0 )
|
||||
{ size_t i_tmp = (i_op + i) - user_m;
|
||||
printOp(
|
||||
std::cout,
|
||||
play,
|
||||
i_tmp,
|
||||
user_iy[i],
|
||||
UsrrvOp,
|
||||
CPPAD_NULL
|
||||
);
|
||||
Base* Z_tmp = taylor + user_iy[i] * J;
|
||||
printOpResult(
|
||||
std::cout,
|
||||
d + 1,
|
||||
Z_tmp,
|
||||
0,
|
||||
(Base *) CPPAD_NULL
|
||||
);
|
||||
std::cout << std::endl;
|
||||
}
|
||||
}
|
||||
Base* Z_tmp = taylor + i_var * J;
|
||||
const addr_t* arg_tmp = arg;
|
||||
if( op == CSumOp )
|
||||
arg_tmp = arg - arg[-1] - 4;
|
||||
if( op == CSkipOp )
|
||||
arg_tmp = arg - arg[-1] - 7;
|
||||
if( op != UsrrvOp )
|
||||
{
|
||||
printOp(
|
||||
std::cout,
|
||||
play,
|
||||
i_op,
|
||||
i_var,
|
||||
op,
|
||||
arg_tmp
|
||||
);
|
||||
if( NumRes(op) > 0 ) printOpResult(
|
||||
std::cout,
|
||||
d + 1,
|
||||
Z_tmp,
|
||||
0,
|
||||
(Base *) CPPAD_NULL
|
||||
);
|
||||
std::cout << std::endl;
|
||||
}
|
||||
}
|
||||
std::cout << std::endl;
|
||||
# else
|
||||
}
|
||||
# endif
|
||||
CPPAD_ASSERT_UNKNOWN( user_state == start_user );
|
||||
CPPAD_ASSERT_UNKNOWN( i_var + 1 == play->num_var_rec() );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
} } // END_CPPAD_LOCAL_NAMESPACE
|
||||
|
||||
// preprocessor symbols that are local to this file
|
||||
# undef CPPAD_FORWARD0SWEEP_TRACE
|
||||
# undef CPPAD_ATOMIC_CALL
|
||||
|
||||
# endif
|
||||
+1058
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,795 @@
|
||||
# ifndef CPPAD_LOCAL_FORWARD2SWEEP_HPP
|
||||
# define CPPAD_LOCAL_FORWARD2SWEEP_HPP
|
||||
|
||||
/* --------------------------------------------------------------------------
|
||||
CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-17 Bradley M. Bell
|
||||
|
||||
CppAD is distributed under multiple licenses. This distribution is under
|
||||
the terms of the
|
||||
Eclipse Public License Version 1.0.
|
||||
|
||||
A copy of this license is included in the COPYING file of this distribution.
|
||||
Please visit http://www.coin-or.org/CppAD/ for information on other licenses.
|
||||
-------------------------------------------------------------------------- */
|
||||
|
||||
namespace CppAD { namespace local { // BEGIN_CPPAD_LOCAL_NAMESPACE
|
||||
/*!
|
||||
\file forward2sweep.hpp
|
||||
Compute one Taylor coefficient for each direction requested.
|
||||
*/
|
||||
|
||||
/*
|
||||
\def CPPAD_ATOMIC_CALL
|
||||
This avoids warnings when NDEBUG is defined and user_ok is not used.
|
||||
If NDEBUG is defined, this resolves to
|
||||
\code
|
||||
user_atom->forward
|
||||
\endcode
|
||||
otherwise, it respolves to
|
||||
\code
|
||||
user_ok = user_atom->forward
|
||||
\endcode
|
||||
This macro is undefined at the end of this file to facillitate its
|
||||
use with a different definition in other files.
|
||||
*/
|
||||
# ifdef NDEBUG
|
||||
# define CPPAD_ATOMIC_CALL user_atom->forward
|
||||
# else
|
||||
# define CPPAD_ATOMIC_CALL user_ok = user_atom->forward
|
||||
# endif
|
||||
|
||||
/*!
|
||||
\def CPPAD_FORWARD2SWEEP_TRACE
|
||||
This value is either zero or one.
|
||||
Zero is the normal operational value.
|
||||
If it is one, a trace of every forward2sweep computation is printed.
|
||||
*/
|
||||
# define CPPAD_FORWARD2SWEEP_TRACE 0
|
||||
|
||||
/*!
|
||||
Compute multiple directions forward mode Taylor coefficients.
|
||||
|
||||
\tparam Base
|
||||
The type used during the forward mode computations; i.e., the corresponding
|
||||
recording of operations used the type AD<Base>.
|
||||
|
||||
\param q
|
||||
is the order of the Taylor coefficients
|
||||
that are computed during this call;
|
||||
<code>q > 0</code>.
|
||||
|
||||
\param r
|
||||
is the number of Taylor coefficients
|
||||
that are computed during this call.
|
||||
|
||||
\param n
|
||||
is the number of independent variables on the tape.
|
||||
|
||||
\param numvar
|
||||
is the total number of variables on the tape.
|
||||
This is also equal to the number of rows in the matrix taylor; i.e.,
|
||||
play->num_var_rec().
|
||||
|
||||
\param play
|
||||
The information stored in play
|
||||
is a recording of the operations corresponding to the function
|
||||
\f[
|
||||
F : {\bf R}^n \rightarrow {\bf R}^m
|
||||
\f]
|
||||
where \f$ n \f$ is the number of independent variables and
|
||||
\f$ m \f$ is the number of dependent variables.
|
||||
\n
|
||||
\n
|
||||
The object play is effectly constant.
|
||||
The exception to this is that while palying back the tape
|
||||
the object play holds information about the current location
|
||||
with in the tape and this changes during palyback.
|
||||
|
||||
\param J
|
||||
Is the number of columns in the coefficient matrix taylor.
|
||||
This must be greater than or equal one.
|
||||
|
||||
\param taylor
|
||||
\n
|
||||
\b Input:
|
||||
For <code>i = 1 , ... , numvar-1</code>,
|
||||
<code>taylor[ (J-1)*r*i + i + 0 ]</code>
|
||||
is the zero order Taylor coefficient corresponding to
|
||||
the i-th variable and all directions.
|
||||
For <code>i = 1 , ... , numvar-1</code>,
|
||||
For <code>k = 1 , ... , q-1</code>,
|
||||
<code>ell = 0 , ... , r-1</code>,
|
||||
<code>taylor[ (J-1)*r*i + i + (k-1)*r + ell + 1 ]</code>
|
||||
is the k-th order Taylor coefficient corresponding to
|
||||
the i-th variabel and ell-th direction.
|
||||
\n
|
||||
\n
|
||||
\b Input:
|
||||
For <code>i = 1 , ... , n</code>,
|
||||
<code>ell = 0 , ... , r-1</code>,
|
||||
<code>taylor[ (J-1)*r*i + i + (q-1)*r + ell + 1 ]</code>
|
||||
is the q-th order Taylor coefficient corresponding to
|
||||
the i-th variable and ell-th direction
|
||||
(these are the independent varaibles).
|
||||
\n
|
||||
\n
|
||||
\b Output:
|
||||
For <code>i = n+1 , ... , numvar-1</code>,
|
||||
<code>ell = 0 , ... , r-1</code>,
|
||||
<code>taylor[ (J-1)*r*i + i + (q-1)*r + ell + 1 ]</code>
|
||||
is the q-th order Taylor coefficient corresponding to
|
||||
the i-th variable and ell-th direction.
|
||||
|
||||
\param cskip_op
|
||||
Is a vector with size play->num_op_rec().
|
||||
If cskip_op[i] is true, the operator with index i
|
||||
does not affect any of the dependent variable (given the value
|
||||
of the independent variables).
|
||||
|
||||
\param var_by_load_op
|
||||
is a vector with size play->num_load_op_rec().
|
||||
It is the variable index corresponding to each the
|
||||
load instruction.
|
||||
In the case where the index is zero,
|
||||
the instruction corresponds to a parameter (not variable).
|
||||
|
||||
*/
|
||||
|
||||
template <class Base>
|
||||
void forward2sweep(
|
||||
const size_t q,
|
||||
const size_t r,
|
||||
const size_t n,
|
||||
const size_t numvar,
|
||||
local::player<Base>* play,
|
||||
const size_t J,
|
||||
Base* taylor,
|
||||
const bool* cskip_op,
|
||||
const pod_vector<addr_t>& var_by_load_op
|
||||
)
|
||||
{
|
||||
CPPAD_ASSERT_UNKNOWN( q > 0 );
|
||||
CPPAD_ASSERT_UNKNOWN( J >= q + 1 );
|
||||
CPPAD_ASSERT_UNKNOWN( play->num_var_rec() == numvar );
|
||||
|
||||
// used to avoid compiler errors until all operators are implemented
|
||||
size_t p = q;
|
||||
|
||||
// op code for current instruction
|
||||
OpCode op;
|
||||
|
||||
// index for current instruction
|
||||
size_t i_op;
|
||||
|
||||
// next variables
|
||||
size_t i_var;
|
||||
|
||||
// operation argument indices
|
||||
const addr_t* arg = CPPAD_NULL;
|
||||
|
||||
// work space used by UserOp.
|
||||
vector<bool> user_vx; // empty vecotor
|
||||
vector<bool> user_vy; // empty vecotor
|
||||
vector<Base> user_tx_one; // argument vector Taylor coefficients
|
||||
vector<Base> user_tx_all;
|
||||
vector<Base> user_ty_one; // result vector Taylor coefficients
|
||||
vector<Base> user_ty_all;
|
||||
//
|
||||
// information defined by forward_user
|
||||
size_t user_old=0, user_m=0, user_n=0, user_i=0, user_j=0;
|
||||
enum_user_state user_state = start_user; // proper initialization
|
||||
//
|
||||
atomic_base<Base>* user_atom = CPPAD_NULL; // user's atomic op calculator
|
||||
# ifndef NDEBUG
|
||||
bool user_ok = false; // atomic op return value
|
||||
# endif
|
||||
|
||||
// length of the parameter vector (used by CppAD assert macros)
|
||||
const size_t num_par = play->num_par_rec();
|
||||
|
||||
// pointer to the beginning of the parameter vector
|
||||
const Base* parameter = CPPAD_NULL;
|
||||
if( num_par > 0 )
|
||||
parameter = play->GetPar();
|
||||
|
||||
// temporary indices
|
||||
size_t i, j, k, ell;
|
||||
|
||||
// number of orders for this user calculation
|
||||
// (not needed for order zero)
|
||||
const size_t user_q1 = q+1;
|
||||
|
||||
// variable indices for results vector
|
||||
// (done differently for order zero).
|
||||
vector<size_t> user_iy;
|
||||
|
||||
// skip the BeginOp at the beginning of the recording
|
||||
play->forward_start(op, arg, i_op, i_var);
|
||||
CPPAD_ASSERT_UNKNOWN( op == BeginOp );
|
||||
# if CPPAD_FORWARD2SWEEP_TRACE
|
||||
bool user_trace = false;
|
||||
std::cout << std::endl;
|
||||
CppAD::vector<Base> Z_vec(q+1);
|
||||
# endif
|
||||
bool flag; // a temporary flag to use in switch cases
|
||||
bool more_operators = true;
|
||||
while(more_operators)
|
||||
{
|
||||
// this op
|
||||
play->forward_next(op, arg, i_op, i_var);
|
||||
CPPAD_ASSERT_UNKNOWN( (i_op > n) | (op == InvOp) );
|
||||
CPPAD_ASSERT_UNKNOWN( (i_op <= n) | (op != InvOp) );
|
||||
CPPAD_ASSERT_UNKNOWN( i_op < play->num_op_rec() );
|
||||
CPPAD_ASSERT_ARG_BEFORE_RESULT(op, arg, i_var);
|
||||
|
||||
// check if we are skipping this operation
|
||||
while( cskip_op[i_op] )
|
||||
{ switch(op)
|
||||
{ case CSumOp:
|
||||
// CSumOp has a variable number of arguments
|
||||
play->forward_csum(op, arg, i_op, i_var);
|
||||
break;
|
||||
|
||||
case CSkipOp:
|
||||
// CSkip has a variable number of arguments
|
||||
play->forward_cskip(op, arg, i_op, i_var);
|
||||
break;
|
||||
|
||||
case UserOp:
|
||||
{ // skip all operations in this user atomic call
|
||||
CPPAD_ASSERT_UNKNOWN( user_state == start_user );
|
||||
play->forward_user(op, user_state,
|
||||
user_old, user_m, user_n, user_i, user_j
|
||||
);
|
||||
size_t n_skip = user_m + user_n + 1;
|
||||
for(i = 0; i < n_skip; i++)
|
||||
{ play->forward_next(op, arg, i_op, i_var);
|
||||
play->forward_user(op, user_state,
|
||||
user_old, user_m, user_n, user_i, user_j
|
||||
);
|
||||
}
|
||||
CPPAD_ASSERT_UNKNOWN( user_state == start_user );
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
play->forward_next(op, arg, i_op, i_var);
|
||||
CPPAD_ASSERT_UNKNOWN( i_op < play->num_op_rec() );
|
||||
}
|
||||
|
||||
// action depends on the operator
|
||||
switch( op )
|
||||
{
|
||||
case AbsOp:
|
||||
forward_abs_op_dir(q, r, i_var, arg[0], J, taylor);
|
||||
break;
|
||||
// -------------------------------------------------
|
||||
|
||||
case AddvvOp:
|
||||
forward_addvv_op_dir(q, r, i_var, arg, parameter, J, taylor);
|
||||
break;
|
||||
// -------------------------------------------------
|
||||
|
||||
case AddpvOp:
|
||||
CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < num_par );
|
||||
forward_addpv_op_dir(q, r, i_var, arg, parameter, J, taylor);
|
||||
break;
|
||||
// -------------------------------------------------
|
||||
|
||||
case AcosOp:
|
||||
// sqrt(1 - x * x), acos(x)
|
||||
CPPAD_ASSERT_UNKNOWN( i_var < numvar );
|
||||
forward_acos_op_dir(q, r, i_var, arg[0], J, taylor);
|
||||
break;
|
||||
// -------------------------------------------------
|
||||
|
||||
# if CPPAD_USE_CPLUSPLUS_2011
|
||||
case AcoshOp:
|
||||
// sqrt(x * x - 1), acosh(x)
|
||||
CPPAD_ASSERT_UNKNOWN( i_var < numvar );
|
||||
forward_acosh_op_dir(q, r, i_var, arg[0], J, taylor);
|
||||
break;
|
||||
# endif
|
||||
// -------------------------------------------------
|
||||
|
||||
case AsinOp:
|
||||
// sqrt(1 - x * x), asin(x)
|
||||
CPPAD_ASSERT_UNKNOWN( i_var < numvar );
|
||||
forward_asin_op_dir(q, r, i_var, arg[0], J, taylor);
|
||||
break;
|
||||
// -------------------------------------------------
|
||||
|
||||
# if CPPAD_USE_CPLUSPLUS_2011
|
||||
case AsinhOp:
|
||||
// sqrt(1 + x * x), asinh(x)
|
||||
CPPAD_ASSERT_UNKNOWN( i_var < numvar );
|
||||
forward_asinh_op_dir(q, r, i_var, arg[0], J, taylor);
|
||||
break;
|
||||
# endif
|
||||
// -------------------------------------------------
|
||||
|
||||
case AtanOp:
|
||||
// 1 + x * x, atan(x)
|
||||
CPPAD_ASSERT_UNKNOWN( i_var < numvar );
|
||||
forward_atan_op_dir(q, r, i_var, arg[0], J, taylor);
|
||||
break;
|
||||
// -------------------------------------------------
|
||||
|
||||
# if CPPAD_USE_CPLUSPLUS_2011
|
||||
case AtanhOp:
|
||||
// 1 - x * x, atanh(x)
|
||||
CPPAD_ASSERT_UNKNOWN( i_var < numvar );
|
||||
forward_atanh_op_dir(q, r, i_var, arg[0], J, taylor);
|
||||
break;
|
||||
# endif
|
||||
// -------------------------------------------------
|
||||
|
||||
case CExpOp:
|
||||
forward_cond_op_dir(
|
||||
q, r, i_var, arg, num_par, parameter, J, taylor
|
||||
);
|
||||
break;
|
||||
// ---------------------------------------------------
|
||||
|
||||
case CosOp:
|
||||
// sin(x), cos(x)
|
||||
CPPAD_ASSERT_UNKNOWN( i_var < numvar );
|
||||
forward_cos_op_dir(q, r, i_var, arg[0], J, taylor);
|
||||
break;
|
||||
// ---------------------------------------------------
|
||||
|
||||
case CoshOp:
|
||||
// sinh(x), cosh(x)
|
||||
CPPAD_ASSERT_UNKNOWN( i_var < numvar );
|
||||
forward_cosh_op_dir(q, r, i_var, arg[0], J, taylor);
|
||||
break;
|
||||
// -------------------------------------------------
|
||||
|
||||
case CSkipOp:
|
||||
// CSkipOp has a variable number of arguments and
|
||||
// forward_next thinks it has no arguments.
|
||||
// we must inform forward_next of this special case.
|
||||
play->forward_cskip(op, arg, i_op, i_var);
|
||||
break;
|
||||
// -------------------------------------------------
|
||||
|
||||
case CSumOp:
|
||||
// CSumOp has a variable number of arguments and
|
||||
// forward_next thinks it has no arguments.
|
||||
// we must inform forward_next of this special case.
|
||||
forward_csum_op_dir(
|
||||
q, r, i_var, arg, num_par, parameter, J, taylor
|
||||
);
|
||||
play->forward_csum(op, arg, i_op, i_var);
|
||||
break;
|
||||
// -------------------------------------------------
|
||||
|
||||
case DisOp:
|
||||
forward_dis_op(p, q, r, i_var, arg, J, taylor);
|
||||
break;
|
||||
// -------------------------------------------------
|
||||
|
||||
case DivvvOp:
|
||||
forward_divvv_op_dir(q, r, i_var, arg, parameter, J, taylor);
|
||||
break;
|
||||
// -------------------------------------------------
|
||||
|
||||
case DivpvOp:
|
||||
CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < num_par );
|
||||
forward_divpv_op_dir(q, r, i_var, arg, parameter, J, taylor);
|
||||
break;
|
||||
// -------------------------------------------------
|
||||
|
||||
case DivvpOp:
|
||||
CPPAD_ASSERT_UNKNOWN( size_t(arg[1]) < num_par );
|
||||
forward_divvp_op_dir(q, r, i_var, arg, parameter, J, taylor);
|
||||
break;
|
||||
// -------------------------------------------------
|
||||
|
||||
case EndOp:
|
||||
// needed for sparse_jacobian test
|
||||
CPPAD_ASSERT_NARG_NRES(op, 0, 0);
|
||||
more_operators = false;
|
||||
break;
|
||||
// -------------------------------------------------
|
||||
|
||||
# if CPPAD_USE_CPLUSPLUS_2011
|
||||
case ErfOp:
|
||||
forward_erf_op_dir(q, r, i_var, arg, parameter, J, taylor);
|
||||
break;
|
||||
// -------------------------------------------------
|
||||
# endif
|
||||
|
||||
case ExpOp:
|
||||
forward_exp_op_dir(q, r, i_var, arg[0], J, taylor);
|
||||
break;
|
||||
// -------------------------------------------------
|
||||
|
||||
# if CPPAD_USE_CPLUSPLUS_2011
|
||||
case Expm1Op:
|
||||
forward_expm1_op_dir(q, r, i_var, arg[0], J, taylor);
|
||||
break;
|
||||
# endif
|
||||
// -------------------------------------------------
|
||||
|
||||
case InvOp:
|
||||
CPPAD_ASSERT_NARG_NRES(op, 0, 1);
|
||||
break;
|
||||
// -------------------------------------------------
|
||||
|
||||
case LdpOp:
|
||||
case LdvOp:
|
||||
forward_load_op(
|
||||
play,
|
||||
op,
|
||||
p,
|
||||
q,
|
||||
r,
|
||||
J,
|
||||
i_var,
|
||||
arg,
|
||||
var_by_load_op.data(),
|
||||
taylor
|
||||
);
|
||||
break;
|
||||
// ---------------------------------------------------
|
||||
|
||||
case EqpvOp:
|
||||
case EqvvOp:
|
||||
case LtpvOp:
|
||||
case LtvpOp:
|
||||
case LtvvOp:
|
||||
case LepvOp:
|
||||
case LevpOp:
|
||||
case LevvOp:
|
||||
case NepvOp:
|
||||
case NevvOp:
|
||||
CPPAD_ASSERT_UNKNOWN(q > 0 );
|
||||
break;
|
||||
// -------------------------------------------------
|
||||
|
||||
case LogOp:
|
||||
forward_log_op_dir(q, r, i_var, arg[0], J, taylor);
|
||||
break;
|
||||
// ---------------------------------------------------
|
||||
|
||||
# if CPPAD_USE_CPLUSPLUS_2011
|
||||
case Log1pOp:
|
||||
forward_log1p_op_dir(q, r, i_var, arg[0], J, taylor);
|
||||
break;
|
||||
# endif
|
||||
// ---------------------------------------------------
|
||||
|
||||
case MulpvOp:
|
||||
CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < num_par );
|
||||
forward_mulpv_op_dir(q, r, i_var, arg, parameter, J, taylor);
|
||||
break;
|
||||
// -------------------------------------------------
|
||||
|
||||
case MulvvOp:
|
||||
forward_mulvv_op_dir(q, r, i_var, arg, parameter, J, taylor);
|
||||
break;
|
||||
// -------------------------------------------------
|
||||
|
||||
case ParOp:
|
||||
k = i_var*(J-1)*r + i_var + (q-1)*r + 1;
|
||||
for(ell = 0; ell < r; ell++)
|
||||
taylor[k + ell] = Base(0.0);
|
||||
break;
|
||||
// -------------------------------------------------
|
||||
|
||||
case PowpvOp:
|
||||
CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < num_par );
|
||||
forward_powpv_op_dir(q, r, i_var, arg, parameter, J, taylor);
|
||||
break;
|
||||
// -------------------------------------------------
|
||||
|
||||
case PowvpOp:
|
||||
CPPAD_ASSERT_UNKNOWN( size_t(arg[1]) < num_par );
|
||||
forward_powvp_op_dir(q, r, i_var, arg, parameter, J, taylor);
|
||||
break;
|
||||
// -------------------------------------------------
|
||||
|
||||
case PowvvOp:
|
||||
forward_powvv_op_dir(q, r, i_var, arg, parameter, J, taylor);
|
||||
break;
|
||||
// -------------------------------------------------
|
||||
|
||||
case PriOp:
|
||||
CPPAD_ASSERT_UNKNOWN(q > 0);
|
||||
break;
|
||||
// -------------------------------------------------
|
||||
|
||||
case SignOp:
|
||||
// sign(x)
|
||||
CPPAD_ASSERT_UNKNOWN( i_var < numvar );
|
||||
forward_sign_op_dir(q, r, i_var, arg[0], J, taylor);
|
||||
break;
|
||||
// -------------------------------------------------
|
||||
|
||||
case SinOp:
|
||||
// cos(x), sin(x)
|
||||
CPPAD_ASSERT_UNKNOWN( i_var < numvar );
|
||||
forward_sin_op_dir(q, r, i_var, arg[0], J, taylor);
|
||||
break;
|
||||
// -------------------------------------------------
|
||||
|
||||
case SinhOp:
|
||||
// cosh(x), sinh(x)
|
||||
CPPAD_ASSERT_UNKNOWN( i_var < numvar );
|
||||
forward_sinh_op_dir(q, r, i_var, arg[0], J, taylor);
|
||||
break;
|
||||
// -------------------------------------------------
|
||||
|
||||
case SqrtOp:
|
||||
forward_sqrt_op_dir(q, r, i_var, arg[0], J, taylor);
|
||||
break;
|
||||
// -------------------------------------------------
|
||||
|
||||
case StppOp:
|
||||
case StpvOp:
|
||||
case StvpOp:
|
||||
case StvvOp:
|
||||
CPPAD_ASSERT_UNKNOWN(q > 0 );
|
||||
break;
|
||||
// -------------------------------------------------
|
||||
|
||||
case SubvvOp:
|
||||
forward_subvv_op_dir(q, r, i_var, arg, parameter, J, taylor);
|
||||
break;
|
||||
// -------------------------------------------------
|
||||
|
||||
case SubpvOp:
|
||||
CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < num_par );
|
||||
forward_subpv_op_dir(q, r, i_var, arg, parameter, J, taylor);
|
||||
break;
|
||||
// -------------------------------------------------
|
||||
|
||||
case SubvpOp:
|
||||
CPPAD_ASSERT_UNKNOWN( size_t(arg[1]) < num_par );
|
||||
forward_subvp_op_dir(q, r, i_var, arg, parameter, J, taylor);
|
||||
break;
|
||||
// -------------------------------------------------
|
||||
|
||||
case TanOp:
|
||||
// tan(x)^2, tan(x)
|
||||
CPPAD_ASSERT_UNKNOWN( i_var < numvar );
|
||||
forward_tan_op_dir(q, r, i_var, arg[0], J, taylor);
|
||||
break;
|
||||
// -------------------------------------------------
|
||||
|
||||
case TanhOp:
|
||||
// tanh(x)^2, tanh(x)
|
||||
CPPAD_ASSERT_UNKNOWN( i_var < numvar );
|
||||
forward_tanh_op_dir(q, r, i_var, arg[0], J, taylor);
|
||||
break;
|
||||
// -------------------------------------------------
|
||||
|
||||
case UserOp:
|
||||
// start or end an atomic operation sequence
|
||||
flag = user_state == start_user;
|
||||
user_atom = play->forward_user(op, user_state,
|
||||
user_old, user_m, user_n, user_i, user_j
|
||||
);
|
||||
if( flag )
|
||||
{ user_tx_one.resize(user_n * user_q1);
|
||||
user_tx_all.resize(user_n * (q * r + 1));
|
||||
//
|
||||
user_ty_one.resize(user_m * user_q1);
|
||||
user_ty_all.resize(user_m * (q * r + 1));
|
||||
//
|
||||
user_iy.resize(user_m);
|
||||
}
|
||||
else
|
||||
{ // call users function for this operation
|
||||
user_atom->set_old(user_old);
|
||||
for(ell = 0; ell < r; ell++)
|
||||
{ // set user_tx
|
||||
for(j = 0; j < user_n; j++)
|
||||
{ size_t j_all = j * (q * r + 1);
|
||||
size_t j_one = j * user_q1;
|
||||
user_tx_one[j_one+0] = user_tx_all[j_all+0];
|
||||
for(k = 1; k < user_q1; k++)
|
||||
{ size_t k_all = j_all + (k-1)*r+1+ell;
|
||||
size_t k_one = j_one + k;
|
||||
user_tx_one[k_one] = user_tx_all[k_all];
|
||||
}
|
||||
}
|
||||
// set user_ty
|
||||
for(i = 0; i < user_m; i++)
|
||||
{ size_t i_all = i * (q * r + 1);
|
||||
size_t i_one = i * user_q1;
|
||||
user_ty_one[i_one+0] = user_ty_all[i_all+0];
|
||||
for(k = 1; k < q; k++)
|
||||
{ size_t k_all = i_all + (k-1)*r+1+ell;
|
||||
size_t k_one = i_one + k;
|
||||
user_ty_one[k_one] = user_ty_all[k_all];
|
||||
}
|
||||
}
|
||||
CPPAD_ATOMIC_CALL(
|
||||
q, q, user_vx, user_vy, user_tx_one, user_ty_one
|
||||
);
|
||||
# ifndef NDEBUG
|
||||
if( ! user_ok )
|
||||
{ std::string msg =
|
||||
user_atom->afun_name()
|
||||
+ ": atomic_base.forward: returned false";
|
||||
CPPAD_ASSERT_KNOWN(false, msg.c_str() );
|
||||
}
|
||||
# endif
|
||||
for(i = 0; i < user_m; i++)
|
||||
{ if( user_iy[i] > 0 )
|
||||
{ size_t i_taylor = user_iy[i]*((J-1)*r+1);
|
||||
size_t q_taylor = i_taylor + (q-1)*r+1+ell;
|
||||
size_t q_one = i * user_q1 + q;
|
||||
taylor[q_taylor] = user_ty_one[q_one];
|
||||
}
|
||||
}
|
||||
}
|
||||
# if CPPAD_FORWARD2SWEEP_TRACE
|
||||
user_trace = true;
|
||||
# endif
|
||||
}
|
||||
break;
|
||||
|
||||
case UsrapOp:
|
||||
// parameter argument in an atomic operation sequence
|
||||
user_tx_all[user_j*(q*r+1) + 0] = parameter[ arg[0]];
|
||||
for(ell = 0; ell < r; ell++)
|
||||
for(k = 1; k < user_q1; k++)
|
||||
user_tx_all[user_j*(q*r+1) + (k-1)*r+1+ell] = Base(0.0);
|
||||
play->forward_user(op, user_state,
|
||||
user_old, user_m, user_n, user_i, user_j
|
||||
);
|
||||
break;
|
||||
|
||||
case UsravOp:
|
||||
// variable argument in an atomic operation sequence
|
||||
user_tx_all[user_j*(q*r+1)+0] = taylor[arg[0]*((J-1)*r+1)+0];
|
||||
for(ell = 0; ell < r; ell++)
|
||||
{ for(k = 1; k < user_q1; k++)
|
||||
{ user_tx_all[user_j*(q*r+1) + (k-1)*r+1+ell] =
|
||||
taylor[arg[0]*((J-1)*r+1) + (k-1)*r+1+ell];
|
||||
}
|
||||
}
|
||||
play->forward_user(op, user_state,
|
||||
user_old, user_m, user_n, user_i, user_j
|
||||
);
|
||||
break;
|
||||
|
||||
case UsrrpOp:
|
||||
// parameter result in an atomic operation sequence
|
||||
user_iy[user_i] = 0;
|
||||
user_ty_all[user_i*(q*r+1) + 0] = parameter[ arg[0]];
|
||||
for(ell = 0; ell < r; ell++)
|
||||
for(k = 1; k < user_q1; k++)
|
||||
user_ty_all[user_i*(q*r+1) + (k-1)*r+1+ell] = Base(0.0);
|
||||
play->forward_user(op, user_state,
|
||||
user_old, user_m, user_n, user_i, user_j
|
||||
);
|
||||
break;
|
||||
|
||||
case UsrrvOp:
|
||||
// variable result in an atomic operation sequence
|
||||
user_iy[user_i] = i_var;
|
||||
user_ty_all[user_i*(q*r+1)+0] = taylor[i_var*((J-1)*r+1)+0];
|
||||
for(ell = 0; ell < r; ell++)
|
||||
{ for(k = 1; k < user_q1; k++)
|
||||
{ user_ty_all[user_i*(q*r+1) + (k-1)*r+1+ell] =
|
||||
taylor[i_var*((J-1)*r+1) + (k-1)*r+1+ell];
|
||||
}
|
||||
}
|
||||
play->forward_user(op, user_state,
|
||||
user_old, user_m, user_n, user_i, user_j
|
||||
);
|
||||
break;
|
||||
// -------------------------------------------------
|
||||
|
||||
case ZmulpvOp:
|
||||
CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < num_par );
|
||||
forward_zmulpv_op_dir(q, r, i_var, arg, parameter, J, taylor);
|
||||
break;
|
||||
// -------------------------------------------------
|
||||
|
||||
case ZmulvpOp:
|
||||
CPPAD_ASSERT_UNKNOWN( size_t(arg[1]) < num_par );
|
||||
forward_zmulvp_op_dir(q, r, i_var, arg, parameter, J, taylor);
|
||||
break;
|
||||
// -------------------------------------------------
|
||||
|
||||
case ZmulvvOp:
|
||||
forward_zmulvv_op_dir(q, r, i_var, arg, parameter, J, taylor);
|
||||
break;
|
||||
// -------------------------------------------------
|
||||
|
||||
default:
|
||||
CPPAD_ASSERT_UNKNOWN(0);
|
||||
}
|
||||
# if CPPAD_FORWARD2SWEEP_TRACE
|
||||
if( user_trace )
|
||||
{ user_trace = false;
|
||||
CPPAD_ASSERT_UNKNOWN( op == UserOp );
|
||||
CPPAD_ASSERT_UNKNOWN( NumArg(UsrrvOp) == 0 );
|
||||
for(i = 0; i < user_m; i++) if( user_iy[i] > 0 )
|
||||
{ size_t i_tmp = (i_op + i) - user_m;
|
||||
printOp(
|
||||
std::cout,
|
||||
play,
|
||||
i_tmp,
|
||||
user_iy[i],
|
||||
UsrrvOp,
|
||||
CPPAD_NULL
|
||||
);
|
||||
Base* Z_tmp = taylor + user_iy[i]*((J-1) * r + 1);
|
||||
{ Z_vec[0] = Z_tmp[0];
|
||||
for(ell = 0; ell < r; ell++)
|
||||
{ std::cout << std::endl << " ";
|
||||
for(size_t p_tmp = 1; p_tmp <= q; p_tmp++)
|
||||
Z_vec[p_tmp] = Z_tmp[(p_tmp-1)*r+ell+1];
|
||||
printOpResult(
|
||||
std::cout,
|
||||
q + 1,
|
||||
Z_vec.data(),
|
||||
0,
|
||||
(Base *) CPPAD_NULL
|
||||
);
|
||||
}
|
||||
}
|
||||
std::cout << std::endl;
|
||||
}
|
||||
}
|
||||
const addr_t* arg_tmp = arg;
|
||||
if( op == CSumOp )
|
||||
arg_tmp = arg - arg[-1] - 4;
|
||||
if( op == CSkipOp )
|
||||
arg_tmp = arg - arg[-1] - 7;
|
||||
if( op != UsrrvOp )
|
||||
{ printOp(
|
||||
std::cout,
|
||||
play,
|
||||
i_op,
|
||||
i_var,
|
||||
op,
|
||||
arg_tmp
|
||||
);
|
||||
Base* Z_tmp = CPPAD_NULL;
|
||||
if( op == UsravOp )
|
||||
Z_tmp = taylor + arg[0]*((J-1) * r + 1);
|
||||
else if( NumRes(op) > 0 )
|
||||
Z_tmp = taylor + i_var*((J-1)*r + 1);
|
||||
if( Z_tmp != CPPAD_NULL )
|
||||
{ Z_vec[0] = Z_tmp[0];
|
||||
for(ell = 0; ell < r; ell++)
|
||||
{ std::cout << std::endl << " ";
|
||||
for(size_t p_tmp = 1; p_tmp <= q; p_tmp++)
|
||||
Z_vec[p_tmp] = Z_tmp[ (p_tmp-1)*r + ell + 1];
|
||||
printOpResult(
|
||||
std::cout,
|
||||
q + 1,
|
||||
Z_vec.data(),
|
||||
0,
|
||||
(Base *) CPPAD_NULL
|
||||
);
|
||||
}
|
||||
}
|
||||
std::cout << std::endl;
|
||||
}
|
||||
}
|
||||
std::cout << std::endl;
|
||||
# else
|
||||
}
|
||||
# endif
|
||||
CPPAD_ASSERT_UNKNOWN( user_state == start_user );
|
||||
CPPAD_ASSERT_UNKNOWN( i_var + 1 == play->num_var_rec() );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// preprocessor symbols that are local to this file
|
||||
# undef CPPAD_FORWARD2SWEEP_TRACE
|
||||
# undef CPPAD_ATOMIC_CALL
|
||||
|
||||
} } // END_CPPAD_LOCAL_NAMESPACE
|
||||
# endif
|
||||
+251
@@ -0,0 +1,251 @@
|
||||
# ifndef CPPAD_LOCAL_HASH_CODE_HPP
|
||||
# define CPPAD_LOCAL_HASH_CODE_HPP
|
||||
|
||||
/* --------------------------------------------------------------------------
|
||||
CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-17 Bradley M. Bell
|
||||
|
||||
CppAD is distributed under multiple licenses. This distribution is under
|
||||
the terms of the
|
||||
Eclipse Public License Version 1.0.
|
||||
|
||||
A copy of this license is included in the COPYING file of this distribution.
|
||||
Please visit http://www.coin-or.org/CppAD/ for information on other licenses.
|
||||
-------------------------------------------------------------------------- */
|
||||
# include <cppad/core/base_hash.hpp>
|
||||
/*!
|
||||
\file local/hash_code.hpp
|
||||
CppAD hashing utility.
|
||||
*/
|
||||
|
||||
|
||||
namespace CppAD { namespace local { // BEGIN_CPPAD_LOCAL_NAMESPACE
|
||||
/*!
|
||||
General purpose hash code for an arbitrary value.
|
||||
|
||||
\tparam Value
|
||||
is the type of the argument being hash coded.
|
||||
It should be a plain old data class; i.e.,
|
||||
the values included in the equality operator in the object and
|
||||
not pointed to by the object.
|
||||
|
||||
\param value
|
||||
the value that we are generating a hash code for.
|
||||
All of the fields in value should have been set before the hash code
|
||||
is computed (otherwise undefined values are used).
|
||||
|
||||
\return
|
||||
is a hash code that is between zero and CPPAD_HASH_TABLE_SIZE - 1.
|
||||
|
||||
\par Checked Assertions
|
||||
\li \c std::numeric_limits<unsigned short>::max() >= CPPAD_HASH_TABLE_SIZE
|
||||
\li \c sizeof(value) is even
|
||||
\li \c sizeof(unsigned short) == 2
|
||||
*/
|
||||
template <class Value>
|
||||
unsigned short local_hash_code(const Value& value)
|
||||
{ CPPAD_ASSERT_UNKNOWN(
|
||||
std::numeric_limits<unsigned short>::max()
|
||||
>=
|
||||
CPPAD_HASH_TABLE_SIZE
|
||||
);
|
||||
CPPAD_ASSERT_UNKNOWN( sizeof(unsigned short) == 2 );
|
||||
CPPAD_ASSERT_UNKNOWN( sizeof(value) % 2 == 0 );
|
||||
//
|
||||
const unsigned short* v
|
||||
= reinterpret_cast<const unsigned short*>(& value);
|
||||
//
|
||||
size_t i = sizeof(value) / 2 - 1;
|
||||
//
|
||||
size_t sum = v[i];
|
||||
//
|
||||
while(i--)
|
||||
sum += v[i];
|
||||
//
|
||||
unsigned short code = static_cast<unsigned short>(
|
||||
sum % CPPAD_HASH_TABLE_SIZE
|
||||
);
|
||||
return code;
|
||||
}
|
||||
|
||||
/*!
|
||||
Specialized hash code for a CppAD operator and its arguments.
|
||||
|
||||
\param op
|
||||
is the operator that we are computing a hash code for.
|
||||
If it is not one of the following operartors, the operator is not
|
||||
hash coded and zero is returned:
|
||||
|
||||
\li unary operators:
|
||||
AbsOp, AcosOp, AcoshOp, AsinOp, AsinhOp, AtanOp, AtanhOp, CosOp, CoshOp
|
||||
ExpOp, Expm1Op, LogOp, Log1pOp, SinOp, SinhOp, SqrtOp, TanOp, TanhOp
|
||||
|
||||
\li binary operators where first argument is a parameter:
|
||||
AddpvOp, DivpvOp, MulpvOp, PowpvOp, SubpvOp, ZmulpvOp
|
||||
|
||||
\li binary operators where second argument is a parameter:
|
||||
DivvpOp, PowvpOp, SubvpOp, Zmulvp
|
||||
|
||||
\li binary operators where first is an index and second is a variable:
|
||||
DisOp
|
||||
|
||||
\li binary operators where both arguments are variables:
|
||||
AddvvOp, DivvvOp, MulvvOp, PowvvOp, SubvvOp, ZmulvvOp
|
||||
|
||||
\param arg
|
||||
is a vector of length \c NumArg(op) or 2 (which ever is smaller),
|
||||
containing the corresponding argument indices for this operator.
|
||||
|
||||
\param npar
|
||||
is the number of parameters corresponding to this operation sequence.
|
||||
|
||||
\param par
|
||||
is a vector of length \a npar containing the parameters
|
||||
for this operation sequence; i.e.,
|
||||
given a parameter index of \c i, the corresponding parameter value is
|
||||
\a par[i].
|
||||
|
||||
|
||||
\return
|
||||
is a hash code that is between zero and CPPAD_HASH_TABLE_SIZE - 1.
|
||||
|
||||
\par Checked Assertions
|
||||
\c op must be one of the operators specified above. In addition,
|
||||
\li \c std::numeric_limits<unsigned short>::max() >= CPPAD_HASH_TABLE_SIZE
|
||||
\li \c sizeof(size_t) is even
|
||||
\li \c sizeof(Base) is even
|
||||
\li \c sizeof(unsigned short) == 2
|
||||
\li \c size_t(op) < size_t(NumberOp) <= CPPAD_HASH_TABLE_SIZE
|
||||
\li if the j-th argument for this operation is a parameter, arg[j] < npar.
|
||||
*/
|
||||
|
||||
template <class Base>
|
||||
unsigned short local_hash_code(
|
||||
OpCode op ,
|
||||
const addr_t* arg ,
|
||||
size_t npar ,
|
||||
const Base* par )
|
||||
{ CPPAD_ASSERT_UNKNOWN(
|
||||
std::numeric_limits<unsigned short>::max()
|
||||
>=
|
||||
CPPAD_HASH_TABLE_SIZE
|
||||
);
|
||||
CPPAD_ASSERT_UNKNOWN( size_t (op) < size_t(NumberOp) );
|
||||
CPPAD_ASSERT_UNKNOWN( sizeof(unsigned short) == 2 );
|
||||
CPPAD_ASSERT_UNKNOWN( sizeof(addr_t) % 2 == 0 );
|
||||
CPPAD_ASSERT_UNKNOWN( sizeof(Base) % 2 == 0 );
|
||||
unsigned short op_fac = static_cast<unsigned short> (
|
||||
CPPAD_HASH_TABLE_SIZE / static_cast<unsigned short>(NumberOp)
|
||||
);
|
||||
CPPAD_ASSERT_UNKNOWN( op_fac > 0 );
|
||||
|
||||
// number of shorts per addr_t value
|
||||
size_t short_addr_t = sizeof(addr_t) / 2;
|
||||
|
||||
// number of shorts per Base value
|
||||
size_t short_base = sizeof(Base) / 2;
|
||||
|
||||
// initialize with value that separates operators as much as possible
|
||||
unsigned short code = static_cast<unsigned short>(
|
||||
static_cast<unsigned short>(op) * op_fac
|
||||
);
|
||||
|
||||
// now code in the operands
|
||||
size_t i;
|
||||
const unsigned short* v;
|
||||
|
||||
// first argument
|
||||
switch(op)
|
||||
{ // Binary operators where first arugment is a parameter.
|
||||
// Code parameters by value instead of
|
||||
// by index for two reasons. One, it gives better separation.
|
||||
// Two, different indices can be same parameter value.
|
||||
case AddpvOp:
|
||||
case DivpvOp:
|
||||
case MulpvOp:
|
||||
case PowpvOp:
|
||||
case SubpvOp:
|
||||
case ZmulpvOp:
|
||||
CPPAD_ASSERT_UNKNOWN( NumArg(op) == 2 );
|
||||
v = reinterpret_cast<const unsigned short*>(par + arg[0]);
|
||||
i = short_base;
|
||||
while(i--)
|
||||
code += v[i];
|
||||
v = reinterpret_cast<const unsigned short*>(arg + 1);
|
||||
i = short_addr_t;
|
||||
while(i--)
|
||||
code += v[i];
|
||||
break;
|
||||
|
||||
// Binary operator where first argument is an index and
|
||||
// second is a variable (same as both variables).
|
||||
case DisOp:
|
||||
|
||||
// Binary operators where both arguments are variables
|
||||
case AddvvOp:
|
||||
case DivvvOp:
|
||||
case MulvvOp:
|
||||
case PowvvOp:
|
||||
case SubvvOp:
|
||||
case ZmulvvOp:
|
||||
CPPAD_ASSERT_UNKNOWN( NumArg(op) == 2 );
|
||||
v = reinterpret_cast<const unsigned short*>(arg + 0);
|
||||
i = 2 * short_addr_t;
|
||||
while(i--)
|
||||
code += v[i];
|
||||
break;
|
||||
|
||||
// Binary operators where second arugment is a parameter.
|
||||
case DivvpOp:
|
||||
case PowvpOp:
|
||||
case SubvpOp:
|
||||
case ZmulvpOp:
|
||||
CPPAD_ASSERT_UNKNOWN( NumArg(op) == 2 );
|
||||
v = reinterpret_cast<const unsigned short*>(arg + 0);
|
||||
i = short_addr_t;
|
||||
while(i--)
|
||||
code += v[i];
|
||||
v = reinterpret_cast<const unsigned short*>(par + arg[1]);
|
||||
i = short_base;
|
||||
while(i--)
|
||||
code += v[i];
|
||||
break;
|
||||
|
||||
// Unary operators
|
||||
case AbsOp:
|
||||
case AcosOp:
|
||||
case AcoshOp:
|
||||
case AsinOp:
|
||||
case AsinhOp:
|
||||
case AtanOp:
|
||||
case AtanhOp:
|
||||
case CosOp:
|
||||
case CoshOp:
|
||||
case ErfOp:
|
||||
case ExpOp:
|
||||
case Expm1Op:
|
||||
case LogOp:
|
||||
case Log1pOp:
|
||||
case SignOp:
|
||||
case SinOp:
|
||||
case SinhOp:
|
||||
case SqrtOp:
|
||||
case TanOp:
|
||||
case TanhOp:
|
||||
CPPAD_ASSERT_UNKNOWN( NumArg(op) == 1 || op == ErfOp );
|
||||
v = reinterpret_cast<const unsigned short*>(arg + 0);
|
||||
i = short_addr_t;
|
||||
while(i--)
|
||||
code += v[i];
|
||||
break;
|
||||
|
||||
// should have been one of he cases above
|
||||
default:
|
||||
CPPAD_ASSERT_UNKNOWN(false);
|
||||
}
|
||||
|
||||
return code % CPPAD_HASH_TABLE_SIZE;
|
||||
}
|
||||
|
||||
} } // END_CPPAD_LOCAL_NAMESPACE
|
||||
|
||||
# endif
|
||||
@@ -0,0 +1,74 @@
|
||||
// $Id: independent.hpp 3845 2016-11-19 01:50:47Z bradbell $
|
||||
# ifndef CPPAD_LOCAL_INDEPENDENT_HPP
|
||||
# define CPPAD_LOCAL_INDEPENDENT_HPP
|
||||
|
||||
/* --------------------------------------------------------------------------
|
||||
CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-16 Bradley M. Bell
|
||||
|
||||
CppAD is distributed under multiple licenses. This distribution is under
|
||||
the terms of the
|
||||
Eclipse Public License Version 1.0.
|
||||
|
||||
A copy of this license is included in the COPYING file of this distribution.
|
||||
Please visit http://www.coin-or.org/CppAD/ for information on other licenses.
|
||||
-------------------------------------------------------------------------- */
|
||||
namespace CppAD { namespace local { // BEGIN_CPPAD_LOCAL_NAMESPACE
|
||||
/*
|
||||
\file local/independent.hpp
|
||||
Implement the declaration of the independent variables
|
||||
*/
|
||||
|
||||
/*!
|
||||
Implementation of the declaration of independent variables (in local namespace).
|
||||
|
||||
\tparam VectorAD
|
||||
This is simple vector type with elements of type AD<Base>.
|
||||
|
||||
\param x
|
||||
Vector of the independent variablerd.
|
||||
|
||||
\param abort_op_index
|
||||
operator index at which execution will be aborted (during the recording
|
||||
of operations). The value zero corresponds to not aborting (will not match).
|
||||
*/
|
||||
template <typename Base>
|
||||
template <typename VectorAD>
|
||||
void ADTape<Base>::Independent(VectorAD &x, size_t abort_op_index)
|
||||
{
|
||||
// check VectorAD is Simple Vector class with AD<Base> elements
|
||||
CheckSimpleVector< AD<Base>, VectorAD>();
|
||||
|
||||
// dimension of the domain space
|
||||
size_t n = x.size();
|
||||
CPPAD_ASSERT_KNOWN(
|
||||
n > 0,
|
||||
"Indepdendent: the argument vector x has zero size"
|
||||
);
|
||||
CPPAD_ASSERT_UNKNOWN( Rec_.num_var_rec() == 0 );
|
||||
|
||||
// set the abort index before doing anything else
|
||||
Rec_.set_abort_op_index(abort_op_index);
|
||||
|
||||
// mark the beginning of the tape and skip the first variable index
|
||||
// (zero) because parameters use taddr zero
|
||||
CPPAD_ASSERT_NARG_NRES(BeginOp, 1, 1);
|
||||
Rec_.PutOp(BeginOp);
|
||||
Rec_.PutArg(0);
|
||||
|
||||
// place each of the independent variables in the tape
|
||||
CPPAD_ASSERT_NARG_NRES(InvOp, 0, 1);
|
||||
size_t j;
|
||||
for(j = 0; j < n; j++)
|
||||
{ // tape address for this independent variable
|
||||
x[j].taddr_ = Rec_.PutOp(InvOp);
|
||||
x[j].tape_id_ = id_;
|
||||
CPPAD_ASSERT_UNKNOWN( size_t(x[j].taddr_) == j+1 );
|
||||
CPPAD_ASSERT_UNKNOWN( Variable(x[j] ) );
|
||||
}
|
||||
|
||||
// done specifying all of the independent variables
|
||||
size_independent_ = n;
|
||||
}
|
||||
} } // END_CPPAD_LOCAL_NAMESPACE
|
||||
|
||||
# endif
|
||||
+689
@@ -0,0 +1,689 @@
|
||||
# ifndef CPPAD_LOCAL_LOAD_OP_HPP
|
||||
# define CPPAD_LOCAL_LOAD_OP_HPP
|
||||
|
||||
/* --------------------------------------------------------------------------
|
||||
CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-17 Bradley M. Bell
|
||||
|
||||
CppAD is distributed under multiple licenses. This distribution is under
|
||||
the terms of the
|
||||
Eclipse Public License Version 1.0.
|
||||
|
||||
A copy of this license is included in the COPYING file of this distribution.
|
||||
Please visit http://www.coin-or.org/CppAD/ for information on other licenses.
|
||||
-------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
namespace CppAD { namespace local { // BEGIN_CPPAD_LOCAL_NAMESPACE
|
||||
/*!
|
||||
\file load_op.hpp
|
||||
Setting a variable so that it corresponds to current value of a VecAD element.
|
||||
*/
|
||||
/*
|
||||
==============================================================================
|
||||
<!-- define preamble -->
|
||||
The C++ source code corresponding to this operation is
|
||||
\verbatim
|
||||
v[x] = y
|
||||
\endverbatim
|
||||
where v is a VecAD<Base> vector, x is an AD<Base> object,
|
||||
and y is AD<Base> or Base objects.
|
||||
We define the index corresponding to v[x] by
|
||||
\verbatim
|
||||
i_v_x = index_by_ind[ arg[0] + i_vec ]
|
||||
\endverbatim
|
||||
where i_vec is defined under the heading arg[1] below:
|
||||
<!-- end preamble -->
|
||||
==============================================================================
|
||||
*/
|
||||
/*!
|
||||
Shared documentation for zero order forward mode implementation of
|
||||
op = LdpOp or LdvOp (not called).
|
||||
|
||||
<!-- replace preamble -->
|
||||
The C++ source code corresponding to this operation is
|
||||
\verbatim
|
||||
v[x] = y
|
||||
\endverbatim
|
||||
where v is a VecAD<Base> vector, x is an AD<Base> object,
|
||||
and y is AD<Base> or Base objects.
|
||||
We define the index corresponding to v[x] by
|
||||
\verbatim
|
||||
i_v_x = index_by_ind[ arg[0] + i_vec ]
|
||||
\endverbatim
|
||||
where i_vec is defined under the heading arg[1] below:
|
||||
<!-- end preamble -->
|
||||
|
||||
\tparam Base
|
||||
base type for the operator; i.e., this operation was recorded
|
||||
using AD<Base> and computations by this routine are done using type Base.
|
||||
|
||||
\param play
|
||||
is the tape that this operation appears in.
|
||||
This is for error detection and not used when NDEBUG is defined.
|
||||
|
||||
\param i_z
|
||||
is the AD variable index corresponding to the variable z.
|
||||
|
||||
\param arg
|
||||
\n
|
||||
arg[0]
|
||||
is the offset of this VecAD vector relative to the beginning
|
||||
of the isvar_by_ind and index_by_ind arrays.
|
||||
\n
|
||||
\n
|
||||
arg[1]
|
||||
\n
|
||||
If this is the LdpOp operation (if x is a parameter),
|
||||
i_vec is defined by
|
||||
\verbatim
|
||||
i_vec = arg[1]
|
||||
\endverbatim
|
||||
If this is the LdvOp operation (if x is a variable),
|
||||
i_vec is defined by
|
||||
\verbatim
|
||||
i_vec = floor( taylor[ arg[1] * cap_order + 0 ] )
|
||||
\endverbatim
|
||||
where floor(c) is the greatest integer less that or equal c.
|
||||
\n
|
||||
\n
|
||||
arg[2]
|
||||
Is the index of this vecad load instruction in the
|
||||
var_by_load_op array.
|
||||
|
||||
\param parameter
|
||||
If v[x] is a parameter, <code>parameter[ i_v_x ]</code> is its value.
|
||||
This vector has size play->num_par_rec().
|
||||
|
||||
\param cap_order
|
||||
number of columns in the matrix containing the Taylor coefficients.
|
||||
|
||||
\param taylor
|
||||
\n
|
||||
Input
|
||||
\n
|
||||
In LdvOp case, <code>taylor[ arg[1] * cap_order + 0 ]</code>
|
||||
is used to compute the index in the definition of i_vec above.
|
||||
If v[x] is a variable, <code>taylor[ i_v_x * cap_order + 0 ]</code>
|
||||
is the zero order Taylor coefficient for v[x].
|
||||
\n
|
||||
\n
|
||||
Output
|
||||
\n
|
||||
<code>taylor[ i_z * cap_order + 0 ]</code>
|
||||
is set to the zero order Taylor coefficient for the variable z.
|
||||
|
||||
\param isvar_by_ind
|
||||
If <code>isvar_by_ind[ arg[0] + i_vec ] </code> is true,
|
||||
v[x] is a variable. Otherwise it is a parameter.
|
||||
This vector has size play->num_vec_ind_rec().
|
||||
|
||||
\param index_by_ind
|
||||
<code>index_by_ind[ arg[0] - 1 ]</code>
|
||||
is the number of elements in the user vector containing this element.
|
||||
<code>index_by_ind[ arg[0] + i_vec ]</code> is the variable or
|
||||
parameter index for this element,
|
||||
This array has size play->num_vec_ind_rec().
|
||||
|
||||
\param var_by_load_op
|
||||
is a vector with size play->num_load_op_rec().
|
||||
The input value of its elements does not matter.
|
||||
Upon return, it contains the variable index corresponding to each load
|
||||
instruction.
|
||||
In the case where the index is zero,
|
||||
the instruction corresponds to a parameter (not variable).
|
||||
This array has size play->num_load_op_rec().
|
||||
|
||||
\par Check User Errors
|
||||
\li In the LdvOp case check that the index is with in range; i.e.
|
||||
<code>i_vec < index_by_ind[ arg[0] - 1 ]</code>.
|
||||
Note that, if x is a parameter,
|
||||
the corresponding vector index and it does not change.
|
||||
In this case, the error above should be detected during tape recording.
|
||||
*/
|
||||
template <class Base>
|
||||
inline void forward_load_op_0(
|
||||
local::player<Base>* play ,
|
||||
size_t i_z ,
|
||||
const addr_t* arg ,
|
||||
const Base* parameter ,
|
||||
size_t cap_order ,
|
||||
Base* taylor ,
|
||||
bool* isvar_by_ind ,
|
||||
size_t* index_by_ind ,
|
||||
addr_t* var_by_load_op )
|
||||
{
|
||||
// This routine is only for documentaiton, it should not be used
|
||||
CPPAD_ASSERT_UNKNOWN( false );
|
||||
}
|
||||
/*!
|
||||
Shared documentation for sparsity operations corresponding to
|
||||
op = LdpOp or LdvOp (not called).
|
||||
|
||||
<!-- replace preamble -->
|
||||
The C++ source code corresponding to this operation is
|
||||
\verbatim
|
||||
v[x] = y
|
||||
\endverbatim
|
||||
where v is a VecAD<Base> vector, x is an AD<Base> object,
|
||||
and y is AD<Base> or Base objects.
|
||||
We define the index corresponding to v[x] by
|
||||
\verbatim
|
||||
i_v_x = index_by_ind[ arg[0] + i_vec ]
|
||||
\endverbatim
|
||||
where i_vec is defined under the heading arg[1] below:
|
||||
<!-- end preamble -->
|
||||
|
||||
\tparam Vector_set
|
||||
is the type used for vectors of sets. It can be either
|
||||
sparse_pack or sparse_list.
|
||||
|
||||
\param op
|
||||
is the code corresponding to this operator;
|
||||
i.e., LdpOp or LdvOp.
|
||||
|
||||
\param i_z
|
||||
is the AD variable index corresponding to the variable z; i.e.,
|
||||
the set with index \a i_z in \a var_sparsity is the sparsity pattern
|
||||
correpsonding to z.
|
||||
|
||||
\param arg
|
||||
\n
|
||||
\a arg[0]
|
||||
is the offset corresponding to this VecAD vector in the VecAD combined array.
|
||||
|
||||
\param num_combined
|
||||
is the total number of elements in the VecAD combinded array.
|
||||
|
||||
\param combined
|
||||
is the VecAD combined array.
|
||||
\n
|
||||
\n
|
||||
\a combined[ \a arg[0] - 1 ]
|
||||
is the index of the set corresponding to the vector v in \a vecad_sparsity.
|
||||
We use the notation i_v for this value; i.e.,
|
||||
\verbatim
|
||||
i_v = combined[ \a arg[0] - 1 ]
|
||||
\endverbatim
|
||||
|
||||
\param var_sparsity
|
||||
The set with index \a i_z in \a var_sparsity is the sparsity pattern for z.
|
||||
This is an output for forward mode operations,
|
||||
and an input for reverse mode operations.
|
||||
|
||||
\param vecad_sparsity
|
||||
The set with index \a i_v is the sparsity pattern for the vector v.
|
||||
This is an input for forward mode operations.
|
||||
For reverse mode operations,
|
||||
the sparsity pattern for z is added to the sparsity pattern for v.
|
||||
|
||||
\par Checked Assertions
|
||||
\li NumArg(op) == 3
|
||||
\li NumRes(op) == 1
|
||||
\li 0 < \a arg[0]
|
||||
\li \a arg[0] < \a num_combined
|
||||
\li i_v < \a vecad_sparsity.n_set()
|
||||
*/
|
||||
template <class Vector_set>
|
||||
inline void sparse_load_op(
|
||||
OpCode op ,
|
||||
size_t i_z ,
|
||||
const addr_t* arg ,
|
||||
size_t num_combined ,
|
||||
const size_t* combined ,
|
||||
Vector_set& var_sparsity ,
|
||||
Vector_set& vecad_sparsity )
|
||||
{
|
||||
// This routine is only for documentaiton, it should not be used
|
||||
CPPAD_ASSERT_UNKNOWN( false );
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
Zero order forward mode implementation of op = LdpOp.
|
||||
|
||||
\copydetails CppAD::local::forward_load_op_0
|
||||
*/
|
||||
template <class Base>
|
||||
inline void forward_load_p_op_0(
|
||||
local::player<Base>* play ,
|
||||
size_t i_z ,
|
||||
const addr_t* arg ,
|
||||
const Base* parameter ,
|
||||
size_t cap_order ,
|
||||
Base* taylor ,
|
||||
bool* isvar_by_ind ,
|
||||
size_t* index_by_ind ,
|
||||
addr_t* var_by_load_op )
|
||||
{ CPPAD_ASSERT_UNKNOWN( NumArg(LdpOp) == 3 );
|
||||
CPPAD_ASSERT_UNKNOWN( NumRes(LdpOp) == 1 );
|
||||
CPPAD_ASSERT_UNKNOWN( 0 < arg[0] );
|
||||
CPPAD_ASSERT_UNKNOWN( size_t(arg[2]) < play->num_load_op_rec() );
|
||||
CPPAD_ASSERT_UNKNOWN( std::numeric_limits<addr_t>::max() >= i_z );
|
||||
|
||||
// Because the index is a parameter, this indexing error should have been
|
||||
// caught and reported to the user when the tape is recording.
|
||||
size_t i_vec = arg[1];
|
||||
CPPAD_ASSERT_UNKNOWN( i_vec < index_by_ind[ arg[0] - 1 ] );
|
||||
CPPAD_ASSERT_UNKNOWN( arg[0] + i_vec < play->num_vec_ind_rec() );
|
||||
|
||||
size_t i_v_x = index_by_ind[ arg[0] + i_vec ];
|
||||
Base* z = taylor + i_z * cap_order;
|
||||
if( isvar_by_ind[ arg[0] + i_vec ] )
|
||||
{ CPPAD_ASSERT_UNKNOWN( i_v_x < i_z );
|
||||
var_by_load_op[ arg[2] ] = addr_t( i_v_x );
|
||||
Base* v_x = taylor + i_v_x * cap_order;
|
||||
z[0] = v_x[0];
|
||||
}
|
||||
else
|
||||
{ CPPAD_ASSERT_UNKNOWN( i_v_x < play->num_par_rec() );
|
||||
var_by_load_op[ arg[2] ] = 0;
|
||||
Base v_x = parameter[i_v_x];
|
||||
z[0] = v_x;
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
Zero order forward mode implementation of op = LdvOp.
|
||||
|
||||
\copydetails CppAD::local::forward_load_op_0
|
||||
*/
|
||||
template <class Base>
|
||||
inline void forward_load_v_op_0(
|
||||
local::player<Base>* play ,
|
||||
size_t i_z ,
|
||||
const addr_t* arg ,
|
||||
const Base* parameter ,
|
||||
size_t cap_order ,
|
||||
Base* taylor ,
|
||||
bool* isvar_by_ind ,
|
||||
size_t* index_by_ind ,
|
||||
addr_t* var_by_load_op )
|
||||
{ CPPAD_ASSERT_UNKNOWN( NumArg(LdvOp) == 3 );
|
||||
CPPAD_ASSERT_UNKNOWN( NumRes(LdvOp) == 1 );
|
||||
CPPAD_ASSERT_UNKNOWN( 0 < arg[0] );
|
||||
CPPAD_ASSERT_UNKNOWN( size_t(arg[2]) < play->num_load_op_rec() );
|
||||
CPPAD_ASSERT_UNKNOWN( std::numeric_limits<addr_t>::max() >= i_z );
|
||||
|
||||
size_t i_vec = Integer( taylor[ arg[1] * cap_order + 0 ] );
|
||||
CPPAD_ASSERT_KNOWN(
|
||||
i_vec < index_by_ind[ arg[0] - 1 ] ,
|
||||
"VecAD: index during zero order forward sweep is out of range"
|
||||
);
|
||||
CPPAD_ASSERT_UNKNOWN( arg[0] + i_vec < play->num_vec_ind_rec() );
|
||||
|
||||
size_t i_v_x = index_by_ind[ arg[0] + i_vec ];
|
||||
Base* z = taylor + i_z * cap_order;
|
||||
if( isvar_by_ind[ arg[0] + i_vec ] )
|
||||
{ CPPAD_ASSERT_UNKNOWN( i_v_x < i_z );
|
||||
var_by_load_op[ arg[2] ] = addr_t( i_v_x );
|
||||
Base* v_x = taylor + i_v_x * cap_order;
|
||||
z[0] = v_x[0];
|
||||
}
|
||||
else
|
||||
{ CPPAD_ASSERT_UNKNOWN( i_v_x < play->num_par_rec() );
|
||||
var_by_load_op[ arg[2] ] = 0;
|
||||
Base v_x = parameter[i_v_x];
|
||||
z[0] = v_x;
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
Forward mode, except for zero order, for op = LdpOp or op = LdvOp
|
||||
|
||||
|
||||
<!-- replace preamble -->
|
||||
The C++ source code corresponding to this operation is
|
||||
\verbatim
|
||||
v[x] = y
|
||||
\endverbatim
|
||||
where v is a VecAD<Base> vector, x is an AD<Base> object,
|
||||
and y is AD<Base> or Base objects.
|
||||
We define the index corresponding to v[x] by
|
||||
\verbatim
|
||||
i_v_x = index_by_ind[ arg[0] + i_vec ]
|
||||
\endverbatim
|
||||
where i_vec is defined under the heading arg[1] below:
|
||||
<!-- end preamble -->
|
||||
|
||||
\tparam Base
|
||||
base type for the operator; i.e., this operation was recorded
|
||||
using AD<Base> and computations by this routine are done using type Base.
|
||||
|
||||
\param play
|
||||
is the tape that this operation appears in.
|
||||
This is for error detection and not used when NDEBUG is defined.
|
||||
|
||||
\param op
|
||||
is the code corresponding to this operator; i.e., LdpOp or LdvOp
|
||||
(only used for error checking).
|
||||
|
||||
\param p
|
||||
is the lowest order of the Taylor coefficient that we are computing.
|
||||
|
||||
\param q
|
||||
is the highest order of the Taylor coefficient that we are computing.
|
||||
|
||||
\param r
|
||||
is the number of directions for the Taylor coefficients that we
|
||||
are computing.
|
||||
|
||||
\param cap_order
|
||||
number of columns in the matrix containing the Taylor coefficients.
|
||||
|
||||
\par tpv
|
||||
We use the notation
|
||||
<code>tpv = (cap_order-1) * r + 1</code>
|
||||
which is the number of Taylor coefficients per variable
|
||||
|
||||
\param i_z
|
||||
is the AD variable index corresponding to the variable z.
|
||||
|
||||
\param arg
|
||||
arg[2]
|
||||
Is the index of this vecad load instruction in the var_by_load_op array.
|
||||
|
||||
\param var_by_load_op
|
||||
is a vector with size play->num_load_op_rec().
|
||||
It contains the variable index corresponding to each load instruction.
|
||||
In the case where the index is zero,
|
||||
the instruction corresponds to a parameter (not variable).
|
||||
|
||||
\par i_var
|
||||
We use the notation
|
||||
\verbatim
|
||||
i_var = size_t( var_by_load_op[ arg[2] ] )
|
||||
\endverbatim
|
||||
|
||||
\param taylor
|
||||
\n
|
||||
Input
|
||||
\n
|
||||
If <code>i_var > 0</code>, v[x] is a variable and
|
||||
for k = 1 , ... , q
|
||||
<code>taylor[ i_var * tpv + (k-1)*r+1+ell ]</code>
|
||||
is the k-th order coefficient for v[x] in the ell-th direction,
|
||||
\n
|
||||
\n
|
||||
Output
|
||||
\n
|
||||
for k = p , ... , q,
|
||||
<code>taylor[ i_z * tpv + (k-1)*r+1+ell ]</code>
|
||||
is set to the k-order Taylor coefficient for z in the ell-th direction.
|
||||
*/
|
||||
template <class Base>
|
||||
inline void forward_load_op(
|
||||
const local::player<Base>* play ,
|
||||
OpCode op ,
|
||||
size_t p ,
|
||||
size_t q ,
|
||||
size_t r ,
|
||||
size_t cap_order ,
|
||||
size_t i_z ,
|
||||
const addr_t* arg ,
|
||||
const addr_t* var_by_load_op ,
|
||||
Base* taylor )
|
||||
{
|
||||
CPPAD_ASSERT_UNKNOWN( NumArg(op) == 3 );
|
||||
CPPAD_ASSERT_UNKNOWN( NumRes(op) == 1 );
|
||||
CPPAD_ASSERT_UNKNOWN( q < cap_order );
|
||||
CPPAD_ASSERT_UNKNOWN( 0 < r);
|
||||
CPPAD_ASSERT_UNKNOWN( 0 < p);
|
||||
CPPAD_ASSERT_UNKNOWN( p <= q );
|
||||
CPPAD_ASSERT_UNKNOWN( size_t(arg[2]) < play->num_load_op_rec() );
|
||||
|
||||
size_t i_var = size_t( var_by_load_op[ arg[2] ] );
|
||||
CPPAD_ASSERT_UNKNOWN( i_var < i_z );
|
||||
|
||||
size_t num_taylor_per_var = (cap_order-1) * r + 1;
|
||||
Base* z = taylor + i_z * num_taylor_per_var;
|
||||
if( i_var > 0 )
|
||||
{ Base* v_x = taylor + i_var * num_taylor_per_var;
|
||||
for(size_t ell = 0; ell < r; ell++)
|
||||
{ for(size_t k = p; k <= q; k++)
|
||||
{ size_t m = (k-1) * r + 1 + ell;
|
||||
z[m] = v_x[m];
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{ for(size_t ell = 0; ell < r; ell++)
|
||||
{ for(size_t k = p; k <= q; k++)
|
||||
{ size_t m = (k-1) * r + 1 + ell;
|
||||
z[m] = Base(0.0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
Reverse mode for op = LdpOp or LdvOp.
|
||||
|
||||
<!-- replace preamble -->
|
||||
The C++ source code corresponding to this operation is
|
||||
\verbatim
|
||||
v[x] = y
|
||||
\endverbatim
|
||||
where v is a VecAD<Base> vector, x is an AD<Base> object,
|
||||
and y is AD<Base> or Base objects.
|
||||
We define the index corresponding to v[x] by
|
||||
\verbatim
|
||||
i_v_x = index_by_ind[ arg[0] + i_vec ]
|
||||
\endverbatim
|
||||
where i_vec is defined under the heading arg[1] below:
|
||||
<!-- end preamble -->
|
||||
|
||||
This routine is given the partial derivatives of a function
|
||||
G(z , y[x] , w , u ... )
|
||||
and it uses them to compute the partial derivatives of
|
||||
\verbatim
|
||||
H( y[x] , w , u , ... ) = G[ z( y[x] ) , y[x] , w , u , ... ]
|
||||
\endverbatim
|
||||
|
||||
\tparam Base
|
||||
base type for the operator; i.e., this operation was recorded
|
||||
using AD< \a Base > and computations by this routine are done using type
|
||||
\a Base.
|
||||
|
||||
\param op
|
||||
is the code corresponding to this operator; i.e., LdpOp or LdvOp
|
||||
(only used for error checking).
|
||||
|
||||
\param d
|
||||
highest order the Taylor coefficient that we are computing the partial
|
||||
derivative with respect to.
|
||||
|
||||
\param i_z
|
||||
is the AD variable index corresponding to the variable z.
|
||||
|
||||
\param arg
|
||||
\a arg[2]
|
||||
Is the index of this vecad load instruction in the
|
||||
var_by_load_op array.
|
||||
|
||||
\param cap_order
|
||||
number of columns in the matrix containing the Taylor coefficients
|
||||
(not used).
|
||||
|
||||
\param taylor
|
||||
matrix of Taylor coefficients (not used).
|
||||
|
||||
\param nc_partial
|
||||
number of colums in the matrix containing all the partial derivatives
|
||||
(not used if \a arg[2] is zero).
|
||||
|
||||
\param partial
|
||||
If \a arg[2] is zero, y[x] is a parameter
|
||||
and no values need to be modified; i.e., \a partial is not used.
|
||||
Otherwise, y[x] is a variable and:
|
||||
\n
|
||||
\n
|
||||
\a partial [ \a i_z * \a nc_partial + k ]
|
||||
for k = 0 , ... , \a d
|
||||
is the partial derivative of G
|
||||
with respect to the k-th order Taylor coefficient for z.
|
||||
\n
|
||||
\n
|
||||
If \a arg[2] is not zero,
|
||||
\a partial [ \a arg[2] * \a nc_partial + k ]
|
||||
for k = 0 , ... , \a d
|
||||
is the partial derivative with respect to
|
||||
the k-th order Taylor coefficient for x.
|
||||
On input, it corresponds to the function G,
|
||||
and on output it corresponds to the the function H.
|
||||
|
||||
\param var_by_load_op
|
||||
is a vector with size play->num_load_op_rec().
|
||||
It contains the variable index corresponding to each load instruction.
|
||||
In the case where the index is zero,
|
||||
the instruction corresponds to a parameter (not variable).
|
||||
|
||||
\par Checked Assertions
|
||||
\li NumArg(op) == 3
|
||||
\li NumRes(op) == 1
|
||||
\li d < cap_order
|
||||
\li size_t(arg[2]) < i_z
|
||||
*/
|
||||
template <class Base>
|
||||
inline void reverse_load_op(
|
||||
OpCode op ,
|
||||
size_t d ,
|
||||
size_t i_z ,
|
||||
const addr_t* arg ,
|
||||
size_t cap_order ,
|
||||
const Base* taylor ,
|
||||
size_t nc_partial ,
|
||||
Base* partial ,
|
||||
const addr_t* var_by_load_op )
|
||||
{ size_t i_load = size_t( var_by_load_op[ arg[2] ] );
|
||||
|
||||
CPPAD_ASSERT_UNKNOWN( NumArg(op) == 3 );
|
||||
CPPAD_ASSERT_UNKNOWN( NumRes(op) == 1 );
|
||||
CPPAD_ASSERT_UNKNOWN( d < cap_order );
|
||||
CPPAD_ASSERT_UNKNOWN( i_load < i_z );
|
||||
|
||||
if( i_load > 0 )
|
||||
{
|
||||
Base* pz = partial + i_z * nc_partial;
|
||||
Base* py_x = partial + i_load * nc_partial;
|
||||
size_t j = d + 1;
|
||||
while(j--)
|
||||
py_x[j] += pz[j];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
Forward mode sparsity operations for LdpOp and LdvOp
|
||||
|
||||
\param dependency
|
||||
is this a dependency (or sparsity) calculation.
|
||||
|
||||
\copydetails CppAD::local::sparse_load_op
|
||||
*/
|
||||
template <class Vector_set>
|
||||
inline void forward_sparse_load_op(
|
||||
bool dependency ,
|
||||
OpCode op ,
|
||||
size_t i_z ,
|
||||
const addr_t* arg ,
|
||||
size_t num_combined ,
|
||||
const size_t* combined ,
|
||||
Vector_set& var_sparsity ,
|
||||
Vector_set& vecad_sparsity )
|
||||
{
|
||||
CPPAD_ASSERT_UNKNOWN( NumArg(op) == 3 );
|
||||
CPPAD_ASSERT_UNKNOWN( NumRes(op) == 1 );
|
||||
CPPAD_ASSERT_UNKNOWN( 0 < arg[0] );
|
||||
CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < num_combined );
|
||||
size_t i_v = combined[ arg[0] - 1 ];
|
||||
CPPAD_ASSERT_UNKNOWN( i_v < vecad_sparsity.n_set() );
|
||||
|
||||
var_sparsity.assignment(i_z, i_v, vecad_sparsity);
|
||||
if( dependency & (op == LdvOp) )
|
||||
var_sparsity.binary_union(i_z, i_z, arg[1], var_sparsity);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
Reverse mode Jacobian sparsity operations for LdpOp and LdvOp
|
||||
|
||||
\param dependency
|
||||
is this a dependency (or sparsity) calculation.
|
||||
|
||||
\copydetails CppAD::local::sparse_load_op
|
||||
*/
|
||||
template <class Vector_set>
|
||||
inline void reverse_sparse_jacobian_load_op(
|
||||
bool dependency ,
|
||||
OpCode op ,
|
||||
size_t i_z ,
|
||||
const addr_t* arg ,
|
||||
size_t num_combined ,
|
||||
const size_t* combined ,
|
||||
Vector_set& var_sparsity ,
|
||||
Vector_set& vecad_sparsity )
|
||||
{
|
||||
CPPAD_ASSERT_UNKNOWN( NumArg(op) == 3 );
|
||||
CPPAD_ASSERT_UNKNOWN( NumRes(op) == 1 );
|
||||
CPPAD_ASSERT_UNKNOWN( 0 < arg[0] );
|
||||
CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < num_combined );
|
||||
size_t i_v = combined[ arg[0] - 1 ];
|
||||
CPPAD_ASSERT_UNKNOWN( i_v < vecad_sparsity.n_set() );
|
||||
|
||||
vecad_sparsity.binary_union(i_v, i_v, i_z, var_sparsity);
|
||||
if( dependency & (op == LdvOp) )
|
||||
var_sparsity.binary_union(arg[1], arg[1], i_z, var_sparsity);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
Reverse mode Hessian sparsity operations for LdpOp and LdvOp
|
||||
|
||||
\copydetails CppAD::local::sparse_load_op
|
||||
|
||||
\param var_jacobian
|
||||
\a var_jacobian[i_z]
|
||||
is false (true) if the Jacobian of G with respect to z is always zero
|
||||
(many be non-zero).
|
||||
|
||||
\param vecad_jacobian
|
||||
\a vecad_jacobian[i_v]
|
||||
is false (true) if the Jacobian with respect to x is always zero
|
||||
(may be non-zero).
|
||||
On input, it corresponds to the function G,
|
||||
and on output it corresponds to the function H.
|
||||
|
||||
*/
|
||||
template <class Vector_set>
|
||||
inline void reverse_sparse_hessian_load_op(
|
||||
OpCode op ,
|
||||
size_t i_z ,
|
||||
const addr_t* arg ,
|
||||
size_t num_combined ,
|
||||
const size_t* combined ,
|
||||
Vector_set& var_sparsity ,
|
||||
Vector_set& vecad_sparsity ,
|
||||
bool* var_jacobian ,
|
||||
bool* vecad_jacobian )
|
||||
{
|
||||
CPPAD_ASSERT_UNKNOWN( NumArg(op) == 3 );
|
||||
CPPAD_ASSERT_UNKNOWN( NumRes(op) == 1 );
|
||||
CPPAD_ASSERT_UNKNOWN( 0 < arg[0] );
|
||||
CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < num_combined );
|
||||
size_t i_v = combined[ arg[0] - 1 ];
|
||||
CPPAD_ASSERT_UNKNOWN( i_v < vecad_sparsity.n_set() );
|
||||
|
||||
vecad_sparsity.binary_union(i_v, i_v, i_z, var_sparsity);
|
||||
|
||||
vecad_jacobian[i_v] |= var_jacobian[i_z];
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
} } // END_CPPAD_LOCAL_NAMESPACE
|
||||
# endif
|
||||
+204
@@ -0,0 +1,204 @@
|
||||
# ifndef CPPAD_LOCAL_LOG1P_OP_HPP
|
||||
# define CPPAD_LOCAL_LOG1P_OP_HPP
|
||||
# if CPPAD_USE_CPLUSPLUS_2011
|
||||
|
||||
/* --------------------------------------------------------------------------
|
||||
CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-17 Bradley M. Bell
|
||||
|
||||
CppAD is distributed under multiple licenses. This distribution is under
|
||||
the terms of the
|
||||
Eclipse Public License Version 1.0.
|
||||
|
||||
A copy of this license is included in the COPYING file of this distribution.
|
||||
Please visit http://www.coin-or.org/CppAD/ for information on other licenses.
|
||||
-------------------------------------------------------------------------- */
|
||||
|
||||
namespace CppAD { namespace local { // BEGIN_CPPAD_LOCAL_NAMESPACE
|
||||
/*!
|
||||
\file log1p_op.hpp
|
||||
Forward and reverse mode calculations for z = log1p(x).
|
||||
*/
|
||||
|
||||
/*!
|
||||
Compute forward mode Taylor coefficient for result of op = Log1pOp.
|
||||
|
||||
The C++ source code corresponding to this operation is
|
||||
\verbatim
|
||||
z = log1p(x)
|
||||
\endverbatim
|
||||
|
||||
\copydetails CppAD::local::forward_unary1_op
|
||||
*/
|
||||
template <class Base>
|
||||
inline void forward_log1p_op(
|
||||
size_t p ,
|
||||
size_t q ,
|
||||
size_t i_z ,
|
||||
size_t i_x ,
|
||||
size_t cap_order ,
|
||||
Base* taylor )
|
||||
{
|
||||
size_t k;
|
||||
|
||||
// check assumptions
|
||||
CPPAD_ASSERT_UNKNOWN( NumArg(Log1pOp) == 1 );
|
||||
CPPAD_ASSERT_UNKNOWN( NumRes(Log1pOp) == 1 );
|
||||
CPPAD_ASSERT_UNKNOWN( q < cap_order );
|
||||
CPPAD_ASSERT_UNKNOWN( p <= q );
|
||||
|
||||
// Taylor coefficients corresponding to argument and result
|
||||
Base* x = taylor + i_x * cap_order;
|
||||
Base* z = taylor + i_z * cap_order;
|
||||
|
||||
if( p == 0 )
|
||||
{ z[0] = log1p( x[0] );
|
||||
p++;
|
||||
if( q == 0 )
|
||||
return;
|
||||
}
|
||||
if ( p == 1 )
|
||||
{ z[1] = x[1] / (Base(1.0) + x[0]);
|
||||
p++;
|
||||
}
|
||||
for(size_t j = p; j <= q; j++)
|
||||
{
|
||||
z[j] = -z[1] * x[j-1];
|
||||
for(k = 2; k < j; k++)
|
||||
z[j] -= Base(double(k)) * z[k] * x[j-k];
|
||||
z[j] /= Base(double(j));
|
||||
z[j] += x[j];
|
||||
z[j] /= (Base(1.0) + x[0]);
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
Muiltiple directions Taylor coefficient for op = Log1pOp.
|
||||
|
||||
The C++ source code corresponding to this operation is
|
||||
\verbatim
|
||||
z = log1p(x)
|
||||
\endverbatim
|
||||
|
||||
\copydetails CppAD::local::forward_unary1_op_dir
|
||||
*/
|
||||
template <class Base>
|
||||
inline void forward_log1p_op_dir(
|
||||
size_t q ,
|
||||
size_t r ,
|
||||
size_t i_z ,
|
||||
size_t i_x ,
|
||||
size_t cap_order ,
|
||||
Base* taylor )
|
||||
{
|
||||
|
||||
// check assumptions
|
||||
CPPAD_ASSERT_UNKNOWN( NumArg(Log1pOp) == 1 );
|
||||
CPPAD_ASSERT_UNKNOWN( NumRes(Log1pOp) == 1 );
|
||||
CPPAD_ASSERT_UNKNOWN( 0 < q );
|
||||
CPPAD_ASSERT_UNKNOWN( q < cap_order );
|
||||
|
||||
// Taylor coefficients corresponding to argument and result
|
||||
size_t num_taylor_per_var = (cap_order-1) * r + 1;
|
||||
Base* x = taylor + i_x * num_taylor_per_var;
|
||||
Base* z = taylor + i_z * num_taylor_per_var;
|
||||
|
||||
size_t m = (q-1) * r + 1;
|
||||
for(size_t ell = 0; ell < r; ell++)
|
||||
{ z[m+ell] = Base(double(q)) * x[m+ell];
|
||||
for(size_t k = 1; k < q; k++)
|
||||
z[m+ell] -= Base(double(k)) * z[(k-1)*r+1+ell] * x[(q-k-1)*r+1+ell];
|
||||
z[m+ell] /= (Base(double(q)) + Base(q) * x[0]);
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
Compute zero order forward mode Taylor coefficient for result of op = Log1pOp.
|
||||
|
||||
The C++ source code corresponding to this operation is
|
||||
\verbatim
|
||||
z = log1p(x)
|
||||
\endverbatim
|
||||
|
||||
\copydetails CppAD::local::forward_unary1_op_0
|
||||
*/
|
||||
template <class Base>
|
||||
inline void forward_log1p_op_0(
|
||||
size_t i_z ,
|
||||
size_t i_x ,
|
||||
size_t cap_order ,
|
||||
Base* taylor )
|
||||
{
|
||||
|
||||
// check assumptions
|
||||
CPPAD_ASSERT_UNKNOWN( NumArg(Log1pOp) == 1 );
|
||||
CPPAD_ASSERT_UNKNOWN( NumRes(Log1pOp) == 1 );
|
||||
CPPAD_ASSERT_UNKNOWN( 0 < cap_order );
|
||||
|
||||
// Taylor coefficients corresponding to argument and result
|
||||
Base* x = taylor + i_x * cap_order;
|
||||
Base* z = taylor + i_z * cap_order;
|
||||
|
||||
z[0] = log1p( x[0] );
|
||||
}
|
||||
|
||||
/*!
|
||||
Compute reverse mode partial derivatives for result of op = Log1pOp.
|
||||
|
||||
The C++ source code corresponding to this operation is
|
||||
\verbatim
|
||||
z = log1p(x)
|
||||
\endverbatim
|
||||
|
||||
\copydetails CppAD::local::reverse_unary1_op
|
||||
*/
|
||||
|
||||
template <class Base>
|
||||
inline void reverse_log1p_op(
|
||||
size_t d ,
|
||||
size_t i_z ,
|
||||
size_t i_x ,
|
||||
size_t cap_order ,
|
||||
const Base* taylor ,
|
||||
size_t nc_partial ,
|
||||
Base* partial )
|
||||
{ size_t j, k;
|
||||
|
||||
// check assumptions
|
||||
CPPAD_ASSERT_UNKNOWN( NumArg(Log1pOp) == 1 );
|
||||
CPPAD_ASSERT_UNKNOWN( NumRes(Log1pOp) == 1 );
|
||||
CPPAD_ASSERT_UNKNOWN( d < cap_order );
|
||||
CPPAD_ASSERT_UNKNOWN( d < nc_partial );
|
||||
|
||||
// Taylor coefficients and partials corresponding to argument
|
||||
const Base* x = taylor + i_x * cap_order;
|
||||
Base* px = partial + i_x * nc_partial;
|
||||
|
||||
// Taylor coefficients and partials corresponding to result
|
||||
const Base* z = taylor + i_z * cap_order;
|
||||
Base* pz = partial + i_z * nc_partial;
|
||||
|
||||
Base inv_1px0 = Base(1.0) / (Base(1) + x[0]);
|
||||
|
||||
j = d;
|
||||
while(j)
|
||||
{ // scale partial w.r.t z[j]
|
||||
pz[j] = azmul(pz[j] , inv_1px0);
|
||||
|
||||
px[0] -= azmul(pz[j], z[j]);
|
||||
px[j] += pz[j];
|
||||
|
||||
// further scale partial w.r.t. z[j]
|
||||
pz[j] /= Base(double(j));
|
||||
|
||||
for(k = 1; k < j; k++)
|
||||
{ pz[k] -= Base(double(k)) * azmul(pz[j], x[j-k]);
|
||||
px[j-k] -= Base(double(k)) * azmul(pz[j], z[k]);
|
||||
}
|
||||
--j;
|
||||
}
|
||||
px[0] += azmul(pz[0], inv_1px0);
|
||||
}
|
||||
|
||||
} } // END_CPPAD_LOCAL_NAMESPACE
|
||||
# endif
|
||||
# endif
|
||||
+202
@@ -0,0 +1,202 @@
|
||||
# ifndef CPPAD_LOCAL_LOG_OP_HPP
|
||||
# define CPPAD_LOCAL_LOG_OP_HPP
|
||||
|
||||
/* --------------------------------------------------------------------------
|
||||
CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-17 Bradley M. Bell
|
||||
|
||||
CppAD is distributed under multiple licenses. This distribution is under
|
||||
the terms of the
|
||||
Eclipse Public License Version 1.0.
|
||||
|
||||
A copy of this license is included in the COPYING file of this distribution.
|
||||
Please visit http://www.coin-or.org/CppAD/ for information on other licenses.
|
||||
-------------------------------------------------------------------------- */
|
||||
|
||||
namespace CppAD { namespace local { // BEGIN_CPPAD_LOCAL_NAMESPACE
|
||||
/*!
|
||||
\file log_op.hpp
|
||||
Forward and reverse mode calculations for z = log(x).
|
||||
*/
|
||||
|
||||
/*!
|
||||
Compute forward mode Taylor coefficient for result of op = LogOp.
|
||||
|
||||
The C++ source code corresponding to this operation is
|
||||
\verbatim
|
||||
z = log(x)
|
||||
\endverbatim
|
||||
|
||||
\copydetails CppAD::local::forward_unary1_op
|
||||
*/
|
||||
template <class Base>
|
||||
inline void forward_log_op(
|
||||
size_t p ,
|
||||
size_t q ,
|
||||
size_t i_z ,
|
||||
size_t i_x ,
|
||||
size_t cap_order ,
|
||||
Base* taylor )
|
||||
{
|
||||
size_t k;
|
||||
|
||||
// check assumptions
|
||||
CPPAD_ASSERT_UNKNOWN( NumArg(LogOp) == 1 );
|
||||
CPPAD_ASSERT_UNKNOWN( NumRes(LogOp) == 1 );
|
||||
CPPAD_ASSERT_UNKNOWN( q < cap_order );
|
||||
CPPAD_ASSERT_UNKNOWN( p <= q );
|
||||
|
||||
// Taylor coefficients corresponding to argument and result
|
||||
Base* x = taylor + i_x * cap_order;
|
||||
Base* z = taylor + i_z * cap_order;
|
||||
|
||||
if( p == 0 )
|
||||
{ z[0] = log( x[0] );
|
||||
p++;
|
||||
if( q == 0 )
|
||||
return;
|
||||
}
|
||||
if ( p == 1 )
|
||||
{ z[1] = x[1] / x[0];
|
||||
p++;
|
||||
}
|
||||
for(size_t j = p; j <= q; j++)
|
||||
{
|
||||
z[j] = -z[1] * x[j-1];
|
||||
for(k = 2; k < j; k++)
|
||||
z[j] -= Base(double(k)) * z[k] * x[j-k];
|
||||
z[j] /= Base(double(j));
|
||||
z[j] += x[j];
|
||||
z[j] /= x[0];
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
Muiltiple directions Taylor coefficient for op = LogOp.
|
||||
|
||||
The C++ source code corresponding to this operation is
|
||||
\verbatim
|
||||
z = log(x)
|
||||
\endverbatim
|
||||
|
||||
\copydetails CppAD::local::forward_unary1_op_dir
|
||||
*/
|
||||
template <class Base>
|
||||
inline void forward_log_op_dir(
|
||||
size_t q ,
|
||||
size_t r ,
|
||||
size_t i_z ,
|
||||
size_t i_x ,
|
||||
size_t cap_order ,
|
||||
Base* taylor )
|
||||
{
|
||||
|
||||
// check assumptions
|
||||
CPPAD_ASSERT_UNKNOWN( NumArg(LogOp) == 1 );
|
||||
CPPAD_ASSERT_UNKNOWN( NumRes(LogOp) == 1 );
|
||||
CPPAD_ASSERT_UNKNOWN( 0 < q );
|
||||
CPPAD_ASSERT_UNKNOWN( q < cap_order );
|
||||
|
||||
// Taylor coefficients corresponding to argument and result
|
||||
size_t num_taylor_per_var = (cap_order-1) * r + 1;
|
||||
Base* x = taylor + i_x * num_taylor_per_var;
|
||||
Base* z = taylor + i_z * num_taylor_per_var;
|
||||
|
||||
size_t m = (q-1) * r + 1;
|
||||
for(size_t ell = 0; ell < r; ell++)
|
||||
{ z[m+ell] = Base(double(q)) * x[m+ell];
|
||||
for(size_t k = 1; k < q; k++)
|
||||
z[m+ell] -= Base(double(k)) * z[(k-1)*r+1+ell] * x[(q-k-1)*r+1+ell];
|
||||
z[m+ell] /= (Base(double(q)) * x[0]);
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
Compute zero order forward mode Taylor coefficient for result of op = LogOp.
|
||||
|
||||
The C++ source code corresponding to this operation is
|
||||
\verbatim
|
||||
z = log(x)
|
||||
\endverbatim
|
||||
|
||||
\copydetails CppAD::local::forward_unary1_op_0
|
||||
*/
|
||||
template <class Base>
|
||||
inline void forward_log_op_0(
|
||||
size_t i_z ,
|
||||
size_t i_x ,
|
||||
size_t cap_order ,
|
||||
Base* taylor )
|
||||
{
|
||||
|
||||
// check assumptions
|
||||
CPPAD_ASSERT_UNKNOWN( NumArg(LogOp) == 1 );
|
||||
CPPAD_ASSERT_UNKNOWN( NumRes(LogOp) == 1 );
|
||||
CPPAD_ASSERT_UNKNOWN( 0 < cap_order );
|
||||
|
||||
// Taylor coefficients corresponding to argument and result
|
||||
Base* x = taylor + i_x * cap_order;
|
||||
Base* z = taylor + i_z * cap_order;
|
||||
|
||||
z[0] = log( x[0] );
|
||||
}
|
||||
|
||||
/*!
|
||||
Compute reverse mode partial derivatives for result of op = LogOp.
|
||||
|
||||
The C++ source code corresponding to this operation is
|
||||
\verbatim
|
||||
z = log(x)
|
||||
\endverbatim
|
||||
|
||||
\copydetails CppAD::local::reverse_unary1_op
|
||||
*/
|
||||
|
||||
template <class Base>
|
||||
inline void reverse_log_op(
|
||||
size_t d ,
|
||||
size_t i_z ,
|
||||
size_t i_x ,
|
||||
size_t cap_order ,
|
||||
const Base* taylor ,
|
||||
size_t nc_partial ,
|
||||
Base* partial )
|
||||
{ size_t j, k;
|
||||
|
||||
// check assumptions
|
||||
CPPAD_ASSERT_UNKNOWN( NumArg(LogOp) == 1 );
|
||||
CPPAD_ASSERT_UNKNOWN( NumRes(LogOp) == 1 );
|
||||
CPPAD_ASSERT_UNKNOWN( d < cap_order );
|
||||
CPPAD_ASSERT_UNKNOWN( d < nc_partial );
|
||||
|
||||
// Taylor coefficients and partials corresponding to argument
|
||||
const Base* x = taylor + i_x * cap_order;
|
||||
Base* px = partial + i_x * nc_partial;
|
||||
|
||||
// Taylor coefficients and partials corresponding to result
|
||||
const Base* z = taylor + i_z * cap_order;
|
||||
Base* pz = partial + i_z * nc_partial;
|
||||
|
||||
Base inv_x0 = Base(1.0) / x[0];
|
||||
|
||||
j = d;
|
||||
while(j)
|
||||
{ // scale partial w.r.t z[j]
|
||||
pz[j] = azmul(pz[j] , inv_x0);
|
||||
|
||||
px[0] -= azmul(pz[j], z[j]);
|
||||
px[j] += pz[j];
|
||||
|
||||
// further scale partial w.r.t. z[j]
|
||||
pz[j] /= Base(double(j));
|
||||
|
||||
for(k = 1; k < j; k++)
|
||||
{ pz[k] -= Base(double(k)) * azmul(pz[j], x[j-k]);
|
||||
px[j-k] -= Base(double(k)) * azmul(pz[j], z[k]);
|
||||
}
|
||||
--j;
|
||||
}
|
||||
px[0] += azmul(pz[0], inv_x0);
|
||||
}
|
||||
|
||||
} } // END_CPPAD_LOCAL_NAMESPACE
|
||||
# endif
|
||||
+359
@@ -0,0 +1,359 @@
|
||||
# ifndef CPPAD_LOCAL_MUL_OP_HPP
|
||||
# define CPPAD_LOCAL_MUL_OP_HPP
|
||||
|
||||
/* --------------------------------------------------------------------------
|
||||
CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-17 Bradley M. Bell
|
||||
|
||||
CppAD is distributed under multiple licenses. This distribution is under
|
||||
the terms of the
|
||||
Eclipse Public License Version 1.0.
|
||||
|
||||
A copy of this license is included in the COPYING file of this distribution.
|
||||
Please visit http://www.coin-or.org/CppAD/ for information on other licenses.
|
||||
-------------------------------------------------------------------------- */
|
||||
|
||||
namespace CppAD { namespace local { // BEGIN_CPPAD_LOCAL_NAMESPACE
|
||||
/*!
|
||||
\file mul_op.hpp
|
||||
Forward and reverse mode calculations for z = x * y.
|
||||
*/
|
||||
|
||||
// --------------------------- Mulvv -----------------------------------------
|
||||
/*!
|
||||
Compute forward mode Taylor coefficients for result of op = MulvvOp.
|
||||
|
||||
The C++ source code corresponding to this operation is
|
||||
\verbatim
|
||||
z = x * y
|
||||
\endverbatim
|
||||
In the documentation below,
|
||||
this operations is for the case where both x and y are variables
|
||||
and the argument \a parameter is not used.
|
||||
|
||||
\copydetails CppAD::local::forward_binary_op
|
||||
*/
|
||||
|
||||
template <class Base>
|
||||
inline void forward_mulvv_op(
|
||||
size_t p ,
|
||||
size_t q ,
|
||||
size_t i_z ,
|
||||
const addr_t* arg ,
|
||||
const Base* parameter ,
|
||||
size_t cap_order ,
|
||||
Base* taylor )
|
||||
{
|
||||
// check assumptions
|
||||
CPPAD_ASSERT_UNKNOWN( NumArg(MulvvOp) == 2 );
|
||||
CPPAD_ASSERT_UNKNOWN( NumRes(MulvvOp) == 1 );
|
||||
CPPAD_ASSERT_UNKNOWN( q < cap_order );
|
||||
CPPAD_ASSERT_UNKNOWN( p <= q );
|
||||
|
||||
// Taylor coefficients corresponding to arguments and result
|
||||
Base* x = taylor + arg[0] * cap_order;
|
||||
Base* y = taylor + arg[1] * cap_order;
|
||||
Base* z = taylor + i_z * cap_order;
|
||||
|
||||
size_t k;
|
||||
for(size_t d = p; d <= q; d++)
|
||||
{ z[d] = Base(0.0);
|
||||
for(k = 0; k <= d; k++)
|
||||
z[d] += x[d-k] * y[k];
|
||||
}
|
||||
}
|
||||
/*!
|
||||
Multiple directions forward mode Taylor coefficients for op = MulvvOp.
|
||||
|
||||
The C++ source code corresponding to this operation is
|
||||
\verbatim
|
||||
z = x * y
|
||||
\endverbatim
|
||||
In the documentation below,
|
||||
this operations is for the case where both x and y are variables
|
||||
and the argument \a parameter is not used.
|
||||
|
||||
\copydetails CppAD::local::forward_binary_op_dir
|
||||
*/
|
||||
|
||||
template <class Base>
|
||||
inline void forward_mulvv_op_dir(
|
||||
size_t q ,
|
||||
size_t r ,
|
||||
size_t i_z ,
|
||||
const addr_t* arg ,
|
||||
const Base* parameter ,
|
||||
size_t cap_order ,
|
||||
Base* taylor )
|
||||
{
|
||||
// check assumptions
|
||||
CPPAD_ASSERT_UNKNOWN( NumArg(MulvvOp) == 2 );
|
||||
CPPAD_ASSERT_UNKNOWN( NumRes(MulvvOp) == 1 );
|
||||
CPPAD_ASSERT_UNKNOWN( 0 < q );
|
||||
CPPAD_ASSERT_UNKNOWN( q < cap_order );
|
||||
|
||||
// Taylor coefficients corresponding to arguments and result
|
||||
size_t num_taylor_per_var = (cap_order-1) * r + 1;
|
||||
Base* x = taylor + arg[0] * num_taylor_per_var;
|
||||
Base* y = taylor + arg[1] * num_taylor_per_var;
|
||||
Base* z = taylor + i_z * num_taylor_per_var;
|
||||
|
||||
size_t k, ell, m;
|
||||
for(ell = 0; ell < r; ell++)
|
||||
{ m = (q-1)*r + ell + 1;
|
||||
z[m] = x[0] * y[m] + x[m] * y[0];
|
||||
for(k = 1; k < q; k++)
|
||||
z[m] += x[(q-k-1)*r + ell + 1] * y[(k-1)*r + ell + 1];
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
Compute zero order forward mode Taylor coefficients for result of op = MulvvOp.
|
||||
|
||||
The C++ source code corresponding to this operation is
|
||||
\verbatim
|
||||
z = x * y
|
||||
\endverbatim
|
||||
In the documentation below,
|
||||
this operations is for the case where both x and y are variables
|
||||
and the argument \a parameter is not used.
|
||||
|
||||
\copydetails CppAD::local::forward_binary_op_0
|
||||
*/
|
||||
|
||||
template <class Base>
|
||||
inline void forward_mulvv_op_0(
|
||||
size_t i_z ,
|
||||
const addr_t* arg ,
|
||||
const Base* parameter ,
|
||||
size_t cap_order ,
|
||||
Base* taylor )
|
||||
{
|
||||
// check assumptions
|
||||
CPPAD_ASSERT_UNKNOWN( NumArg(MulvvOp) == 2 );
|
||||
CPPAD_ASSERT_UNKNOWN( NumRes(MulvvOp) == 1 );
|
||||
|
||||
// Taylor coefficients corresponding to arguments and result
|
||||
Base* x = taylor + arg[0] * cap_order;
|
||||
Base* y = taylor + arg[1] * cap_order;
|
||||
Base* z = taylor + i_z * cap_order;
|
||||
|
||||
z[0] = x[0] * y[0];
|
||||
}
|
||||
|
||||
/*!
|
||||
Compute reverse mode partial derivatives for result of op = MulvvOp.
|
||||
|
||||
The C++ source code corresponding to this operation is
|
||||
\verbatim
|
||||
z = x * y
|
||||
\endverbatim
|
||||
In the documentation below,
|
||||
this operations is for the case where both x and y are variables
|
||||
and the argument \a parameter is not used.
|
||||
|
||||
\copydetails CppAD::local::reverse_binary_op
|
||||
*/
|
||||
|
||||
template <class Base>
|
||||
inline void reverse_mulvv_op(
|
||||
size_t d ,
|
||||
size_t i_z ,
|
||||
const addr_t* arg ,
|
||||
const Base* parameter ,
|
||||
size_t cap_order ,
|
||||
const Base* taylor ,
|
||||
size_t nc_partial ,
|
||||
Base* partial )
|
||||
{
|
||||
// check assumptions
|
||||
CPPAD_ASSERT_UNKNOWN( NumArg(MulvvOp) == 2 );
|
||||
CPPAD_ASSERT_UNKNOWN( NumRes(MulvvOp) == 1 );
|
||||
CPPAD_ASSERT_UNKNOWN( d < cap_order );
|
||||
CPPAD_ASSERT_UNKNOWN( d < nc_partial );
|
||||
|
||||
// Arguments
|
||||
const Base* x = taylor + arg[0] * cap_order;
|
||||
const Base* y = taylor + arg[1] * cap_order;
|
||||
|
||||
// Partial derivatives corresponding to arguments and result
|
||||
Base* px = partial + arg[0] * nc_partial;
|
||||
Base* py = partial + arg[1] * nc_partial;
|
||||
Base* pz = partial + i_z * nc_partial;
|
||||
|
||||
|
||||
// number of indices to access
|
||||
size_t j = d + 1;
|
||||
size_t k;
|
||||
while(j)
|
||||
{ --j;
|
||||
for(k = 0; k <= j; k++)
|
||||
{
|
||||
px[j-k] += azmul(pz[j], y[k]);
|
||||
py[k] += azmul(pz[j], x[j-k]);
|
||||
}
|
||||
}
|
||||
}
|
||||
// --------------------------- Mulpv -----------------------------------------
|
||||
/*!
|
||||
Compute forward mode Taylor coefficients for result of op = MulpvOp.
|
||||
|
||||
The C++ source code corresponding to this operation is
|
||||
\verbatim
|
||||
z = x * y
|
||||
\endverbatim
|
||||
In the documentation below,
|
||||
this operations is for the case where x is a parameter and y is a variable.
|
||||
|
||||
\copydetails CppAD::local::forward_binary_op
|
||||
*/
|
||||
|
||||
template <class Base>
|
||||
inline void forward_mulpv_op(
|
||||
size_t p ,
|
||||
size_t q ,
|
||||
size_t i_z ,
|
||||
const addr_t* arg ,
|
||||
const Base* parameter ,
|
||||
size_t cap_order ,
|
||||
Base* taylor )
|
||||
{
|
||||
// check assumptions
|
||||
CPPAD_ASSERT_UNKNOWN( NumArg(MulpvOp) == 2 );
|
||||
CPPAD_ASSERT_UNKNOWN( NumRes(MulpvOp) == 1 );
|
||||
CPPAD_ASSERT_UNKNOWN( q < cap_order );
|
||||
CPPAD_ASSERT_UNKNOWN( p <= q );
|
||||
|
||||
// Taylor coefficients corresponding to arguments and result
|
||||
Base* y = taylor + arg[1] * cap_order;
|
||||
Base* z = taylor + i_z * cap_order;
|
||||
|
||||
// Paraemter value
|
||||
Base x = parameter[ arg[0] ];
|
||||
|
||||
for(size_t d = p; d <= q; d++)
|
||||
z[d] = x * y[d];
|
||||
}
|
||||
/*!
|
||||
Multiple directions forward mode Taylor coefficients for op = MulpvOp.
|
||||
|
||||
The C++ source code corresponding to this operation is
|
||||
\verbatim
|
||||
z = x * y
|
||||
\endverbatim
|
||||
In the documentation below,
|
||||
this operations is for the case where x is a parameter and y is a variable.
|
||||
|
||||
\copydetails CppAD::local::forward_binary_op_dir
|
||||
*/
|
||||
|
||||
template <class Base>
|
||||
inline void forward_mulpv_op_dir(
|
||||
size_t q ,
|
||||
size_t r ,
|
||||
size_t i_z ,
|
||||
const addr_t* arg ,
|
||||
const Base* parameter ,
|
||||
size_t cap_order ,
|
||||
Base* taylor )
|
||||
{
|
||||
// check assumptions
|
||||
CPPAD_ASSERT_UNKNOWN( NumArg(MulpvOp) == 2 );
|
||||
CPPAD_ASSERT_UNKNOWN( NumRes(MulpvOp) == 1 );
|
||||
CPPAD_ASSERT_UNKNOWN( 0 < q );
|
||||
CPPAD_ASSERT_UNKNOWN( q < cap_order );
|
||||
|
||||
// Taylor coefficients corresponding to arguments and result
|
||||
size_t num_taylor_per_var = (cap_order-1) * r + 1;
|
||||
size_t m = (q-1) * r + 1;
|
||||
Base* y = taylor + arg[1] * num_taylor_per_var + m;
|
||||
Base* z = taylor + i_z * num_taylor_per_var + m;
|
||||
|
||||
// Paraemter value
|
||||
Base x = parameter[ arg[0] ];
|
||||
|
||||
for(size_t ell = 0; ell < r; ell++)
|
||||
z[ell] = x * y[ell];
|
||||
}
|
||||
/*!
|
||||
Compute zero order forward mode Taylor coefficient for result of op = MulpvOp.
|
||||
|
||||
The C++ source code corresponding to this operation is
|
||||
\verbatim
|
||||
z = x * y
|
||||
\endverbatim
|
||||
In the documentation below,
|
||||
this operations is for the case where x is a parameter and y is a variable.
|
||||
|
||||
\copydetails CppAD::local::forward_binary_op_0
|
||||
*/
|
||||
|
||||
template <class Base>
|
||||
inline void forward_mulpv_op_0(
|
||||
size_t i_z ,
|
||||
const addr_t* arg ,
|
||||
const Base* parameter ,
|
||||
size_t cap_order ,
|
||||
Base* taylor )
|
||||
{
|
||||
// check assumptions
|
||||
CPPAD_ASSERT_UNKNOWN( NumArg(MulpvOp) == 2 );
|
||||
CPPAD_ASSERT_UNKNOWN( NumRes(MulpvOp) == 1 );
|
||||
|
||||
// Paraemter value
|
||||
Base x = parameter[ arg[0] ];
|
||||
|
||||
// Taylor coefficients corresponding to arguments and result
|
||||
Base* y = taylor + arg[1] * cap_order;
|
||||
Base* z = taylor + i_z * cap_order;
|
||||
|
||||
z[0] = x * y[0];
|
||||
}
|
||||
|
||||
/*!
|
||||
Compute reverse mode partial derivative for result of op = MulpvOp.
|
||||
|
||||
The C++ source code corresponding to this operation is
|
||||
\verbatim
|
||||
z = x * y
|
||||
\endverbatim
|
||||
In the documentation below,
|
||||
this operations is for the case where x is a parameter and y is a variable.
|
||||
|
||||
\copydetails CppAD::local::reverse_binary_op
|
||||
*/
|
||||
|
||||
template <class Base>
|
||||
inline void reverse_mulpv_op(
|
||||
size_t d ,
|
||||
size_t i_z ,
|
||||
const addr_t* arg ,
|
||||
const Base* parameter ,
|
||||
size_t cap_order ,
|
||||
const Base* taylor ,
|
||||
size_t nc_partial ,
|
||||
Base* partial )
|
||||
{
|
||||
// check assumptions
|
||||
CPPAD_ASSERT_UNKNOWN( NumArg(MulpvOp) == 2 );
|
||||
CPPAD_ASSERT_UNKNOWN( NumRes(MulpvOp) == 1 );
|
||||
CPPAD_ASSERT_UNKNOWN( d < cap_order );
|
||||
CPPAD_ASSERT_UNKNOWN( d < nc_partial );
|
||||
|
||||
// Arguments
|
||||
Base x = parameter[ arg[0] ];
|
||||
|
||||
// Partial derivatives corresponding to arguments and result
|
||||
Base* py = partial + arg[1] * nc_partial;
|
||||
Base* pz = partial + i_z * nc_partial;
|
||||
|
||||
// number of indices to access
|
||||
size_t j = d + 1;
|
||||
while(j)
|
||||
{ --j;
|
||||
py[j] += azmul(pz[j], x);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
} } // END_CPPAD_LOCAL_NAMESPACE
|
||||
# endif
|
||||
+60
@@ -0,0 +1,60 @@
|
||||
// $Id: op.hpp 3876 2017-02-10 12:45:08Z bradbell $
|
||||
# ifndef CPPAD_LOCAL_OP_HPP
|
||||
# define CPPAD_LOCAL_OP_HPP
|
||||
|
||||
/* --------------------------------------------------------------------------
|
||||
CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-17 Bradley M. Bell
|
||||
|
||||
CppAD is distributed under multiple licenses. This distribution is under
|
||||
the terms of the
|
||||
Eclipse Public License Version 1.0.
|
||||
|
||||
A copy of this license is included in the COPYING file of this distribution.
|
||||
Please visit http://www.coin-or.org/CppAD/ for information on other licenses.
|
||||
-------------------------------------------------------------------------- */
|
||||
|
||||
// used by the sparse operators
|
||||
# include <cppad/local/sparse_internal.hpp>
|
||||
|
||||
// operations
|
||||
# include <cppad/core/std_math_98.hpp>
|
||||
# include <cppad/local/abs_op.hpp>
|
||||
# include <cppad/local/add_op.hpp>
|
||||
# include <cppad/local/acos_op.hpp>
|
||||
# include <cppad/local/acosh_op.hpp>
|
||||
# include <cppad/local/asin_op.hpp>
|
||||
# include <cppad/local/asinh_op.hpp>
|
||||
# include <cppad/local/atan_op.hpp>
|
||||
# include <cppad/local/atanh_op.hpp>
|
||||
# include <cppad/local/comp_op.hpp>
|
||||
# include <cppad/local/cond_op.hpp>
|
||||
# include <cppad/local/cos_op.hpp>
|
||||
# include <cppad/local/cosh_op.hpp>
|
||||
# include <cppad/local/cskip_op.hpp>
|
||||
# include <cppad/local/csum_op.hpp>
|
||||
# include <cppad/local/discrete_op.hpp>
|
||||
# include <cppad/local/div_op.hpp>
|
||||
# include <cppad/local/erf_op.hpp>
|
||||
# include <cppad/local/exp_op.hpp>
|
||||
# include <cppad/local/expm1_op.hpp>
|
||||
# include <cppad/local/load_op.hpp>
|
||||
# include <cppad/local/log_op.hpp>
|
||||
# include <cppad/local/log1p_op.hpp>
|
||||
# include <cppad/local/mul_op.hpp>
|
||||
# include <cppad/local/parameter_op.hpp>
|
||||
# include <cppad/local/pow_op.hpp>
|
||||
# include <cppad/local/print_op.hpp>
|
||||
# include <cppad/local/sign_op.hpp>
|
||||
# include <cppad/local/sin_op.hpp>
|
||||
# include <cppad/local/sinh_op.hpp>
|
||||
# include <cppad/local/sqrt_op.hpp>
|
||||
# include <cppad/local/sub_op.hpp>
|
||||
# include <cppad/local/sparse_binary_op.hpp>
|
||||
# include <cppad/local/sparse_unary_op.hpp>
|
||||
# include <cppad/local/store_op.hpp>
|
||||
# include <cppad/local/tan_op.hpp>
|
||||
# include <cppad/local/tanh_op.hpp>
|
||||
# include <cppad/local/zmul_op.hpp>
|
||||
|
||||
|
||||
# endif
|
||||
+1069
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,72 @@
|
||||
// $Id$
|
||||
# ifndef CPPAD_LOCAL_OPTIMIZE_CEXP_INFO_HPP
|
||||
# define CPPAD_LOCAL_OPTIMIZE_CEXP_INFO_HPP
|
||||
/* --------------------------------------------------------------------------
|
||||
CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-17 Bradley M. Bell
|
||||
|
||||
CppAD is distributed under multiple licenses. This distribution is under
|
||||
the terms of the
|
||||
Eclipse Public License Version 1.0.
|
||||
|
||||
A copy of this license is included in the COPYING file of this distribution.
|
||||
Please visit http://www.coin-or.org/CppAD/ for information on other licenses.
|
||||
-------------------------------------------------------------------------- */
|
||||
# include <cppad/local/declare_ad.hpp> // defines CompareOp
|
||||
# include <cppad/utility/vector.hpp>
|
||||
|
||||
/*!
|
||||
\file cexp_info.hpp
|
||||
Information about one conditional expression.
|
||||
*/
|
||||
|
||||
// BEGIN_CPPAD_LOCAL_OPTIMIZE_NAMESPACE
|
||||
namespace CppAD { namespace local { namespace optimize {
|
||||
/*!
|
||||
Information about one conditional expression.
|
||||
*/
|
||||
struct struct_cexp_info {
|
||||
/// The operator index for this conditional expression operation
|
||||
size_t i_op;
|
||||
|
||||
/// (flag & 1) is true if and only if left is a variable
|
||||
/// (flag & 2) is true if and only if right is a variable
|
||||
size_t flag;
|
||||
|
||||
/// variable or parameter index for left comparison operand
|
||||
size_t left;
|
||||
|
||||
/// variable or parameter index for right comparison operand
|
||||
size_t right;
|
||||
|
||||
/// maximum variable index between left and right (ignoring parameters).
|
||||
size_t max_left_right;
|
||||
|
||||
/// set of operator that are not used when comparison result is true
|
||||
/// Note that UsrapOp, UsravOp, UsrrpOp, and UsrrvOp, are not in this
|
||||
/// vector and should be skipped when the corresponding UserOp are skipped.
|
||||
CppAD::vector<size_t> skip_op_true;
|
||||
|
||||
/// set of variables that are not used when comparison result is false
|
||||
/// Note that UsrapOp, UsravOp, UsrrpOp, and UsrrvOp, are not in this
|
||||
/// vector and should be skipped when the corresponding UserOp are skipped.
|
||||
CppAD::vector<size_t> skip_op_false;
|
||||
|
||||
/// comparision operator for this conditional expression
|
||||
CompareOp cop;
|
||||
};
|
||||
|
||||
// Information about the conditional skip in the new operation sequence
|
||||
struct struct_cskip_new {
|
||||
/// new variable or parameter index for left comparison operand
|
||||
size_t left;
|
||||
/// new variable or parameter index for right comparison operand
|
||||
size_t right;
|
||||
/// maximum variable index between left and right (ignoring parameters).
|
||||
size_t max_left_right;
|
||||
/// index where this conditional skips arguments start
|
||||
size_t i_arg;
|
||||
};
|
||||
|
||||
} } } // END_CPPAD_LOCAL_OPTIMIZE_NAMESPACE
|
||||
|
||||
# endif
|
||||
@@ -0,0 +1,38 @@
|
||||
// $Id$
|
||||
# ifndef CPPAD_LOCAL_OPTIMIZE_CSUM_STACKS_HPP
|
||||
# define CPPAD_LOCAL_OPTIMIZE_CSUM_STACKS_HPP
|
||||
/* --------------------------------------------------------------------------
|
||||
CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-16 Bradley M. Bell
|
||||
|
||||
CppAD is distributed under multiple licenses. This distribution is under
|
||||
the terms of the
|
||||
Eclipse Public License Version 1.0.
|
||||
|
||||
A copy of this license is included in the COPYING file of this distribution.
|
||||
Please visit http://www.coin-or.org/CppAD/ for information on other licenses.
|
||||
-------------------------------------------------------------------------- */
|
||||
# include <stack>
|
||||
# include <cppad/local/optimize/csum_variable.hpp>
|
||||
|
||||
/*!
|
||||
\file csum_stacks.hpp
|
||||
Information about one cumulative summation operation.
|
||||
*/
|
||||
|
||||
// BEGIN_CPPAD_LOCAL_OPTIMIZE_NAMESPACE
|
||||
namespace CppAD { namespace local { namespace optimize {
|
||||
/*!
|
||||
Information about one cumulative summation operation.
|
||||
*/
|
||||
struct struct_csum_stacks {
|
||||
/// old operator indices for this cummulative summation
|
||||
std::stack<struct struct_csum_variable> op_stack;
|
||||
/// old variable indices to be added
|
||||
std::stack<size_t > add_stack;
|
||||
/// old variavle indices to be subtracted
|
||||
std::stack<size_t > sub_stack;
|
||||
};
|
||||
|
||||
} } } // END_CPPAD_LOCAL_OPTIMIZE_NAMESPACE
|
||||
|
||||
# endif
|
||||
@@ -0,0 +1,42 @@
|
||||
// $Id$
|
||||
# ifndef CPPAD_LOCAL_OPTIMIZE_CSUM_VARIABLE_HPP
|
||||
# define CPPAD_LOCAL_OPTIMIZE_CSUM_VARIABLE_HPP
|
||||
/* --------------------------------------------------------------------------
|
||||
CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-16 Bradley M. Bell
|
||||
|
||||
CppAD is distributed under multiple licenses. This distribution is under
|
||||
the terms of the
|
||||
Eclipse Public License Version 1.0.
|
||||
|
||||
A copy of this license is included in the COPYING file of this distribution.
|
||||
Please visit http://www.coin-or.org/CppAD/ for information on other licenses.
|
||||
-------------------------------------------------------------------------- */
|
||||
# include <cppad/local/op_code.hpp>
|
||||
# include <cppad/local/declare_ad.hpp> // defines addr_t
|
||||
|
||||
/*!
|
||||
\file csum_variable.hpp
|
||||
Information about one old variable that is part of a new CSumOp operation.
|
||||
*/
|
||||
|
||||
// BEGIN_CPPAD_LOCAL_OPTIMIZE_NAMESPACE
|
||||
namespace CppAD { namespace local { namespace optimize {
|
||||
/*!
|
||||
Information about one old variable that is part of a new CSumOp operation.
|
||||
*/
|
||||
struct struct_csum_variable {
|
||||
/// Pointer to first argument (child) for this old operator.
|
||||
/// Set by the reverse sweep at beginning of optimization.
|
||||
const addr_t* arg;
|
||||
|
||||
/// Was this old variable added to the summation
|
||||
/// (if not it was subtracted)
|
||||
bool add;
|
||||
|
||||
/// Operator for which this old variable is the result, NumRes(op) > 0.
|
||||
OpCode op;
|
||||
};
|
||||
|
||||
} } } // END_CPPAD_LOCAL_OPTIMIZE_NAMESPACE
|
||||
|
||||
# endif
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,58 @@
|
||||
// $Id$
|
||||
# ifndef CPPAD_LOCAL_OPTIMIZE_HASH_CODE_HPP
|
||||
# define CPPAD_LOCAL_OPTIMIZE_HASH_CODE_HPP
|
||||
|
||||
/* --------------------------------------------------------------------------
|
||||
CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-16 Bradley M. Bell
|
||||
|
||||
CppAD is distributed under multiple licenses. This distribution is under
|
||||
the terms of the
|
||||
Eclipse Public License Version 1.0.
|
||||
|
||||
A copy of this license is included in the COPYING file of this distribution.
|
||||
Please visit http://www.coin-or.org/CppAD/ for information on other licenses.
|
||||
-------------------------------------------------------------------------- */
|
||||
/*!
|
||||
\file local/optimize/hash_code.hpp
|
||||
CppAD hashing utility.
|
||||
*/
|
||||
|
||||
|
||||
// BEGIN_CPPAD_LOCAL_OPTIMIZE_NAMESPACE
|
||||
namespace CppAD { namespace local { namespace optimize {
|
||||
/*!
|
||||
Specialized hash code for a CppAD operator and its arguments
|
||||
(used during optimization).
|
||||
|
||||
\param op
|
||||
is the operator that we are computing a hash code for.
|
||||
|
||||
\param num_arg
|
||||
number of elements of arg to include in the hash code
|
||||
(num_arg <= 2).
|
||||
|
||||
\param arg
|
||||
is a vector of length num_arg
|
||||
containing the corresponding argument indices for this operator.
|
||||
|
||||
\return
|
||||
is a hash code that is between zero and CPPAD_HASH_TABLE_SIZE - 1.
|
||||
*/
|
||||
|
||||
inline size_t optimize_hash_code(
|
||||
OpCode op ,
|
||||
size_t num_arg ,
|
||||
const addr_t* arg )
|
||||
{
|
||||
//
|
||||
CPPAD_ASSERT_UNKNOWN(num_arg <= 2 );
|
||||
size_t sum = size_t(arg[0]) + size_t(op);
|
||||
if( 1 < num_arg )
|
||||
sum += size_t(arg[1]);
|
||||
//
|
||||
return sum % CPPAD_HASH_TABLE_SIZE;
|
||||
}
|
||||
|
||||
} } } // END_CPPAD_LOCAL_OPTIMIZE_NAMESPACE
|
||||
|
||||
# endif
|
||||
@@ -0,0 +1,269 @@
|
||||
# ifndef CPPAD_LOCAL_OPTIMIZE_MATCH_OP_HPP
|
||||
# define CPPAD_LOCAL_OPTIMIZE_MATCH_OP_HPP
|
||||
/* --------------------------------------------------------------------------
|
||||
CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-17 Bradley M. Bell
|
||||
|
||||
CppAD is distributed under multiple licenses. This distribution is under
|
||||
the terms of the
|
||||
Eclipse Public License Version 1.0.
|
||||
|
||||
A copy of this license is included in the COPYING file of this distribution.
|
||||
Please visit http://www.coin-or.org/CppAD/ for information on other licenses.
|
||||
-------------------------------------------------------------------------- */
|
||||
# include <cppad/local/optimize/hash_code.hpp>
|
||||
/*!
|
||||
\file match_op.hpp
|
||||
Check if current operator matches a previous operator.
|
||||
*/
|
||||
// BEGIN_CPPAD_LOCAL_OPTIMIZE_NAMESPACE
|
||||
namespace CppAD { namespace local { namespace optimize {
|
||||
/*!
|
||||
Search for a previous operator that matches the current one.
|
||||
|
||||
If an argument for the current operator is a variable,
|
||||
and the argument has previous match,
|
||||
the previous match for the argument is used when checking for a match
|
||||
for the current operator.
|
||||
|
||||
\param var2op
|
||||
mapping from variable index to operator index.
|
||||
|
||||
\param op_info
|
||||
Mapping from operator index to operator information.
|
||||
The input value of op_info[current].previous is assumed to be zero.
|
||||
If a match if found,
|
||||
the output value of op_info[current].previous is set to the
|
||||
matching operator index, otherwise it is left as is.
|
||||
Note that op_info[current].previous < current.
|
||||
|
||||
\param current
|
||||
is the index of the current operator which must be an unary
|
||||
or binary operator. Note that NumArg(ErfOp) == 3 but it is effectivey
|
||||
a unary operator and is allowed otherwise NumArg( op_info[current].op) < 3.
|
||||
It is assumed that hash_table_op is initialized as a vector of emtpy
|
||||
sets. After this initialization, the value of current inceases with
|
||||
each call to match_op.
|
||||
|
||||
\li
|
||||
This must be a unary or binary
|
||||
operator; hence, NumArg( op_info[current].op ) is one or two.
|
||||
There is one exception, NumRes( ErfOp ) == 3, but arg[0]
|
||||
is the only true arguments (the others are always the same).
|
||||
|
||||
\li
|
||||
This must not be a VecAD load or store operation; i.e.,
|
||||
LtpvOp, LtvpOp, LtvvOp, StppOp, StpvOp, StvpOp, StvvOp.
|
||||
It also must not be an independent variable operator InvOp.
|
||||
|
||||
\param hash_table_op
|
||||
is a vector of sets,
|
||||
hash_table_op.n_set() == CPPAD_HASH_TABLE_SIZE and
|
||||
hash_table_op.end() == op_info.size().
|
||||
If i_op is an element of set[j],
|
||||
then the operation op_info[i_op] has hash code j,
|
||||
and op_info[i_op] does not match any other element of set[j].
|
||||
An entry will be added each time match_op is called
|
||||
and a match for the current operator is not found.
|
||||
*/
|
||||
|
||||
inline void match_op(
|
||||
const vector<addr_t>& var2op ,
|
||||
vector<struct_op_info>& op_info ,
|
||||
size_t current ,
|
||||
sparse_list& hash_table_op )
|
||||
{ size_t num_op = op_info.size();
|
||||
//
|
||||
CPPAD_ASSERT_UNKNOWN( op_info[current].previous == 0 );
|
||||
CPPAD_ASSERT_UNKNOWN(
|
||||
hash_table_op.n_set() == CPPAD_HASH_TABLE_SIZE
|
||||
);
|
||||
CPPAD_ASSERT_UNKNOWN( hash_table_op.end() == num_op );
|
||||
CPPAD_ASSERT_UNKNOWN( current < num_op );
|
||||
//
|
||||
// current operator
|
||||
OpCode op = op_info[current].op;
|
||||
const addr_t* arg = op_info[current].arg;
|
||||
//
|
||||
// which arguments are variable
|
||||
size_t num_arg = NumArg(op);
|
||||
//
|
||||
bool variable[2];
|
||||
variable[0] = false;
|
||||
variable[1] = false;
|
||||
switch(op)
|
||||
{ //
|
||||
case ErfOp:
|
||||
num_arg = 1; // other arugments are always the same
|
||||
//
|
||||
case AbsOp:
|
||||
case AcosOp:
|
||||
case AcoshOp:
|
||||
case AsinOp:
|
||||
case AsinhOp:
|
||||
case AtanOp:
|
||||
case AtanhOp:
|
||||
case CosOp:
|
||||
case CoshOp:
|
||||
case ExpOp:
|
||||
case Expm1Op:
|
||||
case LogOp:
|
||||
case Log1pOp:
|
||||
case SignOp:
|
||||
case SinOp:
|
||||
case SinhOp:
|
||||
case SqrtOp:
|
||||
case TanOp:
|
||||
case TanhOp:
|
||||
CPPAD_ASSERT_UNKNOWN( num_arg == 1 );
|
||||
variable[0] = true;
|
||||
break;
|
||||
|
||||
|
||||
case AddpvOp:
|
||||
case DisOp:
|
||||
case DivpvOp:
|
||||
case EqpvOp:
|
||||
case LepvOp:
|
||||
case LtpvOp:
|
||||
case MulpvOp:
|
||||
case NepvOp:
|
||||
case PowpvOp:
|
||||
case SubpvOp:
|
||||
case ZmulpvOp:
|
||||
CPPAD_ASSERT_UNKNOWN( num_arg == 2 );
|
||||
variable[1] = true;
|
||||
break;
|
||||
|
||||
case DivvpOp:
|
||||
case LevpOp:
|
||||
case LtvpOp:
|
||||
case PowvpOp:
|
||||
case SubvpOp:
|
||||
case ZmulvpOp:
|
||||
CPPAD_ASSERT_UNKNOWN( num_arg == 2 );
|
||||
variable[0] = true;
|
||||
break;
|
||||
|
||||
case AddvvOp:
|
||||
case DivvvOp:
|
||||
case EqvvOp:
|
||||
case LevvOp:
|
||||
case LtvvOp:
|
||||
case MulvvOp:
|
||||
case NevvOp:
|
||||
case PowvvOp:
|
||||
case SubvvOp:
|
||||
case ZmulvvOp:
|
||||
CPPAD_ASSERT_UNKNOWN( num_arg == 2 );
|
||||
variable[0] = true;
|
||||
variable[1] = true;
|
||||
break;
|
||||
|
||||
default:
|
||||
CPPAD_ASSERT_UNKNOWN(false);
|
||||
}
|
||||
//
|
||||
// If i-th argument to current operator has a previous operator,
|
||||
// this is the i-th argument for previous operator.
|
||||
// Otherwise, it is the i-th argument for the current operator
|
||||
// (if a previous variable exists)
|
||||
addr_t arg_match[2];
|
||||
for(size_t j = 0; j < num_arg; ++j)
|
||||
{ arg_match[j] = arg[j];
|
||||
if( variable[j] )
|
||||
{ size_t previous = op_info[ var2op[arg[j]] ].previous;
|
||||
if( previous != 0 )
|
||||
{ CPPAD_ASSERT_UNKNOWN( op_info[previous].previous == 0 );
|
||||
//
|
||||
arg_match[j] = op_info[previous].i_var;
|
||||
}
|
||||
}
|
||||
}
|
||||
size_t code = optimize_hash_code(op, num_arg, arg_match);
|
||||
//
|
||||
// iterator for the set with this hash code
|
||||
sparse_list_const_iterator itr(hash_table_op, code);
|
||||
//
|
||||
// check for a match
|
||||
size_t count = 0;
|
||||
while( *itr != num_op )
|
||||
{ ++count;
|
||||
//
|
||||
// candidate previous for current operator
|
||||
size_t candidate = *itr;
|
||||
CPPAD_ASSERT_UNKNOWN( candidate < current );
|
||||
CPPAD_ASSERT_UNKNOWN( op_info[candidate].previous == 0 );
|
||||
//
|
||||
// check for a match
|
||||
bool match = op == op_info[candidate].op;
|
||||
if( match )
|
||||
{ for(size_t j = 0; j < num_arg; j++)
|
||||
{ if( variable[j] )
|
||||
{ size_t previous =
|
||||
op_info[ var2op[op_info[candidate].arg[j]] ].previous;
|
||||
if( previous != 0 )
|
||||
{ CPPAD_ASSERT_UNKNOWN(op_info[previous].previous == 0);
|
||||
//
|
||||
match &=
|
||||
arg_match[j] == addr_t( op_info[previous].i_var );
|
||||
}
|
||||
else
|
||||
match &= arg_match[j] == op_info[candidate].arg[j];
|
||||
}
|
||||
}
|
||||
}
|
||||
if( match )
|
||||
{ op_info[current].previous = static_cast<addr_t>( candidate );
|
||||
return;
|
||||
}
|
||||
++itr;
|
||||
}
|
||||
|
||||
// special case where operator is commutative
|
||||
if( (op == AddvvOp) | (op == MulvvOp ) )
|
||||
{ CPPAD_ASSERT_UNKNOWN( NumArg(op) == 2 );
|
||||
std::swap( arg_match[0], arg_match[1] );
|
||||
//
|
||||
code = optimize_hash_code(op, num_arg, arg_match);
|
||||
sparse_list_const_iterator itr_swap(hash_table_op, code);
|
||||
while( *itr_swap != num_op )
|
||||
{
|
||||
size_t candidate = *itr_swap;
|
||||
CPPAD_ASSERT_UNKNOWN( candidate < current );
|
||||
CPPAD_ASSERT_UNKNOWN( op_info[candidate].previous == 0 );
|
||||
//
|
||||
bool match = op == op_info[candidate].op;
|
||||
if( match )
|
||||
{ for(size_t j = 0; j < num_arg; j++)
|
||||
{ CPPAD_ASSERT_UNKNOWN( variable[j] )
|
||||
size_t previous =
|
||||
op_info[ var2op[op_info[candidate].arg[j]] ].previous;
|
||||
if( previous != 0 )
|
||||
{ CPPAD_ASSERT_UNKNOWN(op_info[previous].previous == 0);
|
||||
//
|
||||
match &=
|
||||
arg_match[j] == addr_t( op_info[previous].i_var );
|
||||
}
|
||||
else
|
||||
match &= arg_match[j] == op_info[candidate].arg[j];
|
||||
}
|
||||
}
|
||||
if( match )
|
||||
{ op_info[current].previous = static_cast<addr_t>( candidate );
|
||||
return;
|
||||
}
|
||||
++itr_swap;
|
||||
}
|
||||
}
|
||||
CPPAD_ASSERT_UNKNOWN( count < 11 );
|
||||
if( count == 10 )
|
||||
{ // restart the list
|
||||
hash_table_op.clear(code);
|
||||
}
|
||||
// no match was found, add this operator the the set for this hash code
|
||||
hash_table_op.add_element(code, current);
|
||||
}
|
||||
|
||||
} } } // END_CPPAD_LOCAL_OPTIMIZE_NAMESPACE
|
||||
|
||||
# endif
|
||||
@@ -0,0 +1,34 @@
|
||||
// $Id$
|
||||
# ifndef CPPAD_LOCAL_OPTIMIZE_OLD2NEW_HPP
|
||||
# define CPPAD_LOCAL_OPTIMIZE_OLD2NEW_HPP
|
||||
/* --------------------------------------------------------------------------
|
||||
CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-16 Bradley M. Bell
|
||||
|
||||
CppAD is distributed under multiple licenses. This distribution is under
|
||||
the terms of the
|
||||
Eclipse Public License Version 1.0.
|
||||
|
||||
A copy of this license is included in the COPYING file of this distribution.
|
||||
Please visit http://www.coin-or.org/CppAD/ for information on other licenses.
|
||||
-------------------------------------------------------------------------- */
|
||||
/*!
|
||||
\file old2new.hpp
|
||||
Information that maps old an old operator to a new opeator and new variable.
|
||||
*/
|
||||
|
||||
// BEGIN_CPPAD_LOCAL_OPTIMIZE_NAMESPACE
|
||||
namespace CppAD { namespace local { namespace optimize {
|
||||
/*!
|
||||
Information that maps old an old operator to a new opeator and new variable.
|
||||
*/
|
||||
struct struct_old2new {
|
||||
/// New operator index for this old operator.
|
||||
addr_t new_op;
|
||||
|
||||
/// New varaible index for this old operator.
|
||||
addr_t new_var;
|
||||
};
|
||||
|
||||
} } } // END_CPPAD_LOCAL_OPTIMIZE_NAMESPACE
|
||||
|
||||
# endif
|
||||
@@ -0,0 +1,51 @@
|
||||
// $Id$
|
||||
# ifndef CPPAD_LOCAL_OPTIMIZE_OP_INFO_HPP
|
||||
# define CPPAD_LOCAL_OPTIMIZE_OP_INFO_HPP
|
||||
/* --------------------------------------------------------------------------
|
||||
CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-16 Bradley M. Bell
|
||||
|
||||
CppAD is distributed under multiple licenses. This distribution is under
|
||||
the terms of the
|
||||
Eclipse Public License Version 1.0.
|
||||
|
||||
A copy of this license is included in the COPYING file of this distribution.
|
||||
Please visit http://www.coin-or.org/CppAD/ for information on other licenses.
|
||||
-------------------------------------------------------------------------- */
|
||||
|
||||
# include <cppad/local/op_code.hpp>
|
||||
# include <cppad/local/optimize/usage.hpp>
|
||||
|
||||
// BEGIN_CPPAD_LOCAL_OPTIMIZE_NAMESPACE
|
||||
namespace CppAD { namespace local { namespace optimize {
|
||||
|
||||
/// information for one operator
|
||||
struct struct_op_info {
|
||||
/// arguments
|
||||
const addr_t* arg;
|
||||
|
||||
/// Primary (not auxillary) variable index for this operator. If the
|
||||
// operator has not results, this is num_var (an invalid variable index).
|
||||
addr_t i_var;
|
||||
|
||||
/*!
|
||||
previous operator that can be used in place of this operator.
|
||||
\li
|
||||
If previous == 0, no such operator was found.
|
||||
\li
|
||||
If previous != 0,
|
||||
op_info[pevious].previous == 0 and
|
||||
op_info[previous].usage == yes_usage.
|
||||
*/
|
||||
addr_t previous;
|
||||
|
||||
/// op code
|
||||
OpCode op;
|
||||
|
||||
/// How is this operator used to compute the dependent variables.
|
||||
/// If usage = csum_usage or usage = no_usage, previous = 0.
|
||||
enum_usage usage;
|
||||
|
||||
};
|
||||
|
||||
} } } // END_CPPAD_LOCAL_OPTIMIZE_NAMESPACE
|
||||
# endif
|
||||
@@ -0,0 +1,922 @@
|
||||
|
||||
# ifndef CPPAD_LOCAL_OPTIMIZE_OPTIMIZE_RUN_HPP
|
||||
# define CPPAD_LOCAL_OPTIMIZE_OPTIMIZE_RUN_HPP
|
||||
|
||||
/* --------------------------------------------------------------------------
|
||||
CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-17 Bradley M. Bell
|
||||
|
||||
CppAD is distributed under multiple licenses. This distribution is under
|
||||
the terms of the
|
||||
Eclipse Public License Version 1.0.
|
||||
|
||||
A copy of this license is included in the COPYING file of this distribution.
|
||||
Please visit http://www.coin-or.org/CppAD/ for information on other licenses.
|
||||
-------------------------------------------------------------------------- */
|
||||
|
||||
# include <stack>
|
||||
# include <iterator>
|
||||
# include <cppad/local/optimize/usage.hpp>
|
||||
# include <cppad/local/optimize/get_op_info.hpp>
|
||||
# include <cppad/local/optimize/old2new.hpp>
|
||||
# include <cppad/local/optimize/size_pair.hpp>
|
||||
# include <cppad/local/optimize/csum_variable.hpp>
|
||||
# include <cppad/local/optimize/csum_stacks.hpp>
|
||||
# include <cppad/local/optimize/cexp_info.hpp>
|
||||
# include <cppad/local/optimize/match_op.hpp>
|
||||
# include <cppad/local/optimize/record_pv.hpp>
|
||||
# include <cppad/local/optimize/record_vp.hpp>
|
||||
# include <cppad/local/optimize/record_vv.hpp>
|
||||
# include <cppad/local/optimize/record_csum.hpp>
|
||||
|
||||
/*!
|
||||
\file optimize_run.hpp
|
||||
Convert a player object to an optimized recorder object
|
||||
*/
|
||||
// BEGIN_CPPAD_LOCAL_OPTIMIZE_NAMESPACE
|
||||
namespace CppAD { namespace local { namespace optimize {
|
||||
/*!
|
||||
Convert a player object to an optimized recorder object
|
||||
|
||||
\tparam Base
|
||||
base type for the operator; i.e., this operation was recorded
|
||||
using AD< \a Base > and computations by this routine are done using type
|
||||
\a Base.
|
||||
|
||||
|
||||
\param options
|
||||
\li
|
||||
If the sub-string "no_conditional_skip" appears,
|
||||
conditional skip operations will not be generated.
|
||||
This may make the optimize routine use significantly less memory
|
||||
and take significantly less time.
|
||||
\li
|
||||
If the sub-string "no_compare_op" appears,
|
||||
then comparison operators will be removed from the optimized tape.
|
||||
These operators are necessary for the compare_change function to be
|
||||
be meaningful in the resulting recording.
|
||||
On the other hand, they are not necessary and take extra time
|
||||
when compare_change is not used.
|
||||
\li
|
||||
If the sub-string "no_print_for" appears,
|
||||
then print forward (PriOp) operators will be removed from the optimized tape.
|
||||
These operators are useful for reporting problems evaluating derivatives
|
||||
at independent variable values different from those used to record a function.
|
||||
|
||||
\param n
|
||||
is the number of independent variables on the tape.
|
||||
|
||||
\param dep_taddr
|
||||
On input this vector contains the indices for each of the dependent
|
||||
variable values in the operation sequence corresponding to \a play.
|
||||
Upon return it contains the indices for the same variables but in
|
||||
the operation sequence corresponding to \a rec.
|
||||
|
||||
\param play
|
||||
This is the operation sequence that we are optimizing.
|
||||
It is essentially const, except for play back state which
|
||||
changes while it plays back the operation seqeunce.
|
||||
|
||||
\param rec
|
||||
The input contents of this recording does not matter.
|
||||
Upon return, it contains an optimized verison of the
|
||||
operation sequence corresponding to \a play.
|
||||
*/
|
||||
|
||||
template <class Base>
|
||||
void optimize_run(
|
||||
const std::string& options ,
|
||||
size_t n ,
|
||||
CppAD::vector<size_t>& dep_taddr ,
|
||||
player<Base>* play ,
|
||||
recorder<Base>* rec )
|
||||
{
|
||||
bool conditional_skip = true;
|
||||
bool compare_op = true;
|
||||
bool print_for_op = true;
|
||||
size_t index = 0;
|
||||
while( index < options.size() )
|
||||
{ while( index < options.size() && options[index] == ' ' )
|
||||
++index;
|
||||
std::string option;
|
||||
while( index < options.size() && options[index] != ' ' )
|
||||
option += options[index++];
|
||||
if( option != "" )
|
||||
{ if( option == "no_conditional_skip" )
|
||||
conditional_skip = false;
|
||||
else if( option == "no_compare_op" )
|
||||
compare_op = false;
|
||||
else if( option == "no_print_for_op" )
|
||||
print_for_op = false;
|
||||
else
|
||||
{ option += " is not a valid optimize option";
|
||||
CPPAD_ASSERT_KNOWN( false , option.c_str() );
|
||||
}
|
||||
}
|
||||
}
|
||||
// number of operators in the player
|
||||
const size_t num_op = play->num_op_rec();
|
||||
CPPAD_ASSERT_UNKNOWN(
|
||||
num_op < size_t( std::numeric_limits<addr_t>::max() )
|
||||
);
|
||||
|
||||
// number of variables in the player
|
||||
const size_t num_var = play->num_var_rec();
|
||||
|
||||
// number of VecAD indices
|
||||
size_t num_vecad_ind = play->num_vec_ind_rec();
|
||||
|
||||
// number of VecAD vectors
|
||||
size_t num_vecad_vec = play->num_vecad_vec_rec();
|
||||
|
||||
// operator information
|
||||
vector<addr_t> var2op;
|
||||
vector<struct_cexp_info> cexp_info;
|
||||
sparse_list skip_op_true;
|
||||
sparse_list skip_op_false;
|
||||
vector<bool> vecad_used;
|
||||
vector<struct_op_info> op_info;
|
||||
get_op_info(
|
||||
conditional_skip,
|
||||
compare_op,
|
||||
print_for_op,
|
||||
play,
|
||||
dep_taddr,
|
||||
var2op,
|
||||
cexp_info,
|
||||
skip_op_true,
|
||||
skip_op_false,
|
||||
vecad_used,
|
||||
op_info
|
||||
);
|
||||
|
||||
// nan with type Base
|
||||
Base base_nan = Base( std::numeric_limits<double>::quiet_NaN() );
|
||||
|
||||
// -------------------------------------------------------------
|
||||
// information for current operator
|
||||
size_t i_op; // index
|
||||
OpCode op; // operator
|
||||
const addr_t* arg; // arguments
|
||||
size_t i_var; // variable index of primary (last) result
|
||||
|
||||
enum_user_state user_state;
|
||||
// -------------------------------------------------------------
|
||||
// conditional expression information
|
||||
//
|
||||
// Size of the conditional expression information structure.
|
||||
// This is equal to the number of conditional expressions when
|
||||
// conditional_skip is true, otherwise it is zero.
|
||||
size_t num_cexp = cexp_info.size();
|
||||
CPPAD_ASSERT_UNKNOWN( conditional_skip || num_cexp == 0 );
|
||||
//
|
||||
// sort the conditional expression information by max_left_right
|
||||
// this is the conditional skip order
|
||||
vector<size_t> cskip_order(num_cexp);
|
||||
if( num_cexp > 0 )
|
||||
{ CppAD::vector<size_t> keys(num_cexp);
|
||||
for(size_t i = 0; i < num_cexp; i++)
|
||||
keys[i] = cexp_info[i].max_left_right;
|
||||
CppAD::index_sort(keys, cskip_order);
|
||||
}
|
||||
// initial index in conditional skip order
|
||||
size_t cskip_order_next = 0;
|
||||
//
|
||||
// initialize index in conditional expression order
|
||||
size_t cexp_next = 0;
|
||||
|
||||
// mapping from conditional expression index to conditional skip
|
||||
// information on new tape
|
||||
vector<struct_cskip_new> cskip_new(num_cexp);
|
||||
//
|
||||
// flag used to indicate that there is no conditional skip
|
||||
// for this conditional expression
|
||||
for(size_t i = 0; i < num_cexp; i++)
|
||||
cskip_new[i].i_arg = 0;
|
||||
// -------------------------------------------------------------
|
||||
|
||||
// Erase all information in the old recording
|
||||
rec->free();
|
||||
|
||||
// initialize mapping from old VecAD index to new VecAD index
|
||||
CPPAD_ASSERT_UNKNOWN(
|
||||
std::numeric_limits<addr_t>::max() >= num_vecad_ind
|
||||
);
|
||||
CppAD::vector<addr_t> new_vecad_ind(num_vecad_ind);
|
||||
for(size_t i = 0; i < num_vecad_ind; i++)
|
||||
new_vecad_ind[i] = addr_t( num_vecad_ind ); // invalid index
|
||||
{
|
||||
size_t j = 0; // index into the old set of indices
|
||||
for(size_t i = 0; i < num_vecad_vec; i++)
|
||||
{ // length of this VecAD
|
||||
size_t length = play->GetVecInd(j);
|
||||
if( vecad_used[i] )
|
||||
{ // Put this VecAD vector in new recording
|
||||
CPPAD_ASSERT_UNKNOWN(length < num_vecad_ind);
|
||||
new_vecad_ind[j] = rec->PutVecInd(length);
|
||||
for(size_t k = 1; k <= length; k++) new_vecad_ind[j+k] =
|
||||
rec->PutVecInd(
|
||||
rec->PutPar(
|
||||
play->GetPar(
|
||||
play->GetVecInd(j+k)
|
||||
) ) );
|
||||
}
|
||||
// start of next VecAD
|
||||
j += length + 1;
|
||||
}
|
||||
CPPAD_ASSERT_UNKNOWN( j == num_vecad_ind );
|
||||
}
|
||||
//
|
||||
// Mapping from old operator index to new operator information
|
||||
// (zero is invalid except for old2new[0].new_op and old2new[0].i_var)
|
||||
vector<struct_old2new> old2new(num_op);
|
||||
for(size_t i = 0; i < num_op; i++)
|
||||
{ old2new[i].new_op = 0;
|
||||
old2new[i].new_var = 0;
|
||||
}
|
||||
|
||||
|
||||
// temporary buffer for new argument values
|
||||
addr_t new_arg[6];
|
||||
|
||||
// temporary work space used by record_csum
|
||||
// (decalared here to avoid realloaction of memory)
|
||||
struct_csum_stacks csum_work;
|
||||
|
||||
// tempory used to hold a size_pair
|
||||
struct_size_pair size_pair;
|
||||
|
||||
user_state = start_user;
|
||||
for(i_op = 0; i_op < num_op; ++i_op)
|
||||
{ addr_t mask; // temporary used in some switch cases
|
||||
//
|
||||
// this operator information
|
||||
op = op_info[i_op].op;
|
||||
arg = op_info[i_op].arg;
|
||||
i_var = op_info[i_op].i_var;
|
||||
//
|
||||
// determine if we should insert a conditional skip here
|
||||
bool skip = conditional_skip;
|
||||
skip &= cskip_order_next < num_cexp;
|
||||
skip &= op != BeginOp;
|
||||
skip &= op != InvOp;
|
||||
skip &= user_state == start_user;
|
||||
if( skip )
|
||||
{ size_t j = cskip_order[cskip_order_next];
|
||||
if( NumRes(op) > 0 )
|
||||
skip &= cexp_info[j].max_left_right < i_var;
|
||||
else
|
||||
skip &= cexp_info[j].max_left_right <= i_var;
|
||||
}
|
||||
if( skip )
|
||||
{ size_t j = cskip_order[cskip_order_next];
|
||||
cskip_order_next++;
|
||||
size_t n_true = skip_op_true.number_elements(j);
|
||||
size_t n_false = skip_op_false.number_elements(j);
|
||||
skip &= n_true > 0 || n_false > 0;
|
||||
if( skip )
|
||||
{ CPPAD_ASSERT_UNKNOWN( NumRes(CSkipOp) == 0 );
|
||||
size_t n_arg = 7 + n_true + n_false;
|
||||
// reserve space for the arguments to this operator but
|
||||
// delay setting them until we have all the new addresses
|
||||
cskip_new[j].i_arg = rec->ReserveArg(n_arg);
|
||||
// i_arg == 0 is used to check if conditional expression
|
||||
// has been skipped.
|
||||
CPPAD_ASSERT_UNKNOWN( cskip_new[j].i_arg > 0 );
|
||||
// There is no corresponding old operator in this case
|
||||
rec->PutOp(CSkipOp);
|
||||
}
|
||||
}
|
||||
if( op == UserOp )
|
||||
{ if( user_state == start_user )
|
||||
user_state = end_user;
|
||||
else
|
||||
{ CPPAD_ASSERT_UNKNOWN( user_state == end_user );
|
||||
user_state = start_user;
|
||||
}
|
||||
}
|
||||
size_t previous;
|
||||
//
|
||||
CPPAD_ASSERT_UNKNOWN(
|
||||
std::numeric_limits<addr_t>::max() >= rec->num_op_rec()
|
||||
);
|
||||
//
|
||||
if( op_info[i_op].usage != yes_usage )
|
||||
{ if( op == CExpOp )
|
||||
++cexp_next;
|
||||
}
|
||||
else switch( op )
|
||||
{
|
||||
case BeginOp:
|
||||
CPPAD_ASSERT_NARG_NRES(op, 1, 1);
|
||||
// Put BeginOp at beginning of recording
|
||||
old2new[i_op].new_op = addr_t( rec->num_op_rec() );
|
||||
old2new[i_op].new_var = rec->PutOp(BeginOp);
|
||||
rec->PutArg(arg[0]);
|
||||
break;
|
||||
|
||||
// --------------------------------------------------------------
|
||||
// Unary operators, argument a variable, one result
|
||||
case AbsOp:
|
||||
case AcosOp:
|
||||
case AcoshOp:
|
||||
case AsinOp:
|
||||
case AsinhOp:
|
||||
case AtanOp:
|
||||
case AtanhOp:
|
||||
case CosOp:
|
||||
case CoshOp:
|
||||
case ErfOp:
|
||||
case ExpOp:
|
||||
case Expm1Op:
|
||||
case LogOp:
|
||||
case Log1pOp:
|
||||
case SignOp:
|
||||
case SinOp:
|
||||
case SinhOp:
|
||||
case SqrtOp:
|
||||
case TanOp:
|
||||
case TanhOp:
|
||||
previous = op_info[i_op].previous;
|
||||
if( previous > 0 )
|
||||
{ size_t j_op = previous;
|
||||
old2new[i_op].new_var = old2new[j_op].new_var;
|
||||
}
|
||||
else
|
||||
{ //
|
||||
new_arg[0] = old2new[ var2op[arg[0]] ].new_var;
|
||||
rec->PutArg( new_arg[0] );
|
||||
//
|
||||
old2new[i_op].new_op = addr_t( rec->num_op_rec() );
|
||||
old2new[i_op].new_var = rec->PutOp(op);
|
||||
CPPAD_ASSERT_UNKNOWN(
|
||||
new_arg[0] < old2new[var2op[i_var]].new_var
|
||||
);
|
||||
if( op == ErfOp )
|
||||
{ CPPAD_ASSERT_NARG_NRES(op, 3, 5);
|
||||
// Error function is a special case
|
||||
// second argument is always the parameter 0
|
||||
// third argument is always the parameter 2 / sqrt(pi)
|
||||
CPPAD_ASSERT_UNKNOWN( NumArg(ErfOp) == 3 );
|
||||
rec->PutArg( rec->PutPar( Base(0.0) ) );
|
||||
rec->PutArg( rec->PutPar(
|
||||
Base( 1.0 / std::sqrt( std::atan(1.0) ) )
|
||||
) );
|
||||
}
|
||||
else
|
||||
{ // some of these operators have an auxillary result;
|
||||
// e.g. sine and cosine are computed together.
|
||||
CPPAD_ASSERT_UNKNOWN( NumArg(op) == 1 );
|
||||
CPPAD_ASSERT_UNKNOWN( NumRes(op) ==1 || NumRes(op) == 2 );
|
||||
}
|
||||
}
|
||||
break;
|
||||
// ---------------------------------------------------
|
||||
// Binary operators, left variable, right parameter, one result
|
||||
case SubvpOp:
|
||||
// check if this is the top of a csum connection
|
||||
if( op_info[i_op].usage == csum_usage )
|
||||
break;
|
||||
if( op_info[ var2op[arg[0]] ].usage == csum_usage )
|
||||
{
|
||||
// convert to a sequence of summation operators
|
||||
size_pair = record_csum(
|
||||
var2op ,
|
||||
op_info ,
|
||||
old2new ,
|
||||
i_var ,
|
||||
play->num_par_rec() ,
|
||||
play->GetPar() ,
|
||||
rec ,
|
||||
csum_work
|
||||
);
|
||||
old2new[i_op].new_op = addr_t( size_pair.i_op );
|
||||
old2new[i_op].new_var = addr_t( size_pair.i_var );
|
||||
// abort rest of this case
|
||||
break;
|
||||
}
|
||||
case DivvpOp:
|
||||
case PowvpOp:
|
||||
case ZmulvpOp:
|
||||
previous = op_info[i_op].previous;
|
||||
if( previous > 0 )
|
||||
{ size_t j_op = previous;
|
||||
old2new[i_op].new_var = old2new[j_op].new_var;
|
||||
}
|
||||
else
|
||||
{ //
|
||||
size_pair = record_vp(
|
||||
var2op ,
|
||||
op_info ,
|
||||
old2new ,
|
||||
i_var ,
|
||||
play->num_par_rec() ,
|
||||
play->GetPar() ,
|
||||
rec ,
|
||||
op ,
|
||||
arg
|
||||
);
|
||||
old2new[i_op].new_op = addr_t( size_pair.i_op );
|
||||
old2new[i_op].new_var = addr_t( size_pair.i_var );
|
||||
}
|
||||
break;
|
||||
// ---------------------------------------------------
|
||||
// Binary operators, left index, right variable, one result
|
||||
case DisOp:
|
||||
CPPAD_ASSERT_NARG_NRES(op, 2, 1);
|
||||
previous = op_info[i_op].previous;
|
||||
if( previous > 0 )
|
||||
{ size_t j_op = previous;
|
||||
old2new[i_op].new_var = old2new[j_op].new_var;
|
||||
}
|
||||
else
|
||||
{ //
|
||||
new_arg[0] = arg[0];
|
||||
new_arg[1] = old2new[ var2op[arg[1]] ].new_var;
|
||||
rec->PutArg( new_arg[0], new_arg[1] );
|
||||
//
|
||||
old2new[i_op].new_op = addr_t( rec->num_op_rec() );
|
||||
old2new[i_op].new_var = rec->PutOp(op);
|
||||
CPPAD_ASSERT_UNKNOWN(
|
||||
new_arg[1] < old2new[var2op[i_var]].new_var
|
||||
);
|
||||
}
|
||||
break;
|
||||
|
||||
// ---------------------------------------------------
|
||||
// Binary operators, left parameter, right variable, one result
|
||||
case SubpvOp:
|
||||
case AddpvOp:
|
||||
// check if this is the top of a csum connection
|
||||
if( op_info[i_op].usage == csum_usage )
|
||||
break;
|
||||
if( op_info[ var2op[arg[1]] ].usage == csum_usage )
|
||||
{
|
||||
// convert to a sequence of summation operators
|
||||
size_pair = record_csum(
|
||||
var2op ,
|
||||
op_info ,
|
||||
old2new ,
|
||||
i_var ,
|
||||
play->num_par_rec() ,
|
||||
play->GetPar() ,
|
||||
rec ,
|
||||
csum_work
|
||||
);
|
||||
old2new[i_op].new_op = addr_t( size_pair.i_op );
|
||||
old2new[i_op].new_var = addr_t( size_pair.i_var );
|
||||
// abort rest of this case
|
||||
break;
|
||||
}
|
||||
case DivpvOp:
|
||||
case MulpvOp:
|
||||
case PowpvOp:
|
||||
case ZmulpvOp:
|
||||
previous = op_info[i_op].previous;
|
||||
if( previous > 0 )
|
||||
{ size_t j_op = previous;
|
||||
old2new[i_op].new_var = old2new[j_op].new_var;
|
||||
}
|
||||
else
|
||||
{ //
|
||||
size_pair = record_pv(
|
||||
var2op ,
|
||||
op_info ,
|
||||
old2new ,
|
||||
i_var ,
|
||||
play->num_par_rec() ,
|
||||
play->GetPar() ,
|
||||
rec ,
|
||||
op ,
|
||||
arg
|
||||
);
|
||||
old2new[i_op].new_op = addr_t( size_pair.i_op );
|
||||
old2new[i_op].new_var = addr_t( size_pair.i_var );
|
||||
}
|
||||
break;
|
||||
// ---------------------------------------------------
|
||||
// Binary operator, left and right variables, one result
|
||||
case AddvvOp:
|
||||
case SubvvOp:
|
||||
// check if this is the top of a csum connection
|
||||
if( op_info[i_op].usage == csum_usage )
|
||||
break;
|
||||
if(
|
||||
op_info[ var2op[arg[0]] ].usage == csum_usage ||
|
||||
op_info[ var2op[arg[1]] ].usage == csum_usage
|
||||
)
|
||||
{
|
||||
// convert to a sequence of summation operators
|
||||
size_pair = record_csum(
|
||||
var2op ,
|
||||
op_info ,
|
||||
old2new ,
|
||||
i_var ,
|
||||
play->num_par_rec() ,
|
||||
play->GetPar() ,
|
||||
rec ,
|
||||
csum_work
|
||||
);
|
||||
old2new[i_op].new_op = addr_t( size_pair.i_op );
|
||||
old2new[i_op].new_var = addr_t( size_pair.i_var );
|
||||
// abort rest of this case
|
||||
break;
|
||||
}
|
||||
case DivvvOp:
|
||||
case MulvvOp:
|
||||
case PowvvOp:
|
||||
case ZmulvvOp:
|
||||
previous = op_info[i_op].previous;
|
||||
if( previous > 0 )
|
||||
{ size_t j_op = previous;
|
||||
old2new[i_op].new_var = old2new[j_op].new_var;
|
||||
}
|
||||
else
|
||||
{ //
|
||||
size_pair = record_vv(
|
||||
var2op ,
|
||||
op_info ,
|
||||
old2new ,
|
||||
i_var ,
|
||||
play->num_par_rec() ,
|
||||
play->GetPar() ,
|
||||
rec ,
|
||||
op ,
|
||||
arg
|
||||
);
|
||||
old2new[i_op].new_op = addr_t( size_pair.i_op );
|
||||
old2new[i_op].new_var = addr_t( size_pair.i_var );
|
||||
}
|
||||
break;
|
||||
// ---------------------------------------------------
|
||||
// Conditional expression operators
|
||||
case CExpOp:
|
||||
CPPAD_ASSERT_NARG_NRES(op, 6, 1);
|
||||
new_arg[0] = arg[0];
|
||||
new_arg[1] = arg[1];
|
||||
mask = 1;
|
||||
for(size_t i = 2; i < 6; i++)
|
||||
{ if( arg[1] & mask )
|
||||
{ new_arg[i] = old2new[ var2op[arg[i]] ].new_var;
|
||||
CPPAD_ASSERT_UNKNOWN(
|
||||
size_t(new_arg[i]) < num_var
|
||||
);
|
||||
}
|
||||
else new_arg[i] = rec->PutPar(
|
||||
play->GetPar( arg[i] )
|
||||
);
|
||||
mask = mask << 1;
|
||||
}
|
||||
rec->PutArg(
|
||||
new_arg[0] ,
|
||||
new_arg[1] ,
|
||||
new_arg[2] ,
|
||||
new_arg[3] ,
|
||||
new_arg[4] ,
|
||||
new_arg[5]
|
||||
);
|
||||
old2new[i_op].new_op = addr_t( rec->num_op_rec() );
|
||||
old2new[i_op].new_var = rec->PutOp(op);
|
||||
//
|
||||
// The new addresses for left and right are used during
|
||||
// fill in the arguments for the CSkip operations. This does not
|
||||
// affect max_left_right which is used during this sweep.
|
||||
if( conditional_skip )
|
||||
{ CPPAD_ASSERT_UNKNOWN( cexp_next < num_cexp );
|
||||
CPPAD_ASSERT_UNKNOWN( cexp_info[cexp_next].i_op == i_op );
|
||||
cskip_new[ cexp_next ].left = new_arg[2];
|
||||
cskip_new[ cexp_next ].right = new_arg[3];
|
||||
++cexp_next;
|
||||
}
|
||||
break;
|
||||
// ---------------------------------------------------
|
||||
// Operations with no arguments and no results
|
||||
case EndOp:
|
||||
CPPAD_ASSERT_NARG_NRES(op, 0, 0);
|
||||
old2new[i_op].new_op = addr_t( rec->num_op_rec() );
|
||||
rec->PutOp(op);
|
||||
break;
|
||||
// ---------------------------------------------------
|
||||
// Operations with two arguments and no results
|
||||
case LepvOp:
|
||||
case LtpvOp:
|
||||
case EqpvOp:
|
||||
case NepvOp:
|
||||
CPPAD_ASSERT_NARG_NRES(op, 2, 0);
|
||||
new_arg[0] = rec->PutPar( play->GetPar(arg[0]) );
|
||||
new_arg[1] = old2new[ var2op[arg[1]] ].new_var;
|
||||
rec->PutArg(new_arg[0], new_arg[1]);
|
||||
old2new[i_op].new_op = addr_t( rec->num_op_rec() );
|
||||
rec->PutOp(op);
|
||||
break;
|
||||
//
|
||||
case LevpOp:
|
||||
case LtvpOp:
|
||||
CPPAD_ASSERT_NARG_NRES(op, 2, 0);
|
||||
new_arg[0] = old2new[ var2op[arg[0]] ].new_var;
|
||||
new_arg[1] = rec->PutPar( play->GetPar(arg[1]) );
|
||||
rec->PutArg(new_arg[0], new_arg[1]);
|
||||
old2new[i_op].new_op = addr_t( rec->num_op_rec() );
|
||||
rec->PutOp(op);
|
||||
break;
|
||||
//
|
||||
case LevvOp:
|
||||
case LtvvOp:
|
||||
case EqvvOp:
|
||||
case NevvOp:
|
||||
CPPAD_ASSERT_NARG_NRES(op, 2, 0);
|
||||
new_arg[0] = old2new[ var2op[arg[0]] ].new_var;
|
||||
new_arg[1] = old2new[ var2op[arg[1]] ].new_var;
|
||||
rec->PutArg(new_arg[0], new_arg[1]);
|
||||
old2new[i_op].new_op = addr_t( rec->num_op_rec() );
|
||||
rec->PutOp(op);
|
||||
break;
|
||||
|
||||
// ---------------------------------------------------
|
||||
// Operations with no arguments and one result
|
||||
case InvOp:
|
||||
CPPAD_ASSERT_NARG_NRES(op, 0, 1);
|
||||
old2new[i_op].new_op = addr_t( rec->num_op_rec() );
|
||||
old2new[i_op].new_var = rec->PutOp(op);
|
||||
break;
|
||||
|
||||
// ---------------------------------------------------
|
||||
// Unary operators, argument a parameter, one result
|
||||
case ParOp:
|
||||
CPPAD_ASSERT_NARG_NRES(op, 1, 1);
|
||||
new_arg[0] = rec->PutPar( play->GetPar(arg[0] ) );
|
||||
rec->PutArg( new_arg[0] );
|
||||
//
|
||||
old2new[i_op].new_op = addr_t( rec->num_op_rec() );
|
||||
old2new[i_op].new_var = rec->PutOp(op);
|
||||
break;
|
||||
|
||||
// ---------------------------------------------------
|
||||
// print forward operator
|
||||
case PriOp:
|
||||
CPPAD_ASSERT_NARG_NRES(op, 5, 0);
|
||||
// arg[0]
|
||||
new_arg[0] = arg[0];
|
||||
//
|
||||
// arg[1]
|
||||
if( arg[0] & 1 )
|
||||
{ new_arg[1] = old2new[ var2op[arg[1]] ].new_var;
|
||||
CPPAD_ASSERT_UNKNOWN( size_t(new_arg[1]) < num_var );
|
||||
}
|
||||
else
|
||||
{ new_arg[1] = rec->PutPar( play->GetPar( arg[1] ) );
|
||||
}
|
||||
//
|
||||
// arg[3]
|
||||
if( arg[0] & 2 )
|
||||
{ new_arg[3] = old2new[ var2op[arg[3]] ].new_var;
|
||||
CPPAD_ASSERT_UNKNOWN( size_t(new_arg[3]) < num_var );
|
||||
}
|
||||
else
|
||||
{ new_arg[3] = rec->PutPar( play->GetPar( arg[3] ) );
|
||||
}
|
||||
new_arg[2] = rec->PutTxt( play->GetTxt(arg[2]) );
|
||||
new_arg[4] = rec->PutTxt( play->GetTxt(arg[4]) );
|
||||
//
|
||||
rec->PutArg(
|
||||
new_arg[0] ,
|
||||
new_arg[1] ,
|
||||
new_arg[2] ,
|
||||
new_arg[3] ,
|
||||
new_arg[4]
|
||||
);
|
||||
// new operator
|
||||
old2new[i_op].new_op = addr_t( rec->num_op_rec() );
|
||||
// no new variable
|
||||
rec->PutOp(op);
|
||||
break;
|
||||
|
||||
// ---------------------------------------------------
|
||||
// VecAD operators
|
||||
|
||||
// Load using a parameter index
|
||||
case LdpOp:
|
||||
CPPAD_ASSERT_NARG_NRES(op, 3, 1);
|
||||
new_arg[0] = new_vecad_ind[ arg[0] ];
|
||||
new_arg[1] = arg[1];
|
||||
CPPAD_ASSERT_UNKNOWN(
|
||||
std::numeric_limits<addr_t>::max() >= rec->num_load_op_rec()
|
||||
);
|
||||
new_arg[2] = addr_t( rec->num_load_op_rec() );
|
||||
CPPAD_ASSERT_UNKNOWN( size_t(new_arg[0]) < num_vecad_ind );
|
||||
rec->PutArg(
|
||||
new_arg[0],
|
||||
new_arg[1],
|
||||
new_arg[2]
|
||||
);
|
||||
old2new[i_op].new_op = addr_t( rec->num_op_rec() );
|
||||
old2new[i_op].new_var = rec->PutLoadOp(op);
|
||||
break;
|
||||
|
||||
// Load using a variable index
|
||||
case LdvOp:
|
||||
CPPAD_ASSERT_NARG_NRES(op, 3, 1);
|
||||
new_arg[0] = new_vecad_ind[ arg[0] ];
|
||||
new_arg[1] = old2new[ var2op[arg[1]] ].new_var;
|
||||
CPPAD_ASSERT_UNKNOWN(
|
||||
std::numeric_limits<addr_t>::max() >= rec->num_load_op_rec()
|
||||
);
|
||||
new_arg[2] = addr_t( rec->num_load_op_rec() );
|
||||
CPPAD_ASSERT_UNKNOWN( size_t(new_arg[0]) < num_vecad_ind );
|
||||
CPPAD_ASSERT_UNKNOWN( size_t(new_arg[1]) < num_var );
|
||||
rec->PutArg(
|
||||
new_arg[0],
|
||||
new_arg[1],
|
||||
new_arg[2]
|
||||
);
|
||||
old2new[i_op].new_op = addr_t( rec->num_op_rec() );
|
||||
old2new[i_op].new_var = rec->PutLoadOp(op);
|
||||
break;
|
||||
|
||||
// Store a parameter using a parameter index
|
||||
case StppOp:
|
||||
CPPAD_ASSERT_NARG_NRES(op, 3, 0);
|
||||
new_arg[0] = new_vecad_ind[ arg[0] ];
|
||||
new_arg[1] = rec->PutPar( play->GetPar(arg[1]) );
|
||||
new_arg[2] = rec->PutPar( play->GetPar(arg[2]) );
|
||||
CPPAD_ASSERT_UNKNOWN( size_t(new_arg[0]) < num_vecad_ind );
|
||||
rec->PutArg(
|
||||
new_arg[0],
|
||||
new_arg[1],
|
||||
new_arg[2]
|
||||
);
|
||||
old2new[i_op].new_op = addr_t( rec->num_op_rec() );
|
||||
rec->PutOp(op);
|
||||
break;
|
||||
|
||||
// Store a parameter using a variable index
|
||||
case StvpOp:
|
||||
CPPAD_ASSERT_NARG_NRES(op, 3, 0);
|
||||
new_arg[0] = new_vecad_ind[ arg[0] ];
|
||||
new_arg[1] = old2new[ var2op[arg[1]] ].new_var;
|
||||
new_arg[2] = rec->PutPar( play->GetPar(arg[2]) );
|
||||
CPPAD_ASSERT_UNKNOWN( size_t(new_arg[0]) < num_vecad_ind );
|
||||
CPPAD_ASSERT_UNKNOWN( size_t(new_arg[1]) < num_var );
|
||||
rec->PutArg(
|
||||
new_arg[0],
|
||||
new_arg[1],
|
||||
new_arg[2]
|
||||
);
|
||||
old2new[i_op].new_op = addr_t( rec->num_op_rec() );
|
||||
rec->PutOp(op);
|
||||
break;
|
||||
|
||||
// Store a variable using a parameter index
|
||||
case StpvOp:
|
||||
CPPAD_ASSERT_NARG_NRES(op, 3, 0);
|
||||
new_arg[0] = new_vecad_ind[ arg[0] ];
|
||||
new_arg[1] = rec->PutPar( play->GetPar(arg[1]) );
|
||||
new_arg[2] = old2new[ var2op[arg[2]] ].new_var;
|
||||
CPPAD_ASSERT_UNKNOWN( size_t(new_arg[0]) < num_vecad_ind );
|
||||
CPPAD_ASSERT_UNKNOWN( size_t(new_arg[2]) < num_var );
|
||||
rec->PutArg(
|
||||
new_arg[0],
|
||||
new_arg[1],
|
||||
new_arg[2]
|
||||
);
|
||||
old2new[i_op].new_op = addr_t( rec->num_op_rec() );
|
||||
rec->PutOp(op);
|
||||
break;
|
||||
|
||||
// Store a variable using a variable index
|
||||
case StvvOp:
|
||||
CPPAD_ASSERT_NARG_NRES(op, 3, 0);
|
||||
new_arg[0] = new_vecad_ind[ arg[0] ];
|
||||
new_arg[1] = old2new[ var2op[arg[1]] ].new_var;
|
||||
new_arg[2] = old2new[ var2op[arg[2]] ].new_var;
|
||||
CPPAD_ASSERT_UNKNOWN( size_t(new_arg[0]) < num_vecad_ind );
|
||||
CPPAD_ASSERT_UNKNOWN( size_t(new_arg[1]) < num_var );
|
||||
CPPAD_ASSERT_UNKNOWN( size_t(new_arg[2]) < num_var );
|
||||
rec->PutArg(
|
||||
new_arg[0],
|
||||
new_arg[1],
|
||||
new_arg[2]
|
||||
);
|
||||
old2new[i_op].new_op = addr_t( rec->num_op_rec() );
|
||||
rec->PutOp(op);
|
||||
break;
|
||||
|
||||
// -----------------------------------------------------------
|
||||
// user atomic function call operators
|
||||
|
||||
case UserOp:
|
||||
CPPAD_ASSERT_NARG_NRES(op, 4, 0);
|
||||
// user_old, user_n, user_m
|
||||
rec->PutArg(arg[0], arg[1], arg[2], arg[3]);
|
||||
old2new[i_op].new_op = addr_t( rec->num_op_rec() );
|
||||
rec->PutOp(UserOp);
|
||||
break;
|
||||
|
||||
case UsrapOp:
|
||||
CPPAD_ASSERT_NARG_NRES(op, 1, 0);
|
||||
new_arg[0] = rec->PutPar( play->GetPar(arg[0]) );
|
||||
rec->PutArg(new_arg[0]);
|
||||
old2new[i_op].new_op = addr_t( rec->num_op_rec() );
|
||||
rec->PutOp(UsrapOp);
|
||||
break;
|
||||
|
||||
case UsravOp:
|
||||
CPPAD_ASSERT_NARG_NRES(op, 1, 0);
|
||||
new_arg[0] = old2new[ var2op[arg[0]] ].new_var;
|
||||
if( size_t(new_arg[0]) < num_var )
|
||||
{ rec->PutArg(new_arg[0]);
|
||||
old2new[i_op].new_op = addr_t( rec->num_op_rec() );
|
||||
rec->PutOp(UsravOp);
|
||||
}
|
||||
else
|
||||
{ // This argument does not affect the result and
|
||||
// has been optimized out so use nan in its place.
|
||||
new_arg[0] = rec->PutPar( base_nan );
|
||||
rec->PutArg(new_arg[0]);
|
||||
old2new[i_op].new_op = addr_t( rec->num_op_rec() );
|
||||
rec->PutOp(UsrapOp);
|
||||
}
|
||||
break;
|
||||
|
||||
case UsrrpOp:
|
||||
CPPAD_ASSERT_NARG_NRES(op, 1, 0);
|
||||
new_arg[0] = rec->PutPar( play->GetPar(arg[0]) );
|
||||
rec->PutArg(new_arg[0]);
|
||||
old2new[i_op].new_op = addr_t( rec->num_op_rec() );
|
||||
rec->PutOp(UsrrpOp);
|
||||
break;
|
||||
|
||||
case UsrrvOp:
|
||||
CPPAD_ASSERT_NARG_NRES(op, 0, 1);
|
||||
old2new[i_op].new_op = addr_t( rec->num_op_rec() );
|
||||
old2new[i_op].new_var = rec->PutOp(UsrrvOp);
|
||||
break;
|
||||
// ---------------------------------------------------
|
||||
|
||||
// all cases should be handled above
|
||||
default:
|
||||
CPPAD_ASSERT_UNKNOWN(false);
|
||||
|
||||
}
|
||||
}
|
||||
// modify the dependent variable vector to new indices
|
||||
for(size_t i = 0; i < dep_taddr.size(); i++ )
|
||||
{ dep_taddr[i] = old2new[ var2op[dep_taddr[i]] ].new_var;
|
||||
CPPAD_ASSERT_UNKNOWN( size_t(dep_taddr[i]) < num_var );
|
||||
}
|
||||
|
||||
# ifndef NDEBUG
|
||||
for(i_op = 0; i_op < num_op; i_op++)
|
||||
if( NumRes( op_info[i_op].op ) > 0 )
|
||||
CPPAD_ASSERT_UNKNOWN(
|
||||
size_t(old2new[i_op].new_op) < rec->num_op_rec()
|
||||
);
|
||||
# endif
|
||||
// make sure that all the conditional expressions have been
|
||||
// checked to see if they are still present
|
||||
CPPAD_ASSERT_UNKNOWN( cskip_order_next == num_cexp );
|
||||
// fill in the arguments for the CSkip operations
|
||||
for(size_t i = 0; i < num_cexp; i++)
|
||||
{ // if cskip_new[i].i_arg == 0, this conditional expression was skipped
|
||||
if( cskip_new[i].i_arg > 0 )
|
||||
{ struct_cexp_info info = cexp_info[i];
|
||||
size_t n_true = skip_op_true.number_elements(i);
|
||||
size_t n_false = skip_op_false.number_elements(i);
|
||||
size_t i_arg = cskip_new[i].i_arg;
|
||||
size_t left = cskip_new[i].left;
|
||||
size_t right = cskip_new[i].right;
|
||||
rec->ReplaceArg(i_arg++, info.cop );
|
||||
rec->ReplaceArg(i_arg++, info.flag );
|
||||
rec->ReplaceArg(i_arg++, left );
|
||||
rec->ReplaceArg(i_arg++, right );
|
||||
rec->ReplaceArg(i_arg++, n_true );
|
||||
rec->ReplaceArg(i_arg++, n_false );
|
||||
sparse_list::const_iterator itr_true(skip_op_true, i);
|
||||
while( *itr_true != skip_op_true.end() )
|
||||
{ i_op = *itr_true;
|
||||
// op_info[i_op].usage == yes_usage
|
||||
CPPAD_ASSERT_UNKNOWN( old2new[i_op].new_op != 0 );
|
||||
rec->ReplaceArg(i_arg++, old2new[i_op].new_op );
|
||||
//
|
||||
++itr_true;
|
||||
}
|
||||
sparse_list::const_iterator itr_false(skip_op_false, i);
|
||||
while( *itr_false != skip_op_false.end() )
|
||||
{ i_op = *itr_false;
|
||||
// op_info[i_op].usage == yes_usage
|
||||
CPPAD_ASSERT_UNKNOWN( old2new[i_op].new_op != 0 );
|
||||
rec->ReplaceArg(i_arg++, old2new[i_op].new_op );
|
||||
//
|
||||
++itr_false;
|
||||
}
|
||||
rec->ReplaceArg(i_arg++, n_true + n_false);
|
||||
# ifndef NDEBUG
|
||||
size_t n_arg = 7 + n_true + n_false;
|
||||
CPPAD_ASSERT_UNKNOWN( cskip_new[i].i_arg + n_arg == i_arg );
|
||||
# endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} } } // END_CPPAD_LOCAL_OPTIMIZE_NAMESPACE
|
||||
|
||||
# endif
|
||||
@@ -0,0 +1,259 @@
|
||||
# ifndef CPPAD_LOCAL_OPTIMIZE_RECORD_CSUM_HPP
|
||||
# define CPPAD_LOCAL_OPTIMIZE_RECORD_CSUM_HPP
|
||||
/* --------------------------------------------------------------------------
|
||||
CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-17 Bradley M. Bell
|
||||
|
||||
CppAD is distributed under multiple licenses. This distribution is under
|
||||
the terms of the
|
||||
Eclipse Public License Version 1.0.
|
||||
|
||||
A copy of this license is included in the COPYING file of this distribution.
|
||||
Please visit http://www.coin-or.org/CppAD/ for information on other licenses.
|
||||
-------------------------------------------------------------------------- */
|
||||
/*!
|
||||
\file record_csum.hpp
|
||||
Recording a cummulative cummulative summation.
|
||||
*/
|
||||
# include <cppad/local/optimize/old2new.hpp>
|
||||
|
||||
// BEGIN_CPPAD_LOCAL_OPTIMIZE_NAMESPACE
|
||||
namespace CppAD { namespace local { namespace optimize {
|
||||
/*!
|
||||
Recording a cummulative cummulative summation.
|
||||
|
||||
\param var2op
|
||||
mapping from old variable index to old operator index.
|
||||
|
||||
\param op_info
|
||||
mapping from old index to operator index to operator information
|
||||
|
||||
\param old2new
|
||||
mapping from old operator index to information about the new recording.
|
||||
|
||||
\param current
|
||||
is the index in the old operation sequence for
|
||||
the variable corresponding to the result for the current operator.
|
||||
We use the notation i_op = var2op[current].
|
||||
It follows that NumRes( op_info[i_op].op ) > 0.
|
||||
If 0 < j_op < i_op, either op_info[j_op].usage == csum_usage,
|
||||
op_info[j_op].usage = no_usage, or old2new[j_op].new_var != 0.
|
||||
|
||||
\param npar
|
||||
is the number of parameters corresponding to the old operation sequence.
|
||||
|
||||
\param par
|
||||
is a vector of length npar containing the parameters
|
||||
the old operation sequence; i.e.,
|
||||
given a parameter index i < npar, the corresponding parameter value is par[i].
|
||||
|
||||
\param rec
|
||||
is the object that will record the new operations.
|
||||
|
||||
\return
|
||||
is the operator and variable indices in the new operation sequence.
|
||||
|
||||
\param work
|
||||
Is temporary work space. On input and output,
|
||||
work.op_stack, work.add_stack, and work.sub_stack, are all empty.
|
||||
These stacks are passed in so that they are created once
|
||||
and then be reused with calls to record_csum.
|
||||
|
||||
\par Assumptions
|
||||
op_info[i_o].op
|
||||
must be one of AddpvOp, AddvvOp, SubpvOp, SubvpOp, SubvvOp.
|
||||
op_info[i_op].usage != no_usage and ! op_info[i_op].usage == csum_usage.
|
||||
Furthermore op_info[j_op].usage == csum_usage is true from some
|
||||
j_op that corresponds to a variable that is an argument to
|
||||
op_info[i_op].
|
||||
*/
|
||||
|
||||
template <class Base>
|
||||
struct_size_pair record_csum(
|
||||
const vector<addr_t>& var2op ,
|
||||
const vector<struct_op_info>& op_info ,
|
||||
const CppAD::vector<struct struct_old2new>& old2new ,
|
||||
size_t current ,
|
||||
size_t npar ,
|
||||
const Base* par ,
|
||||
recorder<Base>* rec ,
|
||||
// local information passed so stacks need not be allocated for every call
|
||||
struct_csum_stacks& work )
|
||||
{
|
||||
// check assumption about work space
|
||||
CPPAD_ASSERT_UNKNOWN( work.op_stack.empty() );
|
||||
CPPAD_ASSERT_UNKNOWN( work.add_stack.empty() );
|
||||
CPPAD_ASSERT_UNKNOWN( work.sub_stack.empty() );
|
||||
//
|
||||
size_t i_op = var2op[current];
|
||||
CPPAD_ASSERT_UNKNOWN( ! ( op_info[i_op].usage == csum_usage ) );
|
||||
//
|
||||
size_t i;
|
||||
OpCode op;
|
||||
const addr_t* arg;
|
||||
bool add;
|
||||
struct struct_csum_variable var;
|
||||
//
|
||||
// information corresponding to the root node in the cummulative summation
|
||||
var.op = op_info[i_op].op; // this operator
|
||||
var.arg = op_info[i_op].arg; // arguments for this operator
|
||||
var.add = true; // was parrent operator positive or negative
|
||||
//
|
||||
// initialize stack as containing this one operator
|
||||
work.op_stack.push( var );
|
||||
//
|
||||
// initialize sum of parameter values as zero
|
||||
Base sum_par(0);
|
||||
//
|
||||
# ifndef NDEBUG
|
||||
bool ok = false;
|
||||
struct_op_info info = op_info[i_op];
|
||||
if( var.op == SubvpOp )
|
||||
ok = op_info[ var2op[info.arg[0]] ].usage == csum_usage;
|
||||
if( var.op == AddpvOp || var.op == SubpvOp )
|
||||
ok = op_info[ var2op[info.arg[1]] ].usage == csum_usage;
|
||||
if( var.op == AddvvOp || var.op == SubvvOp )
|
||||
{ ok = op_info[ var2op[info.arg[0]] ].usage == csum_usage;
|
||||
ok |= op_info[ var2op[info.arg[1]] ].usage == csum_usage;
|
||||
}
|
||||
CPPAD_ASSERT_UNKNOWN( ok );
|
||||
# endif
|
||||
//
|
||||
// while there are operators left on the stack
|
||||
while( ! work.op_stack.empty() )
|
||||
{ // get this summation operator
|
||||
var = work.op_stack.top();
|
||||
work.op_stack.pop();
|
||||
op = var.op;
|
||||
arg = var.arg;
|
||||
add = var.add;
|
||||
//
|
||||
// process first argument to this operator
|
||||
switch(op)
|
||||
{ // cases where first argument is a parameter
|
||||
case AddpvOp:
|
||||
case SubpvOp:
|
||||
CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < npar );
|
||||
// first argument has same sign as parent node
|
||||
if( add )
|
||||
sum_par += par[arg[0]];
|
||||
else sum_par -= par[arg[0]];
|
||||
break;
|
||||
|
||||
// cases where first argument is a variable
|
||||
case AddvvOp:
|
||||
case SubvpOp:
|
||||
case SubvvOp:
|
||||
//
|
||||
// check if the first argument has csum usage
|
||||
if( op_info[var2op[arg[0]]].usage == csum_usage )
|
||||
{ CPPAD_ASSERT_UNKNOWN(
|
||||
size_t( old2new[ var2op[arg[0]] ].new_var) == 0
|
||||
);
|
||||
// push the operator corresponding to the first argument
|
||||
var.op = op_info[ var2op[arg[0]] ].op;
|
||||
var.arg = op_info[ var2op[arg[0]] ].arg;
|
||||
// first argument has same sign as parent node
|
||||
var.add = add;
|
||||
work.op_stack.push( var );
|
||||
}
|
||||
else
|
||||
{ // there are no nodes below this one
|
||||
CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < current );
|
||||
if( add )
|
||||
work.add_stack.push(arg[0]);
|
||||
else work.sub_stack.push(arg[0]);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
CPPAD_ASSERT_UNKNOWN(false);
|
||||
}
|
||||
// process second argument to this operator
|
||||
switch(op)
|
||||
{ // cases where second argument is a parameter
|
||||
case SubvpOp:
|
||||
CPPAD_ASSERT_UNKNOWN( size_t(arg[1]) < npar );
|
||||
// second argument has opposite sign of parent node
|
||||
if( add )
|
||||
sum_par -= par[arg[1]];
|
||||
else sum_par += par[arg[1]];
|
||||
break;
|
||||
|
||||
// cases where second argument is a variable and has opposite sign
|
||||
case SubvvOp:
|
||||
case SubpvOp:
|
||||
add = ! add;
|
||||
|
||||
// cases where second argument is a variable and has same sign
|
||||
case AddvvOp:
|
||||
case AddpvOp:
|
||||
// check if the second argument has csum usage
|
||||
if( op_info[var2op[arg[1]]].usage == csum_usage )
|
||||
{ CPPAD_ASSERT_UNKNOWN(
|
||||
size_t( old2new[ var2op[arg[1]] ].new_var) == 0
|
||||
);
|
||||
// push the operator corresoponding to the second arugment
|
||||
var.op = op_info[ var2op[arg[1]] ].op;
|
||||
var.arg = op_info[ var2op[arg[1]] ].arg;
|
||||
var.add = add;
|
||||
work.op_stack.push( var );
|
||||
}
|
||||
else
|
||||
{ // there are no nodes below this one
|
||||
CPPAD_ASSERT_UNKNOWN( size_t(arg[1]) < current );
|
||||
if( add )
|
||||
work.add_stack.push(arg[1]);
|
||||
else work.sub_stack.push(arg[1]);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
CPPAD_ASSERT_UNKNOWN(false);
|
||||
}
|
||||
}
|
||||
// number of variables to add in this cummulative sum operator
|
||||
size_t n_add = work.add_stack.size();
|
||||
// number of variables to subtract in this cummulative sum operator
|
||||
size_t n_sub = work.sub_stack.size();
|
||||
//
|
||||
CPPAD_ASSERT_UNKNOWN(
|
||||
std::numeric_limits<addr_t>::max() >= n_add + n_sub
|
||||
);
|
||||
//
|
||||
rec->PutArg( addr_t(n_add) ); // arg[0]
|
||||
rec->PutArg( addr_t(n_sub) ); // arg[1]
|
||||
addr_t new_arg = rec->PutPar(sum_par);
|
||||
rec->PutArg(new_arg); // arg[2]
|
||||
// addition arguments
|
||||
for(i = 0; i < n_add; i++)
|
||||
{ CPPAD_ASSERT_UNKNOWN( ! work.add_stack.empty() );
|
||||
size_t old_arg = work.add_stack.top();
|
||||
new_arg = old2new[ var2op[old_arg] ].new_var;
|
||||
CPPAD_ASSERT_UNKNOWN( 0 < new_arg && size_t(new_arg) < current );
|
||||
rec->PutArg(new_arg); // arg[3+i]
|
||||
work.add_stack.pop();
|
||||
}
|
||||
// subtraction arguments
|
||||
for(i = 0; i < n_sub; i++)
|
||||
{ CPPAD_ASSERT_UNKNOWN( ! work.sub_stack.empty() );
|
||||
size_t old_arg = work.sub_stack.top();
|
||||
new_arg = old2new[ var2op[old_arg] ].new_var;
|
||||
CPPAD_ASSERT_UNKNOWN( 0 < new_arg && size_t(new_arg) < current );
|
||||
rec->PutArg(new_arg); // arg[3 + arg[0] + i]
|
||||
work.sub_stack.pop();
|
||||
}
|
||||
// number of additions plus number of subtractions
|
||||
rec->PutArg( addr_t(n_add + n_sub) ); // arg[3 + arg[0] + arg[1]]
|
||||
//
|
||||
// return value
|
||||
struct_size_pair ret;
|
||||
ret.i_op = rec->num_op_rec();
|
||||
ret.i_var = rec->PutOp(CSumOp);
|
||||
//
|
||||
return ret;
|
||||
}
|
||||
|
||||
} } } // END_CPPAD_LOCAL_OPTIMIZE_NAMESPACE
|
||||
|
||||
|
||||
# endif
|
||||
@@ -0,0 +1,105 @@
|
||||
// $Id$
|
||||
# ifndef CPPAD_LOCAL_OPTIMIZE_RECORD_PV_HPP
|
||||
# define CPPAD_LOCAL_OPTIMIZE_RECORD_PV_HPP
|
||||
/* --------------------------------------------------------------------------
|
||||
CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-16 Bradley M. Bell
|
||||
|
||||
CppAD is distributed under multiple licenses. This distribution is under
|
||||
the terms of the
|
||||
Eclipse Public License Version 1.0.
|
||||
|
||||
A copy of this license is included in the COPYING file of this distribution.
|
||||
Please visit http://www.coin-or.org/CppAD/ for information on other licenses.
|
||||
-------------------------------------------------------------------------- */
|
||||
/*!
|
||||
\file record_pv.hpp
|
||||
Record an operation of the form (parameter op variable).
|
||||
*/
|
||||
// BEGIN_CPPAD_LOCAL_OPTIMIZE_NAMESPACE
|
||||
namespace CppAD { namespace local { namespace optimize {
|
||||
|
||||
/*!
|
||||
Record an operation of the form (parameter op variable).
|
||||
|
||||
\param var2op
|
||||
mapping from old variable index to old operator index.
|
||||
|
||||
\param op_info
|
||||
mapping from old index to operator index to operator information
|
||||
|
||||
\param old2new
|
||||
mapping from old operator index to information about the new recording.
|
||||
|
||||
\param current
|
||||
is the index in the old operation sequence for
|
||||
the variable corresponding to the result for the current operator.
|
||||
We use the notation i_op = var2op[current].
|
||||
It follows that NumRes( op_info[i_op].op ) > 0.
|
||||
If 0 < j_op < i_op, either op_info[j_op].csum_connected,
|
||||
op_info[j_op].usage = 0, or old2new[j_op].new_var != 0.
|
||||
|
||||
\param npar
|
||||
is the number of parameters corresponding to the old operation sequence.
|
||||
|
||||
\param par
|
||||
is a vector of length npar containing the parameters
|
||||
the old operation sequence; i.e.,
|
||||
given a parameter index i < npar, the corresponding parameter value is par[i].
|
||||
|
||||
\param rec
|
||||
is the object that will record the new operations.
|
||||
|
||||
\return
|
||||
is the operator and variable indices in the new operation sequence.
|
||||
|
||||
\param op
|
||||
is the operator that we are recording which must be one of the following:
|
||||
AddpvOp, DivpvOp, MulpvOp, PowpvOp, SubpvOp, ZmulpvOp.
|
||||
|
||||
\param arg
|
||||
is the vector of arguments for this operator.
|
||||
*/
|
||||
template <class Base>
|
||||
struct_size_pair record_pv(
|
||||
const vector<addr_t>& var2op ,
|
||||
const vector<struct_op_info>& op_info ,
|
||||
const CppAD::vector<struct struct_old2new>& old2new ,
|
||||
size_t current ,
|
||||
size_t npar ,
|
||||
const Base* par ,
|
||||
recorder<Base>* rec ,
|
||||
OpCode op ,
|
||||
const addr_t* arg )
|
||||
{
|
||||
# ifndef NDEBUG
|
||||
switch(op)
|
||||
{ case AddpvOp:
|
||||
case DivpvOp:
|
||||
case MulpvOp:
|
||||
case PowpvOp:
|
||||
case SubpvOp:
|
||||
case ZmulpvOp:
|
||||
break;
|
||||
|
||||
default:
|
||||
CPPAD_ASSERT_UNKNOWN(false);
|
||||
}
|
||||
# endif
|
||||
CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < npar );
|
||||
CPPAD_ASSERT_UNKNOWN( size_t(arg[1]) < current );
|
||||
addr_t new_arg[2];
|
||||
new_arg[0] = rec->PutPar( par[arg[0]] );
|
||||
new_arg[1] = old2new[ var2op[arg[1]] ].new_var;
|
||||
rec->PutArg( new_arg[0], new_arg[1] );
|
||||
|
||||
struct_size_pair ret;
|
||||
ret.i_op = rec->num_op_rec();
|
||||
ret.i_var = rec->PutOp(op);
|
||||
CPPAD_ASSERT_UNKNOWN( 0 < new_arg[1] && size_t(new_arg[1]) < ret.i_var );
|
||||
return ret;
|
||||
}
|
||||
|
||||
} } } // END_CPPAD_LOCAL_OPTIMIZE_NAMESPACE
|
||||
|
||||
|
||||
# endif
|
||||
@@ -0,0 +1,104 @@
|
||||
// $Id$
|
||||
# ifndef CPPAD_LOCAL_OPTIMIZE_RECORD_VP_HPP
|
||||
# define CPPAD_LOCAL_OPTIMIZE_RECORD_VP_HPP
|
||||
/* --------------------------------------------------------------------------
|
||||
CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-16 Bradley M. Bell
|
||||
|
||||
CppAD is distributed under multiple licenses. This distribution is under
|
||||
the terms of the
|
||||
Eclipse Public License Version 1.0.
|
||||
|
||||
A copy of this license is included in the COPYING file of this distribution.
|
||||
Please visit http://www.coin-or.org/CppAD/ for information on other licenses.
|
||||
-------------------------------------------------------------------------- */
|
||||
/*!
|
||||
\file record_vp.hpp
|
||||
Record an operation of the form (variable op parameter).
|
||||
*/
|
||||
// BEGIN_CPPAD_LOCAL_OPTIMIZE_NAMESPACE
|
||||
namespace CppAD { namespace local { namespace optimize {
|
||||
|
||||
|
||||
/*!
|
||||
Record an operation of the form (variable op parameter).
|
||||
|
||||
\param var2op
|
||||
mapping from old variable index to old operator index.
|
||||
|
||||
\param op_info
|
||||
mapping from old index to operator index to operator information
|
||||
|
||||
\param old2new
|
||||
mapping from old operator index to information about the new recording.
|
||||
|
||||
\param current
|
||||
is the index in the old operation sequence for
|
||||
the variable corresponding to the result for the current operator.
|
||||
We use the notation i_op = var2op[current].
|
||||
It follows that NumRes( op_info[i_op].op ) > 0.
|
||||
If 0 < j_op < i_op, either op_info[j_op].csum_connected,
|
||||
op_info[j_op].usage = 0, or old2new[j_op].new_var != 0.
|
||||
|
||||
\param npar
|
||||
is the number of parameters corresponding to the old operation sequence.
|
||||
|
||||
\param par
|
||||
is a vector of length npar containing the parameters
|
||||
the old operation sequence; i.e.,
|
||||
given a parameter index i < npar, the corresponding parameter value is par[i].
|
||||
|
||||
\param rec
|
||||
is the object that will record the new operations.
|
||||
|
||||
\return
|
||||
is the operator and variable indices in the new operation sequence.
|
||||
|
||||
\param op
|
||||
is the operator that we are recording which must be one of the following:
|
||||
DivvpOp, PowvpOp, SubvpOp, ZmulvpOp.
|
||||
|
||||
\param arg
|
||||
is the vector of arguments for this operator.
|
||||
*/
|
||||
template <class Base>
|
||||
struct_size_pair record_vp(
|
||||
const vector<addr_t>& var2op ,
|
||||
const vector<struct_op_info>& op_info ,
|
||||
const CppAD::vector<struct struct_old2new>& old2new ,
|
||||
size_t current ,
|
||||
size_t npar ,
|
||||
const Base* par ,
|
||||
recorder<Base>* rec ,
|
||||
OpCode op ,
|
||||
const addr_t* arg )
|
||||
{
|
||||
# ifndef NDEBUG
|
||||
switch(op)
|
||||
{ case DivvpOp:
|
||||
case PowvpOp:
|
||||
case SubvpOp:
|
||||
case ZmulvpOp:
|
||||
break;
|
||||
|
||||
default:
|
||||
CPPAD_ASSERT_UNKNOWN(false);
|
||||
}
|
||||
# endif
|
||||
CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < current );
|
||||
CPPAD_ASSERT_UNKNOWN( size_t(arg[1]) < npar );
|
||||
addr_t new_arg[2];
|
||||
new_arg[0] = old2new[ var2op[arg[0]] ].new_var;
|
||||
new_arg[1] = rec->PutPar( par[arg[1]] );
|
||||
rec->PutArg( new_arg[0], new_arg[1] );
|
||||
|
||||
struct_size_pair ret;
|
||||
ret.i_op = rec->num_op_rec();
|
||||
ret.i_var = rec->PutOp(op);
|
||||
CPPAD_ASSERT_UNKNOWN( 0 < new_arg[0] && size_t(new_arg[0]) < ret.i_var );
|
||||
return ret;
|
||||
}
|
||||
|
||||
} } } // END_CPPAD_LOCAL_OPTIMIZE_NAMESPACE
|
||||
|
||||
|
||||
# endif
|
||||
@@ -0,0 +1,105 @@
|
||||
// $Id$
|
||||
# ifndef CPPAD_LOCAL_OPTIMIZE_RECORD_VV_HPP
|
||||
# define CPPAD_LOCAL_OPTIMIZE_RECORD_VV_HPP
|
||||
/* --------------------------------------------------------------------------
|
||||
CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-16 Bradley M. Bell
|
||||
|
||||
CppAD is distributed under multiple licenses. This distribution is under
|
||||
the terms of the
|
||||
Eclipse Public License Version 1.0.
|
||||
|
||||
A copy of this license is included in the COPYING file of this distribution.
|
||||
Please visit http://www.coin-or.org/CppAD/ for information on other licenses.
|
||||
-------------------------------------------------------------------------- */
|
||||
/*!
|
||||
\file record_vv.hpp
|
||||
Record an operation of the form (variable op variable).
|
||||
*/
|
||||
// BEGIN_CPPAD_LOCAL_OPTIMIZE_NAMESPACE
|
||||
namespace CppAD { namespace local { namespace optimize {
|
||||
/*!
|
||||
Record an operation of the form (variable op variable).
|
||||
|
||||
\param var2op
|
||||
mapping from old variable index to old operator index.
|
||||
|
||||
\param op_info
|
||||
mapping from old index to operator index to operator information
|
||||
|
||||
\param old2new
|
||||
mapping from old operator index to information about the new recording.
|
||||
|
||||
\param current
|
||||
is the index in the old operation sequence for
|
||||
the variable corresponding to the result for the current operator.
|
||||
We use the notation i_op = var2op[current].
|
||||
It follows that NumRes( op_info[i_op].op ) > 0.
|
||||
If 0 < j_op < i_op, either op_info[j_op].csum_connected,
|
||||
op_info[j_op].usage = 0, or old2new[j_op].new_var != 0.
|
||||
|
||||
\param npar
|
||||
is the number of parameters corresponding to the old operation sequence.
|
||||
|
||||
\param par
|
||||
is a vector of length npar containing the parameters
|
||||
the old operation sequence; i.e.,
|
||||
given a parameter index i < npar, the corresponding parameter value is par[i].
|
||||
|
||||
\param rec
|
||||
is the object that will record the new operations.
|
||||
|
||||
\return
|
||||
is the operator and variable indices in the new operation sequence.
|
||||
|
||||
\param op
|
||||
is the operator that we are recording which must be one of the following:
|
||||
AddvvOp, DivvvOp, MulvvOp, PowvvOp, SubvvOp, ZmulvvOp.
|
||||
|
||||
\param arg
|
||||
is the vector of arguments for this operator.
|
||||
*/
|
||||
template <class Base>
|
||||
struct_size_pair record_vv(
|
||||
const vector<addr_t>& var2op ,
|
||||
const vector<struct_op_info>& op_info ,
|
||||
const CppAD::vector<struct struct_old2new>& old2new ,
|
||||
size_t current ,
|
||||
size_t npar ,
|
||||
const Base* par ,
|
||||
recorder<Base>* rec ,
|
||||
OpCode op ,
|
||||
const addr_t* arg )
|
||||
{
|
||||
# ifndef NDEBUG
|
||||
switch(op)
|
||||
{ case AddvvOp:
|
||||
case DivvvOp:
|
||||
case MulvvOp:
|
||||
case PowvvOp:
|
||||
case SubvvOp:
|
||||
case ZmulvvOp:
|
||||
break;
|
||||
|
||||
default:
|
||||
CPPAD_ASSERT_UNKNOWN(false);
|
||||
}
|
||||
# endif
|
||||
CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < current );
|
||||
CPPAD_ASSERT_UNKNOWN( size_t(arg[1]) < current );
|
||||
addr_t new_arg[2];
|
||||
new_arg[0] = old2new[ var2op[arg[0]] ].new_var;
|
||||
new_arg[1] = old2new[ var2op[arg[1]] ].new_var;
|
||||
rec->PutArg( new_arg[0], new_arg[1] );
|
||||
|
||||
struct_size_pair ret;
|
||||
ret.i_op = rec->num_op_rec();
|
||||
ret.i_var = rec->PutOp(op);
|
||||
CPPAD_ASSERT_UNKNOWN( 0 < new_arg[0] && size_t(new_arg[0]) < ret.i_var );
|
||||
CPPAD_ASSERT_UNKNOWN( 0 < new_arg[1] && size_t(new_arg[1]) < ret.i_var );
|
||||
return ret;
|
||||
}
|
||||
|
||||
} } } // END_CPPAD_LOCAL_OPTIMIZE_NAMESPACE
|
||||
|
||||
|
||||
# endif
|
||||
@@ -0,0 +1,32 @@
|
||||
// $Id$
|
||||
# ifndef CPPAD_LOCAL_OPTIMIZE_SIZE_PAIR_HPP
|
||||
# define CPPAD_LOCAL_OPTIMIZE_SIZE_PAIR_HPP
|
||||
/* --------------------------------------------------------------------------
|
||||
CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-16 Bradley M. Bell
|
||||
|
||||
CppAD is distributed under multiple licenses. This distribution is under
|
||||
the terms of the
|
||||
Eclipse Public License Version 1.0.
|
||||
|
||||
A copy of this license is included in the COPYING file of this distribution.
|
||||
Please visit http://www.coin-or.org/CppAD/ for information on other licenses.
|
||||
-------------------------------------------------------------------------- */
|
||||
/*!
|
||||
\file size_pair.hpp
|
||||
Information for one variable and one operation sequence.
|
||||
*/
|
||||
// BEGIN_CPPAD_LOCAL_OPTIMIZE_NAMESPACE
|
||||
namespace CppAD { namespace local { namespace optimize {
|
||||
|
||||
/*!
|
||||
\file size_pair.hpp
|
||||
Information for one variable in one operation sequence.
|
||||
*/
|
||||
struct struct_size_pair {
|
||||
size_t i_op; /// operator index for this variable
|
||||
size_t i_var; /// variable index for this variable
|
||||
};
|
||||
|
||||
} } } // END_CPPAD_LOCAL_OPTIMIZE_NAMESPACE
|
||||
|
||||
# endif
|
||||
@@ -0,0 +1,35 @@
|
||||
// $Id$
|
||||
# ifndef CPPAD_LOCAL_OPTIMIZE_USAGE_HPP
|
||||
# define CPPAD_LOCAL_OPTIMIZE_USAGE_HPP
|
||||
/* --------------------------------------------------------------------------
|
||||
CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-16 Bradley M. Bell
|
||||
|
||||
CppAD is distributed under multiple licenses. This distribution is under
|
||||
the terms of the
|
||||
Eclipse Public License Version 1.0.
|
||||
|
||||
A copy of this license is included in the COPYING file of this distribution.
|
||||
Please visit http://www.coin-or.org/CppAD/ for information on other licenses.
|
||||
-------------------------------------------------------------------------- */
|
||||
|
||||
// BEGIN_CPPAD_LOCAL_OPTIMIZE_NAMESPACE
|
||||
namespace CppAD { namespace local { namespace optimize {
|
||||
|
||||
enum enum_usage {
|
||||
/// This operator is not used.
|
||||
no_usage,
|
||||
|
||||
/// This operator is used one or more times.
|
||||
yes_usage,
|
||||
|
||||
/*!
|
||||
This operator is only used once, it is a summation operator,
|
||||
and its parrent is a summation operator. Furthermore, its result is not
|
||||
a dependent variable. Hence case it can be removed as part of a
|
||||
cumulative summation starting at its parent or above.
|
||||
*/
|
||||
csum_usage
|
||||
};
|
||||
|
||||
} } } // END_CPPAD_LOCAL_OPTIMIZE_NAMESPACE
|
||||
# endif
|
||||
@@ -0,0 +1,90 @@
|
||||
// $Id: parameter_op.hpp 3845 2016-11-19 01:50:47Z bradbell $
|
||||
# ifndef CPPAD_LOCAL_PARAMETER_OP_HPP
|
||||
# define CPPAD_LOCAL_PARAMETER_OP_HPP
|
||||
|
||||
/* --------------------------------------------------------------------------
|
||||
CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-16 Bradley M. Bell
|
||||
|
||||
CppAD is distributed under multiple licenses. This distribution is under
|
||||
the terms of the
|
||||
Eclipse Public License Version 1.0.
|
||||
|
||||
A copy of this license is included in the COPYING file of this distribution.
|
||||
Please visit http://www.coin-or.org/CppAD/ for information on other licenses.
|
||||
-------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
namespace CppAD { namespace local { // BEGIN_CPPAD_LOCAL_NAMESPACE
|
||||
/*!
|
||||
\file parameter_op.hpp
|
||||
Zero order forward mode for ParOp
|
||||
*/
|
||||
|
||||
|
||||
/*!
|
||||
Compute zero order forward mode Taylor coefficient for result of op = ParOp.
|
||||
|
||||
The C++ source code corresponding to this operation is one of the following
|
||||
\verbatim
|
||||
ADFun<Base> f(x, y)
|
||||
f.Dependent(x, y)
|
||||
\endverbatim
|
||||
where some of the components of the vector y are parameters.
|
||||
|
||||
\tparam Base
|
||||
base type for the operator; i.e., this operation was recorded
|
||||
using AD< \a Base > and computations by this routine are done using type
|
||||
\a Base .
|
||||
|
||||
\param i_z
|
||||
variable index corresponding to the result for this operation;
|
||||
i.e. the row index in \a taylor corresponding to the component of y
|
||||
that is a parameter.
|
||||
|
||||
\param arg
|
||||
\a arg[0]
|
||||
\n
|
||||
index corresponding to the parameter value for this operator.
|
||||
|
||||
\param num_par
|
||||
is the number of parameters in \a parameter.
|
||||
|
||||
\param parameter
|
||||
\b Input: \a parameter[ \a arg[0] ] is the value of a component
|
||||
of y that is a parameter.
|
||||
|
||||
\param cap_order
|
||||
number of colums in the matrix containing all the Taylor coefficients.
|
||||
|
||||
\param taylor
|
||||
\b Output: \a taylor [ \a i_z * \a cap_order + 0 ]
|
||||
is the zero order Taylor coefficient corresponding to z.
|
||||
|
||||
\par Checked Assertions where op is the unary operator with one result:
|
||||
\li NumArg(op) == 1
|
||||
\li NumRes(op) == 1
|
||||
\li \a size_t(arg[0]) < num_par
|
||||
\li \a 0 < \a cap_order
|
||||
*/
|
||||
template <class Base>
|
||||
inline void forward_par_op_0(
|
||||
size_t i_z ,
|
||||
const addr_t* arg ,
|
||||
size_t num_par ,
|
||||
const Base* parameter ,
|
||||
size_t cap_order ,
|
||||
Base* taylor )
|
||||
{
|
||||
// check assumptions
|
||||
CPPAD_ASSERT_UNKNOWN( NumArg(ParOp) == 1 );
|
||||
CPPAD_ASSERT_UNKNOWN( NumRes(ParOp) == 1 );
|
||||
CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < num_par );
|
||||
CPPAD_ASSERT_UNKNOWN( 0 < cap_order );
|
||||
|
||||
Base* z = taylor + i_z * cap_order;
|
||||
|
||||
z[0] = parameter[ arg[0] ];
|
||||
}
|
||||
|
||||
} } // END_CPPAD_LOCAL_NAMESPACE
|
||||
# endif
|
||||
+1027
File diff suppressed because it is too large
Load Diff
+293
@@ -0,0 +1,293 @@
|
||||
// $Id: pod_vector.hpp 3845 2016-11-19 01:50:47Z bradbell $
|
||||
# ifndef CPPAD_LOCAL_POD_VECTOR_HPP
|
||||
# define CPPAD_LOCAL_POD_VECTOR_HPP
|
||||
|
||||
/* --------------------------------------------------------------------------
|
||||
CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-16 Bradley M. Bell
|
||||
|
||||
CppAD is distributed under multiple licenses. This distribution is under
|
||||
the terms of the
|
||||
Eclipse Public License Version 1.0.
|
||||
|
||||
A copy of this license is included in the COPYING file of this distribution.
|
||||
Please visit http://www.coin-or.org/CppAD/ for information on other licenses.
|
||||
-------------------------------------------------------------------------- */
|
||||
|
||||
# if CPPAD_CSTDINT_HAS_8_TO_64
|
||||
# include <cstdint>
|
||||
# endif
|
||||
# include <algorithm>
|
||||
# include <cppad/utility/thread_alloc.hpp>
|
||||
# include <cppad/core/cppad_assert.hpp>
|
||||
# include <cppad/local/op_code.hpp>
|
||||
|
||||
namespace CppAD { namespace local { // BEGIN_CPPAD_LOCAL_NAMESPACE
|
||||
/*!
|
||||
\file pod_vector.hpp
|
||||
File used to define pod_vector class
|
||||
*/
|
||||
|
||||
/*
|
||||
A list of which Types pod_vector<Type> consideres to be plain old data
|
||||
*/
|
||||
/// default value is false
|
||||
template <class Type> inline bool is_pod(void) { return false; }
|
||||
/// system pod types so far:
|
||||
template <> inline bool is_pod<bool>(void) { return true; }
|
||||
template <> inline bool is_pod<float>(void) { return true; }
|
||||
template <> inline bool is_pod<double>(void) { return true; }
|
||||
# if CPPAD_CSTDINT_HAS_8_TO_64
|
||||
template <> inline bool is_pod<int8_t>(void) { return true; }
|
||||
template <> inline bool is_pod<int16_t>(void) { return true; }
|
||||
template <> inline bool is_pod<int32_t>(void) { return true; }
|
||||
template <> inline bool is_pod<int64_t>(void) { return true; }
|
||||
//
|
||||
template <> inline bool is_pod<uint8_t>(void) { return true; }
|
||||
template <> inline bool is_pod<uint16_t>(void) { return true; }
|
||||
template <> inline bool is_pod<uint32_t>(void) { return true; }
|
||||
template <> inline bool is_pod<uint64_t>(void) { return true; }
|
||||
# else // CPPAD_CSTDINT_HAS_8_TO_64
|
||||
template <> inline bool is_pod<char>(void) { return true; }
|
||||
template <> inline bool is_pod<short int>(void) { return true; }
|
||||
template <> inline bool is_pod<int>(void) { return true; }
|
||||
//
|
||||
template <> inline bool is_pod<unsigned char>(void) { return true; }
|
||||
template <> inline bool is_pod<unsigned short int>(void) { return true; }
|
||||
template <> inline bool is_pod<unsigned int>(void) { return true; }
|
||||
# if CPPAD_SIZE_T_NOT_UNSIGNED_INT
|
||||
template <> inline bool is_pod<size_t>(void) { return true; }
|
||||
# endif
|
||||
# endif // CPPAD_CSTDINT_HAS_8_TO_64
|
||||
|
||||
/// CppAD pod types so far:
|
||||
template <> inline bool is_pod<OpCode>(void) { return true; }
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
/*!
|
||||
A vector class with Type element that does not use element constructors
|
||||
or destructors when Type is Plain Old Data (pod).
|
||||
*/
|
||||
template <class Type>
|
||||
class pod_vector {
|
||||
private:
|
||||
/// maximum number of elements that should ever be in this vector
|
||||
size_t max_length_;
|
||||
/// number of elements currently in this vector
|
||||
size_t length_;
|
||||
/// maximum number of Type elements current allocation can hold
|
||||
size_t capacity_;
|
||||
/// pointer to the first type elements
|
||||
/// (not defined and should not be used when capacity_ = 0)
|
||||
Type *data_;
|
||||
/// do not use the copy constructor
|
||||
explicit pod_vector(const pod_vector& )
|
||||
{ CPPAD_ASSERT_UNKNOWN(false); }
|
||||
public:
|
||||
/// Constructors set capacity, length, and data to zero.
|
||||
///
|
||||
/// \param max_length
|
||||
/// value for maximum number of elements in this vector.
|
||||
inline pod_vector(
|
||||
size_t max_length = std::numeric_limits<size_t>::max()
|
||||
)
|
||||
: max_length_(max_length), length_(0), capacity_(0), data_(CPPAD_NULL)
|
||||
{ }
|
||||
// ----------------------------------------------------------------------
|
||||
/// Destructor: returns allocated memory to \c thread_alloc;
|
||||
/// see \c extend. If this is not plain old data,
|
||||
/// the destructor for each element is called.
|
||||
~pod_vector(void)
|
||||
{ if( capacity_ > 0 )
|
||||
{ void* v_ptr = reinterpret_cast<void*>( data_ );
|
||||
if( ! is_pod<Type>() )
|
||||
{ // call destructor for each element
|
||||
size_t i;
|
||||
for(i = 0; i < capacity_; i++)
|
||||
(data_ + i)->~Type();
|
||||
}
|
||||
thread_alloc::return_memory(v_ptr);
|
||||
}
|
||||
}
|
||||
// ----------------------------------------------------------------------
|
||||
/// current number of elements in this vector.
|
||||
inline size_t size(void) const
|
||||
{ return length_; }
|
||||
/// current capacity (amount of allocated storage) for this vector.
|
||||
inline size_t capacity(void) const
|
||||
{ return capacity_; }
|
||||
/// current data pointer, no longer valid after any of the following:
|
||||
/// extend, erase, operator=, and ~pod_vector.
|
||||
/// Take extreem care when using this function.
|
||||
inline Type* data(void)
|
||||
{ return data_; }
|
||||
/// const version of \c data pointer
|
||||
inline const Type* data(void) const
|
||||
{ return data_; }
|
||||
// ----------------------------------------------------------------------
|
||||
/*!
|
||||
Increase the number of elements the end of this vector.
|
||||
|
||||
\param n
|
||||
is the number of elements to add to end of this vector.
|
||||
|
||||
\return
|
||||
is the number of elements in the vector before \c extend was extended.
|
||||
|
||||
- If \c Type is plain old data, new elements are not initialized;
|
||||
i.e., their constructor is not called. Otherwise, the constructor
|
||||
is called for each new element.
|
||||
|
||||
- This is the only routine that allocates memory for \c pod_vector.
|
||||
and it uses thread_alloc for this allocation, hence this determines
|
||||
which thread corresponds to this vector (when in parallel mode).
|
||||
|
||||
- If the resulting length of the vector would be more than \c max_length_,
|
||||
and \c NDEBUG is not defined, a CPPAD_ASSERT is generated.
|
||||
*/
|
||||
inline size_t extend(size_t n)
|
||||
{ size_t old_length = length_;
|
||||
length_ += n;
|
||||
CPPAD_ASSERT_KNOWN(
|
||||
length_ <= max_length_ ,
|
||||
"pod_vector.hpp: attempt to create to large a vector.\n"
|
||||
"If Type is CPPAD_TYPE_ADDR_TYPE, tape is too long for Type."
|
||||
);
|
||||
// check if we can use current memory
|
||||
if( capacity_ >= length_ )
|
||||
return old_length;
|
||||
|
||||
// save more old information
|
||||
size_t old_capacity = capacity_;
|
||||
Type* old_data = data_;
|
||||
|
||||
// get new memory and set capacity
|
||||
size_t length_bytes = length_ * sizeof(Type);
|
||||
size_t capacity_bytes;
|
||||
void* v_ptr = thread_alloc::get_memory(length_bytes, capacity_bytes);
|
||||
capacity_ = capacity_bytes / sizeof(Type);
|
||||
data_ = reinterpret_cast<Type*>(v_ptr);
|
||||
CPPAD_ASSERT_UNKNOWN( length_ <= capacity_ );
|
||||
|
||||
size_t i;
|
||||
if( ! is_pod<Type>() )
|
||||
{ // call constructor for each new element
|
||||
for(i = 0; i < capacity_; i++)
|
||||
new(data_ + i) Type();
|
||||
}
|
||||
|
||||
// copy old data to new data
|
||||
for(i = 0; i < old_length; i++)
|
||||
data_[i] = old_data[i];
|
||||
|
||||
// return old memory to available pool
|
||||
if( old_capacity > 0 )
|
||||
{ v_ptr = reinterpret_cast<void*>( old_data );
|
||||
if( ! is_pod<Type>() )
|
||||
{ for(i = 0; i < old_capacity; i++)
|
||||
(old_data + i)->~Type();
|
||||
}
|
||||
thread_alloc::return_memory(v_ptr);
|
||||
}
|
||||
|
||||
// return value for extend(n) is the old length
|
||||
return old_length;
|
||||
}
|
||||
// ----------------------------------------------------------------------
|
||||
/// non-constant element access; i.e., we can change this element value
|
||||
Type& operator[](
|
||||
/// element index, must be less than length
|
||||
size_t i
|
||||
)
|
||||
{ CPPAD_ASSERT_UNKNOWN( i < length_ );
|
||||
return data_[i];
|
||||
}
|
||||
// ----------------------------------------------------------------------
|
||||
/// constant element access; i.e., we cannot change this element value
|
||||
const Type& operator[](
|
||||
/// element index, must be less than length
|
||||
size_t i
|
||||
) const
|
||||
{ CPPAD_ASSERT_UNKNOWN( i < length_ );
|
||||
return data_[i];
|
||||
}
|
||||
// ----------------------------------------------------------------------
|
||||
/*!
|
||||
Remove all the elements from this vector but leave the capacity
|
||||
and data pointer as is.
|
||||
|
||||
*/
|
||||
void erase(void)
|
||||
{ length_ = 0;
|
||||
return;
|
||||
}
|
||||
// ----------------------------------------------------------------------
|
||||
/*!
|
||||
Remove all the elements from this vector and delete its memory.
|
||||
*/
|
||||
void free(void)
|
||||
{ if( capacity_ > 0 )
|
||||
{ void* v_ptr = reinterpret_cast<void*>( data_ );
|
||||
if( ! is_pod<Type>() )
|
||||
{ // call destructor for each element
|
||||
size_t i;
|
||||
for(i = 0; i < capacity_; i++)
|
||||
(data_ + i)->~Type();
|
||||
}
|
||||
thread_alloc::return_memory(v_ptr);
|
||||
}
|
||||
data_ = CPPAD_NULL;
|
||||
capacity_ = 0;
|
||||
length_ = 0;
|
||||
}
|
||||
/// vector assignment operator
|
||||
/// If the resulting length of the vector would be more than
|
||||
/// \c max_length_, and \c NDEBUG is not defined,
|
||||
/// a CPPAD_ASSERT is generated.
|
||||
void operator=(
|
||||
/// right hand size of the assingment operation
|
||||
const pod_vector& x
|
||||
)
|
||||
{ size_t i;
|
||||
|
||||
if( x.length_ <= capacity_ )
|
||||
{ // use existing allocation for this vector
|
||||
length_ = x.length_;
|
||||
CPPAD_ASSERT_KNOWN(
|
||||
length_ <= max_length_ ,
|
||||
"pod_vector.hpp: attempt to create to large a vector.\n"
|
||||
"If Type is CPPAD_TYPE_ADDR_TYPE, tape long for Type."
|
||||
);
|
||||
}
|
||||
else
|
||||
{ // free old memory and get new memory of sufficient length
|
||||
if( capacity_ > 0 )
|
||||
{ void* v_ptr = reinterpret_cast<void*>( data_ );
|
||||
if( ! is_pod<Type>() )
|
||||
{ // call destructor for each element
|
||||
for(i = 0; i < capacity_; i++)
|
||||
(data_ + i)->~Type();
|
||||
}
|
||||
thread_alloc::return_memory(v_ptr);
|
||||
}
|
||||
length_ = capacity_ = 0;
|
||||
extend( x.length_ );
|
||||
}
|
||||
CPPAD_ASSERT_UNKNOWN( length_ == x.length_ );
|
||||
for(i = 0; i < length_; i++)
|
||||
{ data_[i] = x.data_[i]; }
|
||||
}
|
||||
/*!
|
||||
Swap all properties of this vector with another.
|
||||
|
||||
\param other
|
||||
is the other vector that we are swapping this vector with.
|
||||
*/
|
||||
void swap(pod_vector& other)
|
||||
{ std::swap(capacity_, other.capacity_);
|
||||
std::swap(length_, other.length_);
|
||||
std::swap(data_, other.data_);
|
||||
}
|
||||
};
|
||||
|
||||
} } // END_CPPAD_LOCAL_NAMESPACE
|
||||
# endif
|
||||
+659
@@ -0,0 +1,659 @@
|
||||
# ifndef CPPAD_LOCAL_POW_OP_HPP
|
||||
# define CPPAD_LOCAL_POW_OP_HPP
|
||||
|
||||
/* --------------------------------------------------------------------------
|
||||
CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-17 Bradley M. Bell
|
||||
|
||||
CppAD is distributed under multiple licenses. This distribution is under
|
||||
the terms of the
|
||||
Eclipse Public License Version 1.0.
|
||||
|
||||
A copy of this license is included in the COPYING file of this distribution.
|
||||
Please visit http://www.coin-or.org/CppAD/ for information on other licenses.
|
||||
-------------------------------------------------------------------------- */
|
||||
|
||||
namespace CppAD { namespace local { // BEGIN_CPPAD_LOCAL_NAMESPACE
|
||||
/*!
|
||||
\file pow_op.hpp
|
||||
Forward and reverse mode calculations for z = pow(x, y).
|
||||
*/
|
||||
|
||||
// --------------------------- Powvv -----------------------------------------
|
||||
/*!
|
||||
Compute forward mode Taylor coefficients for result of op = PowvvOp.
|
||||
|
||||
In the documentation below,
|
||||
this operations is for the case where both x and y are variables
|
||||
and the argument \a parameter is not used.
|
||||
|
||||
\copydetails CppAD::local::forward_pow_op
|
||||
*/
|
||||
|
||||
template <class Base>
|
||||
inline void forward_powvv_op(
|
||||
size_t p ,
|
||||
size_t q ,
|
||||
size_t i_z ,
|
||||
const addr_t* arg ,
|
||||
const Base* parameter ,
|
||||
size_t cap_order ,
|
||||
Base* taylor )
|
||||
{
|
||||
// convert from final result to first result
|
||||
i_z -= 2; // 2 = NumRes(PowvvOp) - 1;
|
||||
|
||||
// check assumptions
|
||||
CPPAD_ASSERT_UNKNOWN( NumArg(PowvvOp) == 2 );
|
||||
CPPAD_ASSERT_UNKNOWN( NumRes(PowvvOp) == 3 );
|
||||
CPPAD_ASSERT_UNKNOWN( q < cap_order );
|
||||
CPPAD_ASSERT_UNKNOWN( p <= q );
|
||||
CPPAD_ASSERT_UNKNOWN( std::numeric_limits<addr_t>::max() >= i_z );
|
||||
|
||||
// z_0 = log(x)
|
||||
forward_log_op(p, q, i_z, arg[0], cap_order, taylor);
|
||||
|
||||
// z_1 = z_0 * y
|
||||
addr_t adr[2];
|
||||
adr[0] = addr_t( i_z );
|
||||
adr[1] = arg[1];
|
||||
forward_mulvv_op(p, q, i_z+1, adr, parameter, cap_order, taylor);
|
||||
|
||||
// z_2 = exp(z_1)
|
||||
// final result for zero order case is exactly the same as for Base
|
||||
if( p == 0 )
|
||||
{ // Taylor coefficients corresponding to arguments and result
|
||||
Base* x = taylor + arg[0] * cap_order;
|
||||
Base* y = taylor + arg[1] * cap_order;
|
||||
Base* z_2 = taylor + (i_z+2) * cap_order;
|
||||
|
||||
z_2[0] = pow(x[0], y[0]);
|
||||
p++;
|
||||
}
|
||||
if( p <= q )
|
||||
forward_exp_op(p, q, i_z+2, i_z+1, cap_order, taylor);
|
||||
}
|
||||
/*!
|
||||
Multiple directions forward mode Taylor coefficients for op = PowvvOp.
|
||||
|
||||
The C++ source code corresponding to this operation is
|
||||
\verbatim
|
||||
z = pow(x, y)
|
||||
\endverbatim
|
||||
In the documentation below,
|
||||
this operations is for the case where x is a variable and y is a parameter.
|
||||
|
||||
\copydetails CppAD::local::forward_pow_op_dir
|
||||
*/
|
||||
|
||||
template <class Base>
|
||||
inline void forward_powvv_op_dir(
|
||||
size_t q ,
|
||||
size_t r ,
|
||||
size_t i_z ,
|
||||
const addr_t* arg ,
|
||||
const Base* parameter ,
|
||||
size_t cap_order ,
|
||||
Base* taylor )
|
||||
{
|
||||
// convert from final result to first result
|
||||
i_z -= 2; // 2 = NumRes(PowvvOp) - 1
|
||||
|
||||
// check assumptions
|
||||
CPPAD_ASSERT_UNKNOWN( NumArg(PowvvOp) == 2 );
|
||||
CPPAD_ASSERT_UNKNOWN( NumRes(PowvvOp) == 3 );
|
||||
CPPAD_ASSERT_UNKNOWN( 0 < q );
|
||||
CPPAD_ASSERT_UNKNOWN( q < cap_order );
|
||||
CPPAD_ASSERT_UNKNOWN( std::numeric_limits<addr_t>::max() >= i_z );
|
||||
|
||||
// z_0 = log(x)
|
||||
forward_log_op_dir(q, r, i_z, arg[0], cap_order, taylor);
|
||||
|
||||
// z_1 = y * z_0
|
||||
addr_t adr[2];
|
||||
adr[0] = addr_t( i_z );
|
||||
adr[1] = arg[1];
|
||||
forward_mulvv_op_dir(q, r, i_z+1, adr, parameter, cap_order, taylor);
|
||||
|
||||
// z_2 = exp(z_1)
|
||||
forward_exp_op_dir(q, r, i_z+2, i_z+1, cap_order, taylor);
|
||||
}
|
||||
/*!
|
||||
Compute zero order forward mode Taylor coefficients for result of op = PowvvOp.
|
||||
|
||||
The C++ source code corresponding to this operation is
|
||||
\verbatim
|
||||
z = pow(x, y)
|
||||
\endverbatim
|
||||
In the documentation below,
|
||||
this operations is for the case where both x and y are variables
|
||||
and the argument \a parameter is not used.
|
||||
|
||||
\copydetails CppAD::local::forward_pow_op_0
|
||||
*/
|
||||
|
||||
template <class Base>
|
||||
inline void forward_powvv_op_0(
|
||||
size_t i_z ,
|
||||
const addr_t* arg ,
|
||||
const Base* parameter ,
|
||||
size_t cap_order ,
|
||||
Base* taylor )
|
||||
{
|
||||
// convert from final result to first result
|
||||
i_z -= 2; // NumRes(PowvvOp) - 1;
|
||||
|
||||
// check assumptions
|
||||
CPPAD_ASSERT_UNKNOWN( NumArg(PowvvOp) == 2 );
|
||||
CPPAD_ASSERT_UNKNOWN( NumRes(PowvvOp) == 3 );
|
||||
|
||||
// Taylor coefficients corresponding to arguments and result
|
||||
Base* x = taylor + arg[0] * cap_order;
|
||||
Base* y = taylor + arg[1] * cap_order;
|
||||
Base* z_0 = taylor + i_z * cap_order;
|
||||
Base* z_1 = z_0 + cap_order;
|
||||
Base* z_2 = z_1 + cap_order;
|
||||
|
||||
z_0[0] = log( x[0] );
|
||||
z_1[0] = z_0[0] * y[0];
|
||||
z_2[0] = pow(x[0], y[0]);
|
||||
|
||||
}
|
||||
|
||||
/*!
|
||||
Compute reverse mode partial derivatives for result of op = PowvvOp.
|
||||
|
||||
The C++ source code corresponding to this operation is
|
||||
\verbatim
|
||||
z = pow(x, y)
|
||||
\endverbatim
|
||||
In the documentation below,
|
||||
this operations is for the case where both x and y are variables
|
||||
and the argument \a parameter is not used.
|
||||
|
||||
\copydetails CppAD::local::reverse_pow_op
|
||||
*/
|
||||
|
||||
template <class Base>
|
||||
inline void reverse_powvv_op(
|
||||
size_t d ,
|
||||
size_t i_z ,
|
||||
const addr_t* arg ,
|
||||
const Base* parameter ,
|
||||
size_t cap_order ,
|
||||
const Base* taylor ,
|
||||
size_t nc_partial ,
|
||||
Base* partial )
|
||||
{
|
||||
// convert from final result to first result
|
||||
i_z -= 2; // NumRes(PowvvOp) - 1;
|
||||
|
||||
// check assumptions
|
||||
CPPAD_ASSERT_UNKNOWN( NumArg(PowvvOp) == 2 );
|
||||
CPPAD_ASSERT_UNKNOWN( NumRes(PowvvOp) == 3 );
|
||||
CPPAD_ASSERT_UNKNOWN( d < cap_order );
|
||||
CPPAD_ASSERT_UNKNOWN( d < nc_partial );
|
||||
CPPAD_ASSERT_UNKNOWN( std::numeric_limits<addr_t>::max() >= i_z );
|
||||
|
||||
// z_2 = exp(z_1)
|
||||
reverse_exp_op(
|
||||
d, i_z+2, i_z+1, cap_order, taylor, nc_partial, partial
|
||||
);
|
||||
|
||||
// z_1 = z_0 * y
|
||||
addr_t adr[2];
|
||||
adr[0] = addr_t( i_z );
|
||||
adr[1] = arg[1];
|
||||
reverse_mulvv_op(
|
||||
d, i_z+1, adr, parameter, cap_order, taylor, nc_partial, partial
|
||||
);
|
||||
|
||||
// z_0 = log(x)
|
||||
reverse_log_op(
|
||||
d, i_z, arg[0], cap_order, taylor, nc_partial, partial
|
||||
);
|
||||
}
|
||||
|
||||
// --------------------------- Powpv -----------------------------------------
|
||||
/*!
|
||||
Compute forward mode Taylor coefficients for result of op = PowpvOp.
|
||||
|
||||
The C++ source code corresponding to this operation is
|
||||
\verbatim
|
||||
z = pow(x, y)
|
||||
\endverbatim
|
||||
In the documentation below,
|
||||
this operations is for the case where x is a parameter and y is a variable.
|
||||
|
||||
\copydetails CppAD::local::forward_pow_op
|
||||
*/
|
||||
|
||||
template <class Base>
|
||||
inline void forward_powpv_op(
|
||||
size_t p ,
|
||||
size_t q ,
|
||||
size_t i_z ,
|
||||
const addr_t* arg ,
|
||||
const Base* parameter ,
|
||||
size_t cap_order ,
|
||||
Base* taylor )
|
||||
{
|
||||
// convert from final result to first result
|
||||
i_z -= 2; // 2 = NumRes(PowpvOp) - 1;
|
||||
|
||||
// check assumptions
|
||||
CPPAD_ASSERT_UNKNOWN( NumArg(PowpvOp) == 2 );
|
||||
CPPAD_ASSERT_UNKNOWN( NumRes(PowpvOp) == 3 );
|
||||
CPPAD_ASSERT_UNKNOWN( q < cap_order );
|
||||
CPPAD_ASSERT_UNKNOWN( p <= q );
|
||||
|
||||
// Taylor coefficients corresponding to arguments and result
|
||||
Base* z_0 = taylor + i_z * cap_order;
|
||||
|
||||
// z_0 = log(x)
|
||||
Base x = parameter[ arg[0] ];
|
||||
size_t d;
|
||||
for(d = p; d <= q; d++)
|
||||
{ if( d == 0 )
|
||||
z_0[d] = log(x);
|
||||
else z_0[d] = Base(0.0);
|
||||
}
|
||||
|
||||
// 2DO: remove requirement that i_z * cap_order <= max addr_t value
|
||||
CPPAD_ASSERT_KNOWN(
|
||||
std::numeric_limits<addr_t>::max() >= i_z * cap_order,
|
||||
"cppad_tape_addr_type maximum value has been exceeded\n"
|
||||
"This is due to a kludge in the pow operation and should be fixed."
|
||||
);
|
||||
|
||||
// z_1 = z_0 * y
|
||||
addr_t adr[2];
|
||||
// offset of z_i in taylor (as if it were a parameter); i.e., log(x)
|
||||
adr[0] = addr_t( i_z * cap_order );
|
||||
// offset of y in taylor (as a variable)
|
||||
adr[1] = arg[1];
|
||||
|
||||
// Trick: use taylor both for the parameter vector and variable values
|
||||
forward_mulpv_op(p, q, i_z+1, adr, taylor, cap_order, taylor);
|
||||
|
||||
// z_2 = exp(z_1)
|
||||
// zero order case exactly same as Base type operation
|
||||
if( p == 0 )
|
||||
{ Base* y = taylor + arg[1] * cap_order;
|
||||
Base* z_2 = taylor + (i_z+2) * cap_order;
|
||||
z_2[0] = pow(x, y[0]);
|
||||
p++;
|
||||
}
|
||||
if( p <= q )
|
||||
forward_exp_op(p, q, i_z+2, i_z+1, cap_order, taylor);
|
||||
}
|
||||
/*!
|
||||
Multiple directions forward mode Taylor coefficients for op = PowpvOp.
|
||||
|
||||
The C++ source code corresponding to this operation is
|
||||
\verbatim
|
||||
z = pow(x, y)
|
||||
\endverbatim
|
||||
In the documentation below,
|
||||
this operations is for the case where x is a parameter and y is a variable.
|
||||
|
||||
\copydetails CppAD::local::forward_pow_op_dir
|
||||
*/
|
||||
|
||||
template <class Base>
|
||||
inline void forward_powpv_op_dir(
|
||||
size_t q ,
|
||||
size_t r ,
|
||||
size_t i_z ,
|
||||
const addr_t* arg ,
|
||||
const Base* parameter ,
|
||||
size_t cap_order ,
|
||||
Base* taylor )
|
||||
{
|
||||
// convert from final result to first result
|
||||
i_z -= 2; // 2 = NumRes(PowpvOp) - 1;
|
||||
|
||||
// check assumptions
|
||||
CPPAD_ASSERT_UNKNOWN( NumArg(PowpvOp) == 2 );
|
||||
CPPAD_ASSERT_UNKNOWN( NumRes(PowpvOp) == 3 );
|
||||
CPPAD_ASSERT_UNKNOWN( 0 < q );
|
||||
CPPAD_ASSERT_UNKNOWN( q < cap_order );
|
||||
|
||||
// Taylor coefficients corresponding to arguments and result
|
||||
size_t num_taylor_per_var = (cap_order-1) * r + 1;
|
||||
Base* z_0 = taylor + i_z * num_taylor_per_var;
|
||||
|
||||
// z_0 = log(x)
|
||||
size_t m = (q-1) * r + 1;
|
||||
for(size_t ell = 0; ell < r; ell++)
|
||||
z_0[m+ell] = Base(0.0);
|
||||
|
||||
// 2DO: remove requirement i_z * num_taylor_per_var <= max addr_t value
|
||||
CPPAD_ASSERT_KNOWN(
|
||||
std::numeric_limits<addr_t>::max() >= i_z * num_taylor_per_var,
|
||||
"cppad_tape_addr_type maximum value has been exceeded\n"
|
||||
"This is due to a kludge in the pow operation and should be fixed."
|
||||
);
|
||||
|
||||
// z_1 = z_0 * y
|
||||
addr_t adr[2];
|
||||
// offset of z_0 in taylor (as if it were a parameter); i.e., log(x)
|
||||
adr[0] = addr_t( i_z * num_taylor_per_var );
|
||||
// ofset of y in taylor (as a variable)
|
||||
adr[1] = arg[1];
|
||||
|
||||
// Trick: use taylor both for the parameter vector and variable values
|
||||
forward_mulpv_op_dir(q, r, i_z+1, adr, taylor, cap_order, taylor);
|
||||
|
||||
// z_2 = exp(z_1)
|
||||
forward_exp_op_dir(q, r, i_z+2, i_z+1, cap_order, taylor);
|
||||
}
|
||||
/*!
|
||||
Compute zero order forward mode Taylor coefficient for result of op = PowpvOp.
|
||||
|
||||
The C++ source code corresponding to this operation is
|
||||
\verbatim
|
||||
z = pow(x, y)
|
||||
\endverbatim
|
||||
In the documentation below,
|
||||
this operations is for the case where x is a parameter and y is a variable.
|
||||
|
||||
\copydetails CppAD::local::forward_pow_op_0
|
||||
*/
|
||||
|
||||
template <class Base>
|
||||
inline void forward_powpv_op_0(
|
||||
size_t i_z ,
|
||||
const addr_t* arg ,
|
||||
const Base* parameter ,
|
||||
size_t cap_order ,
|
||||
Base* taylor )
|
||||
{
|
||||
// convert from final result to first result
|
||||
i_z -= 2; // NumRes(PowpvOp) - 1;
|
||||
|
||||
// check assumptions
|
||||
CPPAD_ASSERT_UNKNOWN( NumArg(PowpvOp) == 2 );
|
||||
CPPAD_ASSERT_UNKNOWN( NumRes(PowpvOp) == 3 );
|
||||
|
||||
// Paraemter value
|
||||
Base x = parameter[ arg[0] ];
|
||||
|
||||
// Taylor coefficients corresponding to arguments and result
|
||||
Base* y = taylor + arg[1] * cap_order;
|
||||
Base* z_0 = taylor + i_z * cap_order;
|
||||
Base* z_1 = z_0 + cap_order;
|
||||
Base* z_2 = z_1 + cap_order;
|
||||
|
||||
// z_0 = log(x)
|
||||
z_0[0] = log(x);
|
||||
|
||||
// z_1 = z_0 * y
|
||||
z_1[0] = z_0[0] * y[0];
|
||||
|
||||
// z_2 = exp(z_1)
|
||||
// zero order case exactly same as Base type operation
|
||||
z_2[0] = pow(x, y[0]);
|
||||
}
|
||||
|
||||
/*!
|
||||
Compute reverse mode partial derivative for result of op = PowpvOp.
|
||||
|
||||
The C++ source code corresponding to this operation is
|
||||
\verbatim
|
||||
z = pow(x, y)
|
||||
\endverbatim
|
||||
In the documentation below,
|
||||
this operations is for the case where x is a parameter and y is a variable.
|
||||
|
||||
\copydetails CppAD::local::reverse_pow_op
|
||||
*/
|
||||
|
||||
template <class Base>
|
||||
inline void reverse_powpv_op(
|
||||
size_t d ,
|
||||
size_t i_z ,
|
||||
const addr_t* arg ,
|
||||
const Base* parameter ,
|
||||
size_t cap_order ,
|
||||
const Base* taylor ,
|
||||
size_t nc_partial ,
|
||||
Base* partial )
|
||||
{
|
||||
// convert from final result to first result
|
||||
i_z -= 2; // NumRes(PowpvOp) - 1;
|
||||
|
||||
// check assumptions
|
||||
CPPAD_ASSERT_UNKNOWN( NumArg(PowvvOp) == 2 );
|
||||
CPPAD_ASSERT_UNKNOWN( NumRes(PowvvOp) == 3 );
|
||||
CPPAD_ASSERT_UNKNOWN( d < cap_order );
|
||||
CPPAD_ASSERT_UNKNOWN( d < nc_partial );
|
||||
|
||||
// z_2 = exp(z_1)
|
||||
reverse_exp_op(
|
||||
d, i_z+2, i_z+1, cap_order, taylor, nc_partial, partial
|
||||
);
|
||||
|
||||
// 2DO: remove requirement that i_z * cap_order <= max addr_t value
|
||||
CPPAD_ASSERT_KNOWN(
|
||||
std::numeric_limits<addr_t>::max() >= i_z * cap_order,
|
||||
"cppad_tape_addr_type maximum value has been exceeded\n"
|
||||
"This is due to a kludge in the pow operation and should be fixed."
|
||||
);
|
||||
|
||||
// z_1 = z_0 * y
|
||||
addr_t adr[2];
|
||||
adr[0] = addr_t( i_z * cap_order ); // offset of z_0[0] in taylor
|
||||
adr[1] = arg[1]; // index of y in taylor and partial
|
||||
// use taylor both for parameter and variable values
|
||||
reverse_mulpv_op(
|
||||
d, i_z+1, adr, taylor, cap_order, taylor, nc_partial, partial
|
||||
);
|
||||
|
||||
// z_0 = log(x)
|
||||
// x is a parameter
|
||||
}
|
||||
|
||||
// --------------------------- Powvp -----------------------------------------
|
||||
/*!
|
||||
Compute forward mode Taylor coefficients for result of op = PowvpOp.
|
||||
|
||||
The C++ source code corresponding to this operation is
|
||||
\verbatim
|
||||
z = pow(x, y)
|
||||
\endverbatim
|
||||
In the documentation below,
|
||||
this operations is for the case where x is a variable and y is a parameter.
|
||||
|
||||
\copydetails CppAD::local::forward_pow_op
|
||||
*/
|
||||
|
||||
template <class Base>
|
||||
inline void forward_powvp_op(
|
||||
size_t p ,
|
||||
size_t q ,
|
||||
size_t i_z ,
|
||||
const addr_t* arg ,
|
||||
const Base* parameter ,
|
||||
size_t cap_order ,
|
||||
Base* taylor )
|
||||
{
|
||||
// convert from final result to first result
|
||||
i_z -= 2; // 2 = NumRes(PowvpOp) - 1
|
||||
|
||||
// check assumptions
|
||||
CPPAD_ASSERT_UNKNOWN( NumArg(PowvpOp) == 2 );
|
||||
CPPAD_ASSERT_UNKNOWN( NumRes(PowvpOp) == 3 );
|
||||
CPPAD_ASSERT_UNKNOWN( q < cap_order );
|
||||
CPPAD_ASSERT_UNKNOWN( p <= q );
|
||||
CPPAD_ASSERT_UNKNOWN( std::numeric_limits<addr_t>::max() >= i_z );
|
||||
|
||||
// z_0 = log(x)
|
||||
forward_log_op(p, q, i_z, arg[0], cap_order, taylor);
|
||||
|
||||
// z_1 = y * z_0
|
||||
addr_t adr[2];
|
||||
adr[0] = arg[1];
|
||||
adr[1] = addr_t( i_z );
|
||||
forward_mulpv_op(p, q, i_z+1, adr, parameter, cap_order, taylor);
|
||||
|
||||
// z_2 = exp(z_1)
|
||||
// zero order case exactly same as Base type operation
|
||||
if( p == 0 )
|
||||
{ Base* z_2 = taylor + (i_z+2) * cap_order;
|
||||
Base* x = taylor + arg[0] * cap_order;
|
||||
Base y = parameter[ arg[1] ];
|
||||
z_2[0] = pow(x[0], y);
|
||||
p++;
|
||||
}
|
||||
if( p <= q )
|
||||
forward_exp_op(p, q, i_z+2, i_z+1, cap_order, taylor);
|
||||
}
|
||||
/*!
|
||||
Multiple directions forward mode Taylor coefficients for op = PowvpOp.
|
||||
|
||||
The C++ source code corresponding to this operation is
|
||||
\verbatim
|
||||
z = pow(x, y)
|
||||
\endverbatim
|
||||
In the documentation below,
|
||||
this operations is for the case where x is a variable and y is a parameter.
|
||||
|
||||
\copydetails CppAD::local::forward_pow_op_dir
|
||||
*/
|
||||
|
||||
template <class Base>
|
||||
inline void forward_powvp_op_dir(
|
||||
size_t q ,
|
||||
size_t r ,
|
||||
size_t i_z ,
|
||||
const addr_t* arg ,
|
||||
const Base* parameter ,
|
||||
size_t cap_order ,
|
||||
Base* taylor )
|
||||
{
|
||||
// convert from final result to first result
|
||||
i_z -= 2; // 2 = NumRes(PowvpOp) - 1
|
||||
|
||||
// check assumptions
|
||||
CPPAD_ASSERT_UNKNOWN( NumArg(PowvpOp) == 2 );
|
||||
CPPAD_ASSERT_UNKNOWN( NumRes(PowvpOp) == 3 );
|
||||
CPPAD_ASSERT_UNKNOWN( 0 < q );
|
||||
CPPAD_ASSERT_UNKNOWN( q < cap_order );
|
||||
CPPAD_ASSERT_UNKNOWN( std::numeric_limits<addr_t>::max() >= i_z );
|
||||
|
||||
// z_0 = log(x)
|
||||
forward_log_op_dir(q, r, i_z, arg[0], cap_order, taylor);
|
||||
|
||||
// z_1 = y * z_0
|
||||
addr_t adr[2];
|
||||
adr[0] = arg[1];
|
||||
adr[1] = addr_t( i_z );
|
||||
forward_mulpv_op_dir(q, r, i_z+1, adr, parameter, cap_order, taylor);
|
||||
|
||||
// z_2 = exp(z_1)
|
||||
forward_exp_op_dir(q, r, i_z+2, i_z+1, cap_order, taylor);
|
||||
}
|
||||
|
||||
/*!
|
||||
Compute zero order forward mode Taylor coefficients for result of op = PowvpOp.
|
||||
|
||||
The C++ source code corresponding to this operation is
|
||||
\verbatim
|
||||
z = pow(x, y)
|
||||
\endverbatim
|
||||
In the documentation below,
|
||||
this operations is for the case where x is a variable and y is a parameter.
|
||||
|
||||
\copydetails CppAD::local::forward_pow_op_0
|
||||
*/
|
||||
|
||||
template <class Base>
|
||||
inline void forward_powvp_op_0(
|
||||
size_t i_z ,
|
||||
const addr_t* arg ,
|
||||
const Base* parameter ,
|
||||
size_t cap_order ,
|
||||
Base* taylor )
|
||||
{
|
||||
// convert from final result to first result
|
||||
i_z -= 2; // NumRes(PowvpOp) - 1;
|
||||
|
||||
// check assumptions
|
||||
CPPAD_ASSERT_UNKNOWN( NumArg(PowvpOp) == 2 );
|
||||
CPPAD_ASSERT_UNKNOWN( NumRes(PowvpOp) == 3 );
|
||||
|
||||
// Paraemter value
|
||||
Base y = parameter[ arg[1] ];
|
||||
|
||||
// Taylor coefficients corresponding to arguments and result
|
||||
Base* x = taylor + arg[0] * cap_order;
|
||||
Base* z_0 = taylor + i_z * cap_order;
|
||||
Base* z_1 = z_0 + cap_order;
|
||||
Base* z_2 = z_1 + cap_order;
|
||||
|
||||
// z_0 = log(x)
|
||||
z_0[0] = log(x[0]);
|
||||
|
||||
// z_1 = z_0 * y
|
||||
z_1[0] = z_0[0] * y;
|
||||
|
||||
// z_2 = exp(z_1)
|
||||
// zero order case exactly same as Base type operation
|
||||
z_2[0] = pow(x[0], y);
|
||||
}
|
||||
|
||||
/*!
|
||||
Compute reverse mode partial derivative for result of op = PowvpOp.
|
||||
|
||||
The C++ source code corresponding to this operation is
|
||||
\verbatim
|
||||
z = pow(x, y)
|
||||
\endverbatim
|
||||
In the documentation below,
|
||||
this operations is for the case where x is a variable and y is a parameter.
|
||||
|
||||
\copydetails CppAD::local::reverse_pow_op
|
||||
*/
|
||||
|
||||
template <class Base>
|
||||
inline void reverse_powvp_op(
|
||||
size_t d ,
|
||||
size_t i_z ,
|
||||
const addr_t* arg ,
|
||||
const Base* parameter ,
|
||||
size_t cap_order ,
|
||||
const Base* taylor ,
|
||||
size_t nc_partial ,
|
||||
Base* partial )
|
||||
{
|
||||
// convert from final result to first result
|
||||
i_z -= 2; // NumRes(PowvpOp) - 1;
|
||||
|
||||
// check assumptions
|
||||
CPPAD_ASSERT_UNKNOWN( NumArg(PowvpOp) == 2 );
|
||||
CPPAD_ASSERT_UNKNOWN( NumRes(PowvpOp) == 3 );
|
||||
CPPAD_ASSERT_UNKNOWN( d < cap_order );
|
||||
CPPAD_ASSERT_UNKNOWN( d < nc_partial );
|
||||
CPPAD_ASSERT_UNKNOWN( std::numeric_limits<addr_t>::max() >= i_z );
|
||||
|
||||
// z_2 = exp(z_1)
|
||||
reverse_exp_op(
|
||||
d, i_z+2, i_z+1, cap_order, taylor, nc_partial, partial
|
||||
);
|
||||
|
||||
// z_1 = y * z_0
|
||||
addr_t adr[2];
|
||||
adr[0] = arg[1];
|
||||
adr[1] = addr_t( i_z );
|
||||
reverse_mulpv_op(
|
||||
d, i_z+1, adr, parameter, cap_order, taylor, nc_partial, partial
|
||||
);
|
||||
|
||||
// z_0 = log(x)
|
||||
reverse_log_op(
|
||||
d, i_z, arg[0], cap_order, taylor, nc_partial, partial
|
||||
);
|
||||
}
|
||||
|
||||
} } // END_CPPAD_LOCAL_NAMESPACE
|
||||
# endif
|
||||
+148
@@ -0,0 +1,148 @@
|
||||
// $Id: print_op.hpp 3845 2016-11-19 01:50:47Z bradbell $
|
||||
# ifndef CPPAD_LOCAL_PRINT_OP_HPP
|
||||
# define CPPAD_LOCAL_PRINT_OP_HPP
|
||||
|
||||
/* --------------------------------------------------------------------------
|
||||
CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-16 Bradley M. Bell
|
||||
|
||||
CppAD is distributed under multiple licenses. This distribution is under
|
||||
the terms of the
|
||||
Eclipse Public License Version 1.0.
|
||||
|
||||
A copy of this license is included in the COPYING file of this distribution.
|
||||
Please visit http://www.coin-or.org/CppAD/ for information on other licenses.
|
||||
-------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
namespace CppAD { namespace local { // BEGIN_CPPAD_LOCAL_NAMESPACE
|
||||
/*!
|
||||
Print operation for parameters; i.e., op = PriOp.
|
||||
|
||||
The C++ source code corresponding to this operation is
|
||||
\verbatim
|
||||
f.Forward(0, x)
|
||||
PrintFor(before, var)
|
||||
PrintFor(pos, before, var, after)
|
||||
\endverbatim
|
||||
The PrintFor call puts the print operation on the tape
|
||||
and the print occurs during the zero order forward mode computation.
|
||||
|
||||
\tparam Base
|
||||
base type for the operator; i.e., this operation was recorded
|
||||
using AD< \a Base > and computations by this routine are done using type
|
||||
\a Base .
|
||||
|
||||
\param s_out
|
||||
the results are printed on this output stream.
|
||||
|
||||
\param arg
|
||||
\a arg[0] & 1
|
||||
\n
|
||||
If this is zero, \a pos is a parameter. Otherwise it is a variable.
|
||||
\n
|
||||
\a arg[0] & 2
|
||||
\n
|
||||
If this is zero, \a var is a parameter. Otherwise it is a variable.
|
||||
\n
|
||||
\n
|
||||
\a arg[1]
|
||||
\n
|
||||
If \a pos is a parameter, <code>parameter[arg[1]]</code> is its value.
|
||||
Othwise <code>taylor[ arg[1] * cap_order + 0 ]</code> is the zero
|
||||
order Taylor coefficient for \a pos.
|
||||
\n
|
||||
\n
|
||||
\a arg[2]
|
||||
\n
|
||||
index of the text to be printed before \a var
|
||||
if \a pos is not a positive value.
|
||||
\n
|
||||
\n
|
||||
\a arg[3]
|
||||
\n
|
||||
If \a var is a parameter, <code>parameter[arg[3]]</code> is its value.
|
||||
Othwise <code>taylor[ arg[3] * cap_order + 0 ]</code> is the zero
|
||||
order Taylor coefficient for \a var.
|
||||
\n
|
||||
\n
|
||||
\a arg[4]
|
||||
\n
|
||||
index of the text to be printed after \a var
|
||||
if \a pos is not a positive value.
|
||||
|
||||
\param num_text
|
||||
is the total number of text characters on the tape
|
||||
(only used for error checking).
|
||||
|
||||
\param text
|
||||
\b Input: <code>text[arg[1]]</code> is the first character of the text
|
||||
that will be printed. All the characters from there to (but not including)
|
||||
the first '\\0' are printed.
|
||||
|
||||
\param num_par
|
||||
is the total number of values in the \a parameter vector
|
||||
|
||||
\param parameter
|
||||
Contains the value of parameters.
|
||||
|
||||
\param cap_order
|
||||
number of colums in the matrix containing all the Taylor coefficients.
|
||||
|
||||
\param taylor
|
||||
Contains the value of variables.
|
||||
|
||||
\par Checked Assertions:
|
||||
\li NumArg(PriOp) == 5
|
||||
\li NumRes(PriOp) == 0
|
||||
\li text != CPPAD_NULL
|
||||
\li arg[1] < num_text
|
||||
\li if \a pos is a parameter, arg[1] < num_par
|
||||
\li if \a var is a parameter, arg[3] < num_par
|
||||
*/
|
||||
template <class Base>
|
||||
inline void forward_pri_0(
|
||||
std::ostream& s_out ,
|
||||
const addr_t* arg ,
|
||||
size_t num_text ,
|
||||
const char* text ,
|
||||
size_t num_par ,
|
||||
const Base* parameter ,
|
||||
size_t cap_order ,
|
||||
const Base* taylor )
|
||||
{ Base pos, var;
|
||||
const char* before;
|
||||
const char* after;
|
||||
CPPAD_ASSERT_NARG_NRES(PriOp, 5, 0);
|
||||
|
||||
// pos
|
||||
if( arg[0] & 1 )
|
||||
{ pos = taylor[ arg[1] * cap_order + 0 ];
|
||||
}
|
||||
else
|
||||
{ CPPAD_ASSERT_UNKNOWN( size_t(arg[1]) < num_par );
|
||||
pos = parameter[ arg[1] ];
|
||||
}
|
||||
|
||||
// before
|
||||
CPPAD_ASSERT_UNKNOWN( size_t(arg[2]) < num_text );
|
||||
before = text + arg[2];
|
||||
|
||||
// var
|
||||
if( arg[0] & 2 )
|
||||
{ var = taylor[ arg[3] * cap_order + 0 ];
|
||||
}
|
||||
else
|
||||
{ CPPAD_ASSERT_UNKNOWN( size_t(arg[3]) < num_par );
|
||||
var = parameter[ arg[3] ];
|
||||
}
|
||||
|
||||
// after
|
||||
CPPAD_ASSERT_UNKNOWN( size_t(arg[4]) < num_text );
|
||||
after = text + arg[4];
|
||||
|
||||
if( ! GreaterThanZero( pos ) )
|
||||
s_out << before << var << after;
|
||||
}
|
||||
|
||||
} } // END_CPPAD_LOCAL_NAMESPACE
|
||||
# endif
|
||||
+1459
File diff suppressed because it is too large
Load Diff
+618
@@ -0,0 +1,618 @@
|
||||
# ifndef CPPAD_LOCAL_RECORDER_HPP
|
||||
# define CPPAD_LOCAL_RECORDER_HPP
|
||||
/* --------------------------------------------------------------------------
|
||||
CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-17 Bradley M. Bell
|
||||
|
||||
CppAD is distributed under multiple licenses. This distribution is under
|
||||
the terms of the
|
||||
Eclipse Public License Version 1.0.
|
||||
|
||||
A copy of this license is included in the COPYING file of this distribution.
|
||||
Please visit http://www.coin-or.org/CppAD/ for information on other licenses.
|
||||
-------------------------------------------------------------------------- */
|
||||
# include <cppad/core/hash_code.hpp>
|
||||
# include <cppad/local/pod_vector.hpp>
|
||||
|
||||
namespace CppAD { namespace local { // BEGIN_CPPAD_LOCAL_NAMESPACE
|
||||
/*!
|
||||
\file recorder.hpp
|
||||
File used to define the recorder class.
|
||||
*/
|
||||
|
||||
/*!
|
||||
Class used to store an operation sequence while it is being recorded
|
||||
(the operation sequence is copied to the player class for playback).
|
||||
|
||||
\tparam Base
|
||||
This is an AD< \a Base > operation sequence recording; i.e.,
|
||||
it records operations of type AD< \a Base >.
|
||||
*/
|
||||
template <class Base>
|
||||
class recorder {
|
||||
friend class player<Base>;
|
||||
|
||||
private:
|
||||
/// operator index at which to abort recording with an error
|
||||
/// (do not abort when zero)
|
||||
size_t abort_op_index_;
|
||||
|
||||
/// offset for this thread in the static hash table
|
||||
const size_t thread_offset_;
|
||||
|
||||
/// Number of variables in the recording.
|
||||
size_t num_var_rec_;
|
||||
|
||||
/// Number vecad load operations (LdpOp or LdvOp) currently in recording.
|
||||
size_t num_load_op_rec_;
|
||||
|
||||
/// The operators in the recording.
|
||||
pod_vector<CPPAD_OP_CODE_TYPE> op_rec_;
|
||||
|
||||
/// The VecAD indices in the recording.
|
||||
pod_vector<addr_t> vecad_ind_rec_;
|
||||
|
||||
/// The argument indices in the recording
|
||||
pod_vector<addr_t> op_arg_rec_;
|
||||
|
||||
/// The parameters in the recording.
|
||||
/// Note that Base may not be plain old data, so use false in consructor.
|
||||
pod_vector<Base> par_rec_;
|
||||
|
||||
/// Character strings ('\\0' terminated) in the recording.
|
||||
pod_vector<char> text_rec_;
|
||||
// ---------------------- Public Functions -----------------------------------
|
||||
public:
|
||||
/// Default constructor
|
||||
recorder(void) :
|
||||
thread_offset_( thread_alloc::thread_num() * CPPAD_HASH_TABLE_SIZE ) ,
|
||||
num_var_rec_(0) ,
|
||||
num_load_op_rec_(0) ,
|
||||
op_rec_( std::numeric_limits<addr_t>::max() ) ,
|
||||
vecad_ind_rec_( std::numeric_limits<addr_t>::max() ) ,
|
||||
op_arg_rec_( std::numeric_limits<addr_t>::max() ) ,
|
||||
par_rec_( std::numeric_limits<addr_t>::max() ) ,
|
||||
text_rec_( std::numeric_limits<addr_t>::max() )
|
||||
{
|
||||
abort_op_index_ = 0;
|
||||
}
|
||||
|
||||
/// Set the abort index
|
||||
void set_abort_op_index(size_t abort_op_index)
|
||||
{ abort_op_index_ = abort_op_index; }
|
||||
|
||||
/// Get the abort index
|
||||
size_t get_abort_op_index(void)
|
||||
{ return abort_op_index_; }
|
||||
|
||||
/// Destructor
|
||||
~recorder(void)
|
||||
{ }
|
||||
|
||||
/*!
|
||||
Frees all information in recording.
|
||||
|
||||
Frees the operation sequence store in this recording
|
||||
(the operation sequence is empty after this operation).
|
||||
The buffers used to store the current recording are returned
|
||||
to the system (so as to conserve on memory).
|
||||
*/
|
||||
void free(void)
|
||||
{ num_var_rec_ = 0;
|
||||
num_load_op_rec_ = 0;
|
||||
op_rec_.free();
|
||||
vecad_ind_rec_.free();
|
||||
op_arg_rec_.free();
|
||||
par_rec_.free();
|
||||
text_rec_.free();
|
||||
}
|
||||
/// Put next operator in the operation sequence.
|
||||
inline addr_t PutOp(OpCode op);
|
||||
/// Put a vecad load operator in the operation sequence (special case)
|
||||
inline addr_t PutLoadOp(OpCode op);
|
||||
/// Add a value to the end of the current vector of VecAD indices.
|
||||
inline addr_t PutVecInd(size_t vec_ind);
|
||||
/// Find or add a parameter to the current vector of parameters.
|
||||
inline addr_t PutPar(const Base &par);
|
||||
/// Put one operation argument index in the recording
|
||||
inline void PutArg(addr_t arg0);
|
||||
/// Put two operation argument index in the recording
|
||||
inline void PutArg(addr_t arg0, addr_t arg1);
|
||||
/// Put three operation argument index in the recording
|
||||
inline void PutArg(addr_t arg0, addr_t arg1, addr_t arg2);
|
||||
/// Put four operation argument index in the recording
|
||||
inline void PutArg(addr_t arg0, addr_t arg1, addr_t arg2, addr_t arg3);
|
||||
/// Put five operation argument index in the recording
|
||||
inline void PutArg(addr_t arg0, addr_t arg1, addr_t arg2, addr_t arg3,
|
||||
addr_t arg4);
|
||||
/// Put six operation argument index in the recording
|
||||
inline void PutArg(addr_t arg0, addr_t arg1, addr_t arg2, addr_t arg3,
|
||||
addr_t arg4, addr_t arg5);
|
||||
|
||||
// Reserve space for a specified number of arguments
|
||||
inline size_t ReserveArg(size_t n_arg);
|
||||
|
||||
// Replace an argument value
|
||||
void ReplaceArg(size_t i_arg, size_t value);
|
||||
|
||||
/// Put a character string in the text for this recording.
|
||||
inline addr_t PutTxt(const char *text);
|
||||
|
||||
/// Number of variables currently stored in the recording.
|
||||
size_t num_var_rec(void) const
|
||||
{ return num_var_rec_; }
|
||||
|
||||
/// Number of LdpOp and LdvOp operations currently in the recording.
|
||||
size_t num_load_op_rec(void) const
|
||||
{ return num_load_op_rec_; }
|
||||
|
||||
/// Number of operators currently stored in the recording.
|
||||
size_t num_op_rec(void) const
|
||||
{ return op_rec_.size(); }
|
||||
|
||||
/// Approximate amount of memory used by the recording
|
||||
size_t Memory(void) const
|
||||
{ return op_rec_.capacity() * sizeof(CPPAD_OP_CODE_TYPE)
|
||||
+ vecad_ind_rec_.capacity() * sizeof(size_t)
|
||||
+ op_arg_rec_.capacity() * sizeof(addr_t)
|
||||
+ par_rec_.capacity() * sizeof(Base)
|
||||
+ text_rec_.capacity() * sizeof(char);
|
||||
}
|
||||
};
|
||||
|
||||
/*!
|
||||
Put next operator in the operation sequence.
|
||||
|
||||
This sets the op code for the next operation in this recording.
|
||||
This call must be followed by putting the corresponding
|
||||
\verbatim
|
||||
NumArg(op)
|
||||
\endverbatim
|
||||
argument indices in the recording.
|
||||
|
||||
\param op
|
||||
Is the op code corresponding to the the operation that is being
|
||||
recorded (which must not be LdpOp or LdvOp).
|
||||
|
||||
\return
|
||||
The return value is the index of the primary (last) variable
|
||||
corresponding to the result of this operation.
|
||||
The number of variables corresponding to the operation is given by
|
||||
\verbatim
|
||||
NumRes(op)
|
||||
\endverbatim
|
||||
With each call to PutOp or PutLoadOp,
|
||||
the return index increases by the number of variables corresponding
|
||||
to the call.
|
||||
This index starts at zero after the default constructor
|
||||
and after each call to Erase.
|
||||
*/
|
||||
template <class Base>
|
||||
inline addr_t recorder<Base>::PutOp(OpCode op)
|
||||
{ size_t i = op_rec_.extend(1);
|
||||
CPPAD_ASSERT_KNOWN(
|
||||
(abort_op_index_ == 0) || (abort_op_index_ != i),
|
||||
"Operator index equals abort_op_index in Independent"
|
||||
);
|
||||
op_rec_[i] = static_cast<CPPAD_OP_CODE_TYPE>(op);
|
||||
CPPAD_ASSERT_UNKNOWN( op_rec_.size() == i + 1 );
|
||||
CPPAD_ASSERT_UNKNOWN( (op != LdpOp) & (op != LdvOp) );
|
||||
|
||||
// first operator should be a BeginOp and NumRes( BeginOp ) > 0
|
||||
num_var_rec_ += NumRes(op);
|
||||
CPPAD_ASSERT_UNKNOWN( num_var_rec_ > 0 );
|
||||
|
||||
// index of last variable corresponding to this operation
|
||||
// (if NumRes(op) > 0)
|
||||
CPPAD_ASSERT_KNOWN(
|
||||
(size_t) std::numeric_limits<addr_t>::max() >= num_var_rec_ - 1,
|
||||
"cppad_tape_addr_type maximum value has been exceeded"
|
||||
)
|
||||
|
||||
return static_cast<addr_t>( num_var_rec_ - 1 );
|
||||
}
|
||||
|
||||
/*!
|
||||
Put next LdpOp or LdvOp operator in operation sequence (special cases).
|
||||
|
||||
This sets the op code for the next operation in this recording.
|
||||
This call must be followed by putting the corresponding
|
||||
\verbatim
|
||||
NumArg(op)
|
||||
\endverbatim
|
||||
argument indices in the recording.
|
||||
|
||||
\param op
|
||||
Is the op code corresponding to the the operation that is being
|
||||
recorded (which must be LdpOp or LdvOp).
|
||||
|
||||
\return
|
||||
The return value is the index of the primary (last) variable
|
||||
corresponding to the result of this operation.
|
||||
The number of variables corresponding to the operation is given by
|
||||
\verbatim
|
||||
NumRes(op)
|
||||
\endverbatim
|
||||
which must be one for this operation.
|
||||
With each call to PutLoadOp or PutOp,
|
||||
the return index increases by the number of variables corresponding
|
||||
to this call to the call.
|
||||
This index starts at zero after the default constructor
|
||||
and after each call to Erase.
|
||||
|
||||
\par num_load_op_rec()
|
||||
The return value for <code>num_load_op_rec()</code>
|
||||
increases by one after each call to this function
|
||||
(and starts at zero after the default constructor or Erase).
|
||||
*/
|
||||
template <class Base>
|
||||
inline addr_t recorder<Base>::PutLoadOp(OpCode op)
|
||||
{ size_t i = op_rec_.extend(1);
|
||||
CPPAD_ASSERT_KNOWN(
|
||||
(abort_op_index_ == 0) || (abort_op_index_ != i),
|
||||
"This is the abort operator index specified by "
|
||||
"Independent(x, abort_op_index)."
|
||||
);
|
||||
op_rec_[i] = static_cast<CPPAD_OP_CODE_TYPE>(op);
|
||||
CPPAD_ASSERT_UNKNOWN( op_rec_.size() == i + 1 );
|
||||
CPPAD_ASSERT_UNKNOWN( (op == LdpOp) | (op == LdvOp) );
|
||||
|
||||
// first operator should be a BeginOp and NumRes( BeginOp ) > 0
|
||||
num_var_rec_ += NumRes(op);
|
||||
CPPAD_ASSERT_UNKNOWN( num_var_rec_ > 0 );
|
||||
|
||||
// count this vecad load operation
|
||||
num_load_op_rec_++;
|
||||
|
||||
// index of last variable corresponding to this operation
|
||||
// (if NumRes(op) > 0)
|
||||
CPPAD_ASSERT_KNOWN(
|
||||
(size_t) std::numeric_limits<addr_t>::max() >= num_var_rec_ - 1,
|
||||
"cppad_tape_addr_type maximum value has been exceeded"
|
||||
)
|
||||
return static_cast<addr_t>( num_var_rec_ - 1 );
|
||||
}
|
||||
|
||||
/*!
|
||||
Add a value to the end of the current vector of VecAD indices.
|
||||
|
||||
For each VecAD vector, this routine is used to store the length
|
||||
of the vector followed by the parameter index corresponding to each
|
||||
value in the vector.
|
||||
This value for the elements of the VecAD vector corresponds to the
|
||||
beginning of the operation sequence.
|
||||
|
||||
\param vec_ind
|
||||
is the index to be palced at the end of the vector of VecAD indices.
|
||||
|
||||
\return
|
||||
is the index in the vector of VecAD indices corresponding to this value.
|
||||
This index starts at zero after the recorder default constructor
|
||||
and after each call to Erase.
|
||||
It increments by one for each call to PutVecInd..
|
||||
*/
|
||||
template <class Base>
|
||||
inline addr_t recorder<Base>::PutVecInd(size_t vec_ind)
|
||||
{ size_t i = vecad_ind_rec_.extend(1);
|
||||
CPPAD_ASSERT_UNKNOWN( std::numeric_limits<addr_t>::max() >= vec_ind );
|
||||
vecad_ind_rec_[i] = addr_t( vec_ind );
|
||||
CPPAD_ASSERT_UNKNOWN( vecad_ind_rec_.size() == i + 1 );
|
||||
|
||||
CPPAD_ASSERT_KNOWN(
|
||||
std::numeric_limits<addr_t>::max() >= i,
|
||||
"cppad_tape_addr_type maximum value has been exceeded"
|
||||
);
|
||||
return static_cast<addr_t>( i );
|
||||
}
|
||||
|
||||
/*!
|
||||
Find or add a parameter to the current vector of parameters.
|
||||
|
||||
\param par
|
||||
is the parameter to be found or placed in the vector of parameters.
|
||||
|
||||
\return
|
||||
is the index in the parameter vector corresponding to this parameter value.
|
||||
This value is not necessarily placed at the end of the vector
|
||||
(because values that are identically equal may be reused).
|
||||
*/
|
||||
template <class Base>
|
||||
addr_t recorder<Base>::PutPar(const Base &par)
|
||||
{ static size_t hash_table[CPPAD_HASH_TABLE_SIZE * CPPAD_MAX_NUM_THREADS];
|
||||
size_t i;
|
||||
size_t code;
|
||||
|
||||
CPPAD_ASSERT_UNKNOWN(
|
||||
thread_offset_ / CPPAD_HASH_TABLE_SIZE
|
||||
==
|
||||
thread_alloc::thread_num()
|
||||
);
|
||||
|
||||
// get hash code for this value
|
||||
code = static_cast<size_t>( hash_code(par) );
|
||||
CPPAD_ASSERT_UNKNOWN( code < CPPAD_HASH_TABLE_SIZE );
|
||||
|
||||
// If we have a match, return the parameter index
|
||||
i = hash_table[code + thread_offset_];
|
||||
if( i < par_rec_.size() && IdenticalEqualPar(par_rec_[i], par) )
|
||||
{ CPPAD_ASSERT_KNOWN(
|
||||
static_cast<size_t>( std::numeric_limits<addr_t>::max() ) >= i,
|
||||
"cppad_tape_addr_type maximum value has been exceeded"
|
||||
)
|
||||
return static_cast<addr_t>( i );
|
||||
}
|
||||
|
||||
// place a new value in the table
|
||||
i = par_rec_.extend(1);
|
||||
par_rec_[i] = par;
|
||||
CPPAD_ASSERT_UNKNOWN( par_rec_.size() == i + 1 );
|
||||
|
||||
// make the hash code point to this new value
|
||||
hash_table[code + thread_offset_] = i;
|
||||
|
||||
// return the parameter index
|
||||
CPPAD_ASSERT_KNOWN(
|
||||
static_cast<size_t>( std::numeric_limits<addr_t>::max() ) >= i,
|
||||
"cppad_tape_addr_type maximum value has been exceeded"
|
||||
)
|
||||
return static_cast<addr_t>( i );
|
||||
}
|
||||
// -------------------------- PutArg --------------------------------------
|
||||
/*!
|
||||
Prototype for putting operation argument indices in the recording.
|
||||
|
||||
The following syntax
|
||||
\verbatim
|
||||
rec.PutArg(arg0)
|
||||
rec.PutArg(arg0, arg1)
|
||||
.
|
||||
.
|
||||
.
|
||||
rec.PutArg(arg0, arg1, ..., arg5)
|
||||
\endverbatim
|
||||
places the values passed to PutArg at the current end of the
|
||||
operation argument indices for the recording.
|
||||
\a arg0 comes before \a arg1, etc.
|
||||
The proper number of operation argument indices
|
||||
corresponding to the operation code op is given by
|
||||
\verbatim
|
||||
NumArg(op)
|
||||
\endverbatim
|
||||
The number of the operation argument indices starts at zero
|
||||
after the default constructor and each call to Erase.
|
||||
It increases by the number of indices placed by each call to PutArg.
|
||||
*/
|
||||
inline void prototype_put_arg(void)
|
||||
{ // This routine should not be called
|
||||
CPPAD_ASSERT_UNKNOWN(false);
|
||||
}
|
||||
/*!
|
||||
Put one operation argument index in the recording
|
||||
|
||||
\param arg0
|
||||
The operation argument index
|
||||
|
||||
\copydetails prototype_put_arg
|
||||
*/
|
||||
template <class Base>
|
||||
inline void recorder<Base>::PutArg(addr_t arg0)
|
||||
{
|
||||
size_t i = op_arg_rec_.extend(1);
|
||||
op_arg_rec_[i] = static_cast<addr_t>( arg0 );
|
||||
CPPAD_ASSERT_UNKNOWN( op_arg_rec_.size() == i + 1 );
|
||||
}
|
||||
/*!
|
||||
Put two operation argument index in the recording
|
||||
|
||||
\param arg0
|
||||
First operation argument index.
|
||||
|
||||
\param arg1
|
||||
Second operation argument index.
|
||||
|
||||
\copydetails prototype_put_arg
|
||||
*/
|
||||
template <class Base>
|
||||
inline void recorder<Base>::PutArg(addr_t arg0, addr_t arg1)
|
||||
{
|
||||
size_t i = op_arg_rec_.extend(2);
|
||||
op_arg_rec_[i++] = static_cast<addr_t>( arg0 );
|
||||
op_arg_rec_[i] = static_cast<addr_t>( arg1 );
|
||||
CPPAD_ASSERT_UNKNOWN( op_arg_rec_.size() == i + 1 );
|
||||
}
|
||||
/*!
|
||||
Put three operation argument index in the recording
|
||||
|
||||
\param arg0
|
||||
First operation argument index.
|
||||
|
||||
\param arg1
|
||||
Second operation argument index.
|
||||
|
||||
\param arg2
|
||||
Third operation argument index.
|
||||
|
||||
\copydetails prototype_put_arg
|
||||
*/
|
||||
template <class Base>
|
||||
inline void recorder<Base>::PutArg(addr_t arg0, addr_t arg1, addr_t arg2)
|
||||
{
|
||||
size_t i = op_arg_rec_.extend(3);
|
||||
op_arg_rec_[i++] = static_cast<addr_t>( arg0 );
|
||||
op_arg_rec_[i++] = static_cast<addr_t>( arg1 );
|
||||
op_arg_rec_[i] = static_cast<addr_t>( arg2 );
|
||||
CPPAD_ASSERT_UNKNOWN( op_arg_rec_.size() == i + 1 );
|
||||
}
|
||||
/*!
|
||||
Put four operation argument index in the recording
|
||||
|
||||
\param arg0
|
||||
First operation argument index.
|
||||
|
||||
\param arg1
|
||||
Second operation argument index.
|
||||
|
||||
\param arg2
|
||||
Third operation argument index.
|
||||
|
||||
\param arg3
|
||||
Fourth operation argument index.
|
||||
|
||||
\copydetails prototype_put_arg
|
||||
*/
|
||||
template <class Base>
|
||||
inline void recorder<Base>::PutArg(addr_t arg0, addr_t arg1, addr_t arg2,
|
||||
addr_t arg3)
|
||||
{
|
||||
size_t i = op_arg_rec_.extend(4);
|
||||
op_arg_rec_[i++] = static_cast<addr_t>( arg0 );
|
||||
op_arg_rec_[i++] = static_cast<addr_t>( arg1 );
|
||||
op_arg_rec_[i++] = static_cast<addr_t>( arg2 );
|
||||
op_arg_rec_[i] = static_cast<addr_t>( arg3 );
|
||||
CPPAD_ASSERT_UNKNOWN( op_arg_rec_.size() == i + 1 );
|
||||
|
||||
}
|
||||
/*!
|
||||
Put five operation argument index in the recording
|
||||
|
||||
\param arg0
|
||||
First operation argument index.
|
||||
|
||||
\param arg1
|
||||
Second operation argument index.
|
||||
|
||||
\param arg2
|
||||
Third operation argument index.
|
||||
|
||||
\param arg3
|
||||
Fourth operation argument index.
|
||||
|
||||
\param arg4
|
||||
Fifth operation argument index.
|
||||
|
||||
\copydetails prototype_put_arg
|
||||
*/
|
||||
template <class Base>
|
||||
inline void recorder<Base>::PutArg(addr_t arg0, addr_t arg1, addr_t arg2,
|
||||
addr_t arg3, addr_t arg4)
|
||||
{
|
||||
size_t i = op_arg_rec_.extend(5);
|
||||
op_arg_rec_[i++] = static_cast<addr_t>( arg0 );
|
||||
op_arg_rec_[i++] = static_cast<addr_t>( arg1 );
|
||||
op_arg_rec_[i++] = static_cast<addr_t>( arg2 );
|
||||
op_arg_rec_[i++] = static_cast<addr_t>( arg3 );
|
||||
op_arg_rec_[i] = static_cast<addr_t>( arg4 );
|
||||
CPPAD_ASSERT_UNKNOWN( op_arg_rec_.size() == i + 1 );
|
||||
|
||||
}
|
||||
/*!
|
||||
Put six operation argument index in the recording
|
||||
|
||||
\param arg0
|
||||
First operation argument index.
|
||||
|
||||
\param arg1
|
||||
Second operation argument index.
|
||||
|
||||
\param arg2
|
||||
Third operation argument index.
|
||||
|
||||
\param arg3
|
||||
Fourth operation argument index.
|
||||
|
||||
\param arg4
|
||||
Fifth operation argument index.
|
||||
|
||||
\param arg5
|
||||
Sixth operation argument index.
|
||||
|
||||
\copydetails prototype_put_arg
|
||||
*/
|
||||
template <class Base>
|
||||
inline void recorder<Base>::PutArg(addr_t arg0, addr_t arg1, addr_t arg2,
|
||||
addr_t arg3, addr_t arg4, addr_t arg5)
|
||||
{
|
||||
size_t i = op_arg_rec_.extend(6);
|
||||
op_arg_rec_[i++] = static_cast<addr_t>( arg0 );
|
||||
op_arg_rec_[i++] = static_cast<addr_t>( arg1 );
|
||||
op_arg_rec_[i++] = static_cast<addr_t>( arg2 );
|
||||
op_arg_rec_[i++] = static_cast<addr_t>( arg3 );
|
||||
op_arg_rec_[i++] = static_cast<addr_t>( arg4 );
|
||||
op_arg_rec_[i] = static_cast<addr_t>( arg5 );
|
||||
CPPAD_ASSERT_UNKNOWN( op_arg_rec_.size() == i + 1 );
|
||||
}
|
||||
// --------------------------------------------------------------------------
|
||||
/*!
|
||||
Reserve space for arguments, but delay placing values there.
|
||||
|
||||
\param n_arg
|
||||
number of arguements to reserve space for
|
||||
|
||||
\return
|
||||
is the index in the argument vector corresponding to the
|
||||
first of the arguments being reserved.
|
||||
*/
|
||||
template <class Base>
|
||||
inline size_t recorder<Base>::ReserveArg(size_t n_arg)
|
||||
{
|
||||
size_t i = op_arg_rec_.extend(n_arg);
|
||||
CPPAD_ASSERT_UNKNOWN( op_arg_rec_.size() == i + n_arg );
|
||||
return i;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief
|
||||
Replace an argument value in the recording
|
||||
(intended to fill in reserved values).
|
||||
|
||||
\param i_arg
|
||||
is the index, in argument vector, for the value that is replaced.
|
||||
|
||||
\param value
|
||||
is the new value for the argument with the specified index.
|
||||
*/
|
||||
template <class Base>
|
||||
inline void recorder<Base>::ReplaceArg(size_t i_arg, size_t value)
|
||||
{ op_arg_rec_[i_arg] = static_cast<addr_t>( value ); }
|
||||
// --------------------------------------------------------------------------
|
||||
/*!
|
||||
Put a character string in the text for this recording.
|
||||
|
||||
\param text
|
||||
is a '\\0' terminated character string that is to be put in the
|
||||
vector of characters corresponding to this recording.
|
||||
The terminator '\\0' will be included.
|
||||
|
||||
\return
|
||||
is the offset with in the text vector for this recording at which
|
||||
the character string starts.
|
||||
*/
|
||||
template <class Base>
|
||||
inline addr_t recorder<Base>::PutTxt(const char *text)
|
||||
{
|
||||
// determine length of the text including terminating '\0'
|
||||
size_t n = 0;
|
||||
while( text[n] != '\0' )
|
||||
n++;
|
||||
CPPAD_ASSERT_UNKNOWN( n <= 1000 );
|
||||
n++;
|
||||
CPPAD_ASSERT_UNKNOWN( text[n-1] == '\0' );
|
||||
|
||||
// copy text including terminating '\0'
|
||||
size_t i = text_rec_.extend(n);
|
||||
size_t j;
|
||||
for(j = 0; j < n; j++)
|
||||
text_rec_[i + j] = text[j];
|
||||
CPPAD_ASSERT_UNKNOWN( text_rec_.size() == i + n );
|
||||
|
||||
CPPAD_ASSERT_KNOWN(
|
||||
std::numeric_limits<addr_t>::max() >= i,
|
||||
"cppad_tape_addr_type maximum value has been exceeded"
|
||||
);
|
||||
//
|
||||
return static_cast<addr_t>( i );
|
||||
}
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
|
||||
} } // END_CPPAD_LOCAL_NAMESPACE
|
||||
# endif
|
||||
@@ -0,0 +1,783 @@
|
||||
# ifndef CPPAD_LOCAL_REV_HES_SWEEP_HPP
|
||||
# define CPPAD_LOCAL_REV_HES_SWEEP_HPP
|
||||
|
||||
/* --------------------------------------------------------------------------
|
||||
CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-17 Bradley M. Bell
|
||||
|
||||
CppAD is distributed under multiple licenses. This distribution is under
|
||||
the terms of the
|
||||
Eclipse Public License Version 1.0.
|
||||
|
||||
A copy of this license is included in the COPYING file of this distribution.
|
||||
Please visit http://www.coin-or.org/CppAD/ for information on other licenses.
|
||||
-------------------------------------------------------------------------- */
|
||||
|
||||
namespace CppAD { namespace local { // BEGIN_CPPAD_LOCAL_NAMESPACE
|
||||
/*!
|
||||
\file rev_hes_sweep.hpp
|
||||
Compute Reverse mode Hessian sparsity patterns.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\def CPPAD_REV_HES_SWEEP_TRACE
|
||||
This value is either zero or one.
|
||||
Zero is the normal operational value.
|
||||
If it is one, a trace of every rev_hes_sweep computation is printed.
|
||||
*/
|
||||
# define CPPAD_REV_HES_SWEEP_TRACE 0
|
||||
|
||||
/*!
|
||||
Given the forward Jacobian sparsity pattern for all the variables,
|
||||
and the reverse Jacobian sparsity pattern for the dependent variables,
|
||||
RevHesSweep computes the Hessian sparsity pattern for all the independent
|
||||
variables.
|
||||
|
||||
\tparam Base
|
||||
base type for the operator; i.e., this operation sequence was recorded
|
||||
using AD< \a Base > and computations by this routine are done using type
|
||||
\a Base.
|
||||
|
||||
\tparam Vector_set
|
||||
is the type used for vectors of sets. It can be either
|
||||
sparse_pack or sparse_list.
|
||||
|
||||
\param n
|
||||
is the number of independent variables on the tape.
|
||||
|
||||
\param numvar
|
||||
is the total number of variables on the tape; i.e.,
|
||||
\a play->num_var_rec().
|
||||
This is also the number of rows in the entire sparsity pattern
|
||||
\a rev_hes_sparse.
|
||||
|
||||
\param play
|
||||
The information stored in \a play
|
||||
is a recording of the operations corresponding to a function
|
||||
\f[
|
||||
F : {\bf R}^n \rightarrow {\bf R}^m
|
||||
\f]
|
||||
where \f$ n \f$ is the number of independent variables
|
||||
and \f$ m \f$ is the number of dependent variables.
|
||||
The object \a play is effectly constant.
|
||||
It is not declared const because while playing back the tape
|
||||
the object \a play holds information about the current location
|
||||
with in the tape and this changes during playback.
|
||||
|
||||
\param for_jac_sparse
|
||||
For i = 0 , ... , \a numvar - 1,
|
||||
(for all the variables on the tape),
|
||||
the forward Jacobian sparsity pattern for the variable with index i
|
||||
corresponds to the set with index i in \a for_jac_sparse.
|
||||
|
||||
\param RevJac
|
||||
\b Input:
|
||||
For i = 0, ... , \a numvar - 1
|
||||
the if the variable with index i on the tape is an dependent variable and
|
||||
included in the Hessian, \a RevJac[ i ] is equal to true,
|
||||
otherwise it is equal to false.
|
||||
\n
|
||||
\n
|
||||
\b Output: The values in \a RevJac upon return are not specified; i.e.,
|
||||
it is used for temporary work space.
|
||||
|
||||
\param rev_hes_sparse
|
||||
The reverse Hessian sparsity pattern for the variable with index i
|
||||
corresponds to the set with index i in \a rev_hes_sparse.
|
||||
\n
|
||||
\n
|
||||
\b Input: For i = 0 , ... , \a numvar - 1
|
||||
the reverse Hessian sparsity pattern for the variable with index i is empty.
|
||||
\n
|
||||
\n
|
||||
\b Output: For j = 1 , ... , \a n,
|
||||
the reverse Hessian sparsity pattern for the independent dependent variable
|
||||
with index (j-1) is given by the set with index j
|
||||
in \a rev_hes_sparse.
|
||||
The values in the rest of \a rev_hes_sparse are not specified; i.e.,
|
||||
they are used for temporary work space.
|
||||
*/
|
||||
|
||||
template <class Base, class Vector_set>
|
||||
void RevHesSweep(
|
||||
size_t n,
|
||||
size_t numvar,
|
||||
local::player<Base>* play,
|
||||
const Vector_set& for_jac_sparse,
|
||||
bool* RevJac,
|
||||
Vector_set& rev_hes_sparse
|
||||
)
|
||||
{
|
||||
OpCode op;
|
||||
size_t i_op;
|
||||
size_t i_var;
|
||||
|
||||
const addr_t* arg = CPPAD_NULL;
|
||||
|
||||
// length of the parameter vector (used by CppAD assert macros)
|
||||
const size_t num_par = play->num_par_rec();
|
||||
|
||||
size_t i, j, k;
|
||||
|
||||
// check numvar argument
|
||||
CPPAD_ASSERT_UNKNOWN( play->num_var_rec() == numvar );
|
||||
CPPAD_ASSERT_UNKNOWN( for_jac_sparse.n_set() == numvar );
|
||||
CPPAD_ASSERT_UNKNOWN( rev_hes_sparse.n_set() == numvar );
|
||||
CPPAD_ASSERT_UNKNOWN( numvar > 0 );
|
||||
|
||||
// upper limit exclusive for set elements
|
||||
size_t limit = rev_hes_sparse.end();
|
||||
CPPAD_ASSERT_UNKNOWN( for_jac_sparse.end() == limit );
|
||||
|
||||
// check number of sets match
|
||||
CPPAD_ASSERT_UNKNOWN(
|
||||
for_jac_sparse.n_set() == rev_hes_sparse.n_set()
|
||||
);
|
||||
|
||||
// vecad_sparsity contains a sparsity pattern for each VecAD object.
|
||||
// vecad_ind maps a VecAD index (beginning of the VecAD object)
|
||||
// to the index for the corresponding set in vecad_sparsity.
|
||||
size_t num_vecad_ind = play->num_vec_ind_rec();
|
||||
size_t num_vecad_vec = play->num_vecad_vec_rec();
|
||||
Vector_set vecad_sparse;
|
||||
vecad_sparse.resize(num_vecad_vec, limit);
|
||||
pod_vector<size_t> vecad_ind;
|
||||
pod_vector<bool> vecad_jac;
|
||||
if( num_vecad_vec > 0 )
|
||||
{ size_t length;
|
||||
vecad_ind.extend(num_vecad_ind);
|
||||
vecad_jac.extend(num_vecad_vec);
|
||||
j = 0;
|
||||
for(i = 0; i < num_vecad_vec; i++)
|
||||
{ // length of this VecAD
|
||||
length = play->GetVecInd(j);
|
||||
// set vecad_ind to proper index for this VecAD
|
||||
vecad_ind[j] = i;
|
||||
// make all other values for this vector invalid
|
||||
for(k = 1; k <= length; k++)
|
||||
vecad_ind[j+k] = num_vecad_vec;
|
||||
// start of next VecAD
|
||||
j += length + 1;
|
||||
// initialize this vector's reverse jacobian value
|
||||
vecad_jac[i] = false;
|
||||
}
|
||||
CPPAD_ASSERT_UNKNOWN( j == play->num_vec_ind_rec() );
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// user's atomic op calculator
|
||||
atomic_base<Base>* user_atom = CPPAD_NULL; // user's atomic op calculator
|
||||
//
|
||||
// work space used by UserOp.
|
||||
vector<Base> user_x; // parameters in x as integers
|
||||
vector<size_t> user_ix; // variable indices for argument vector
|
||||
vector<size_t> user_iy; // variable indices for result vector
|
||||
//
|
||||
// information set by forward_user (initialization to avoid warnings)
|
||||
size_t user_old=0, user_m=0, user_n=0, user_i=0, user_j=0;
|
||||
// information set by forward_user (necessary initialization)
|
||||
enum_user_state user_state = end_user; // proper initialization
|
||||
// ----------------------------------------------------------------------
|
||||
//
|
||||
// pointer to the beginning of the parameter vector
|
||||
// (used by atomic functions
|
||||
const Base* parameter = CPPAD_NULL;
|
||||
if( num_par > 0 )
|
||||
parameter = play->GetPar();
|
||||
//
|
||||
// Initialize
|
||||
play->reverse_start(op, arg, i_op, i_var);
|
||||
CPPAD_ASSERT_UNKNOWN( op == EndOp );
|
||||
# if CPPAD_REV_HES_SWEEP_TRACE
|
||||
std::cout << std::endl;
|
||||
CppAD::vectorBool zf_value(limit);
|
||||
CppAD::vectorBool zh_value(limit);
|
||||
# endif
|
||||
bool more_operators = true;
|
||||
while(more_operators)
|
||||
{ bool flag; // temporary for use in switch cases
|
||||
//
|
||||
// next op
|
||||
play->reverse_next(op, arg, i_op, i_var);
|
||||
# ifndef NDEBUG
|
||||
if( i_op <= n )
|
||||
{ CPPAD_ASSERT_UNKNOWN((op == InvOp) | (op == BeginOp));
|
||||
}
|
||||
else CPPAD_ASSERT_UNKNOWN((op != InvOp) & (op != BeginOp));
|
||||
# endif
|
||||
|
||||
// rest of information depends on the case
|
||||
switch( op )
|
||||
{
|
||||
case AbsOp:
|
||||
CPPAD_ASSERT_NARG_NRES(op, 1, 1)
|
||||
reverse_sparse_hessian_linear_unary_op(
|
||||
i_var, arg[0], RevJac, for_jac_sparse, rev_hes_sparse
|
||||
);
|
||||
break;
|
||||
// -------------------------------------------------
|
||||
|
||||
case AddvvOp:
|
||||
CPPAD_ASSERT_NARG_NRES(op, 2, 1)
|
||||
reverse_sparse_hessian_addsub_op(
|
||||
i_var, arg, RevJac, for_jac_sparse, rev_hes_sparse
|
||||
);
|
||||
break;
|
||||
// -------------------------------------------------
|
||||
|
||||
case AddpvOp:
|
||||
CPPAD_ASSERT_NARG_NRES(op, 2, 1)
|
||||
reverse_sparse_hessian_linear_unary_op(
|
||||
i_var, arg[1], RevJac, for_jac_sparse, rev_hes_sparse
|
||||
);
|
||||
break;
|
||||
// -------------------------------------------------
|
||||
|
||||
case AcosOp:
|
||||
// sqrt(1 - x * x), acos(x)
|
||||
CPPAD_ASSERT_NARG_NRES(op, 1, 2)
|
||||
reverse_sparse_hessian_nonlinear_unary_op(
|
||||
i_var, arg[0], RevJac, for_jac_sparse, rev_hes_sparse
|
||||
);
|
||||
break;
|
||||
// -------------------------------------------------
|
||||
|
||||
# if CPPAD_USE_CPLUSPLUS_2011
|
||||
case AcoshOp:
|
||||
// sqrt(x * x - 1), acosh(x)
|
||||
CPPAD_ASSERT_NARG_NRES(op, 1, 2)
|
||||
reverse_sparse_hessian_nonlinear_unary_op(
|
||||
i_var, arg[0], RevJac, for_jac_sparse, rev_hes_sparse
|
||||
);
|
||||
break;
|
||||
# endif
|
||||
// -------------------------------------------------
|
||||
|
||||
case AsinOp:
|
||||
// sqrt(1 - x * x), asin(x)
|
||||
CPPAD_ASSERT_NARG_NRES(op, 1, 2)
|
||||
reverse_sparse_hessian_nonlinear_unary_op(
|
||||
i_var, arg[0], RevJac, for_jac_sparse, rev_hes_sparse
|
||||
);
|
||||
break;
|
||||
// -------------------------------------------------
|
||||
|
||||
# if CPPAD_USE_CPLUSPLUS_2011
|
||||
case AsinhOp:
|
||||
// sqrt(1 + x * x), asinh(x)
|
||||
CPPAD_ASSERT_NARG_NRES(op, 1, 2)
|
||||
reverse_sparse_hessian_nonlinear_unary_op(
|
||||
i_var, arg[0], RevJac, for_jac_sparse, rev_hes_sparse
|
||||
);
|
||||
break;
|
||||
# endif
|
||||
// -------------------------------------------------
|
||||
|
||||
case AtanOp:
|
||||
// 1 + x * x, atan(x)
|
||||
CPPAD_ASSERT_NARG_NRES(op, 1, 2)
|
||||
reverse_sparse_hessian_nonlinear_unary_op(
|
||||
i_var, arg[0], RevJac, for_jac_sparse, rev_hes_sparse
|
||||
);
|
||||
break;
|
||||
// -------------------------------------------------
|
||||
|
||||
# if CPPAD_USE_CPLUSPLUS_2011
|
||||
case AtanhOp:
|
||||
// 1 - x * x, atanh(x)
|
||||
CPPAD_ASSERT_NARG_NRES(op, 1, 2)
|
||||
reverse_sparse_hessian_nonlinear_unary_op(
|
||||
i_var, arg[0], RevJac, for_jac_sparse, rev_hes_sparse
|
||||
);
|
||||
break;
|
||||
# endif
|
||||
// -------------------------------------------------
|
||||
|
||||
case BeginOp:
|
||||
CPPAD_ASSERT_NARG_NRES(op, 1, 1)
|
||||
more_operators = false;
|
||||
break;
|
||||
// -------------------------------------------------
|
||||
|
||||
case CSkipOp:
|
||||
// CSkipOp has a variable number of arguments and
|
||||
// reverse_next thinks it one has one argument.
|
||||
// We must inform reverse_next of this special case.
|
||||
play->reverse_cskip(op, arg, i_op, i_var);
|
||||
break;
|
||||
// -------------------------------------------------
|
||||
|
||||
case CSumOp:
|
||||
// CSumOp has a variable number of arguments and
|
||||
// reverse_next thinks it one has one argument.
|
||||
// We must inform reverse_next of this special case.
|
||||
play->reverse_csum(op, arg, i_op, i_var);
|
||||
reverse_sparse_hessian_csum_op(
|
||||
i_var, arg, RevJac, rev_hes_sparse
|
||||
);
|
||||
break;
|
||||
// -------------------------------------------------
|
||||
|
||||
case CExpOp:
|
||||
reverse_sparse_hessian_cond_op(
|
||||
i_var, arg, num_par, RevJac, rev_hes_sparse
|
||||
);
|
||||
break;
|
||||
// ---------------------------------------------------
|
||||
|
||||
case CosOp:
|
||||
// sin(x), cos(x)
|
||||
CPPAD_ASSERT_NARG_NRES(op, 1, 2)
|
||||
reverse_sparse_hessian_nonlinear_unary_op(
|
||||
i_var, arg[0], RevJac, for_jac_sparse, rev_hes_sparse
|
||||
);
|
||||
break;
|
||||
// ---------------------------------------------------
|
||||
|
||||
case CoshOp:
|
||||
// sinh(x), cosh(x)
|
||||
CPPAD_ASSERT_NARG_NRES(op, 1, 2)
|
||||
reverse_sparse_hessian_nonlinear_unary_op(
|
||||
i_var, arg[0], RevJac, for_jac_sparse, rev_hes_sparse
|
||||
);
|
||||
break;
|
||||
// -------------------------------------------------
|
||||
|
||||
case DisOp:
|
||||
CPPAD_ASSERT_NARG_NRES(op, 2, 1)
|
||||
// derivativve is identically zero
|
||||
break;
|
||||
// -------------------------------------------------
|
||||
|
||||
case DivvvOp:
|
||||
CPPAD_ASSERT_NARG_NRES(op, 2, 1)
|
||||
reverse_sparse_hessian_div_op(
|
||||
i_var, arg, RevJac, for_jac_sparse, rev_hes_sparse
|
||||
);
|
||||
break;
|
||||
// -------------------------------------------------
|
||||
|
||||
case DivpvOp:
|
||||
CPPAD_ASSERT_NARG_NRES(op, 2, 1)
|
||||
reverse_sparse_hessian_nonlinear_unary_op(
|
||||
i_var, arg[1], RevJac, for_jac_sparse, rev_hes_sparse
|
||||
);
|
||||
break;
|
||||
// -------------------------------------------------
|
||||
|
||||
case DivvpOp:
|
||||
CPPAD_ASSERT_NARG_NRES(op, 2, 1)
|
||||
reverse_sparse_hessian_linear_unary_op(
|
||||
i_var, arg[0], RevJac, for_jac_sparse, rev_hes_sparse
|
||||
);
|
||||
break;
|
||||
// -------------------------------------------------
|
||||
|
||||
case ErfOp:
|
||||
// arg[1] is always the parameter 0
|
||||
// arg[2] is always the parameter 2 / sqrt(pi)
|
||||
CPPAD_ASSERT_NARG_NRES(op, 3, 5);
|
||||
reverse_sparse_hessian_nonlinear_unary_op(
|
||||
i_var, arg[0], RevJac, for_jac_sparse, rev_hes_sparse
|
||||
);
|
||||
break;
|
||||
// -------------------------------------------------
|
||||
|
||||
case ExpOp:
|
||||
CPPAD_ASSERT_NARG_NRES(op, 1, 1)
|
||||
reverse_sparse_hessian_nonlinear_unary_op(
|
||||
i_var, arg[0], RevJac, for_jac_sparse, rev_hes_sparse
|
||||
);
|
||||
break;
|
||||
// -------------------------------------------------
|
||||
|
||||
# if CPPAD_USE_CPLUSPLUS_2011
|
||||
case Expm1Op:
|
||||
CPPAD_ASSERT_NARG_NRES(op, 1, 1)
|
||||
reverse_sparse_hessian_nonlinear_unary_op(
|
||||
i_var, arg[0], RevJac, for_jac_sparse, rev_hes_sparse
|
||||
);
|
||||
break;
|
||||
# endif
|
||||
// -------------------------------------------------
|
||||
|
||||
case InvOp:
|
||||
CPPAD_ASSERT_NARG_NRES(op, 0, 1)
|
||||
// Z is already defined
|
||||
break;
|
||||
// -------------------------------------------------
|
||||
|
||||
case LdpOp:
|
||||
reverse_sparse_hessian_load_op(
|
||||
op,
|
||||
i_var,
|
||||
arg,
|
||||
num_vecad_ind,
|
||||
vecad_ind.data(),
|
||||
rev_hes_sparse,
|
||||
vecad_sparse,
|
||||
RevJac,
|
||||
vecad_jac.data()
|
||||
);
|
||||
break;
|
||||
// -------------------------------------------------
|
||||
|
||||
case LdvOp:
|
||||
reverse_sparse_hessian_load_op(
|
||||
op,
|
||||
i_var,
|
||||
arg,
|
||||
num_vecad_ind,
|
||||
vecad_ind.data(),
|
||||
rev_hes_sparse,
|
||||
vecad_sparse,
|
||||
RevJac,
|
||||
vecad_jac.data()
|
||||
);
|
||||
break;
|
||||
// -------------------------------------------------
|
||||
|
||||
case EqpvOp:
|
||||
case EqvvOp:
|
||||
case LtpvOp:
|
||||
case LtvpOp:
|
||||
case LtvvOp:
|
||||
case LepvOp:
|
||||
case LevpOp:
|
||||
case LevvOp:
|
||||
case NepvOp:
|
||||
case NevvOp:
|
||||
CPPAD_ASSERT_NARG_NRES(op, 2, 0);
|
||||
break;
|
||||
// -------------------------------------------------
|
||||
|
||||
case LogOp:
|
||||
CPPAD_ASSERT_NARG_NRES(op, 1, 1)
|
||||
reverse_sparse_hessian_nonlinear_unary_op(
|
||||
i_var, arg[0], RevJac, for_jac_sparse, rev_hes_sparse
|
||||
);
|
||||
break;
|
||||
// -------------------------------------------------
|
||||
|
||||
# if CPPAD_USE_CPLUSPLUS_2011
|
||||
case Log1pOp:
|
||||
CPPAD_ASSERT_NARG_NRES(op, 1, 1)
|
||||
reverse_sparse_hessian_nonlinear_unary_op(
|
||||
i_var, arg[0], RevJac, for_jac_sparse, rev_hes_sparse
|
||||
);
|
||||
break;
|
||||
# endif
|
||||
// -------------------------------------------------
|
||||
|
||||
case MulpvOp:
|
||||
CPPAD_ASSERT_NARG_NRES(op, 2, 1)
|
||||
reverse_sparse_hessian_linear_unary_op(
|
||||
i_var, arg[1], RevJac, for_jac_sparse, rev_hes_sparse
|
||||
);
|
||||
break;
|
||||
// -------------------------------------------------
|
||||
|
||||
case MulvvOp:
|
||||
CPPAD_ASSERT_NARG_NRES(op, 2, 1)
|
||||
reverse_sparse_hessian_mul_op(
|
||||
i_var, arg, RevJac, for_jac_sparse, rev_hes_sparse
|
||||
);
|
||||
break;
|
||||
// -------------------------------------------------
|
||||
|
||||
case ParOp:
|
||||
CPPAD_ASSERT_NARG_NRES(op, 1, 1)
|
||||
|
||||
break;
|
||||
// -------------------------------------------------
|
||||
|
||||
case PowpvOp:
|
||||
CPPAD_ASSERT_NARG_NRES(op, 2, 3)
|
||||
reverse_sparse_hessian_nonlinear_unary_op(
|
||||
i_var, arg[1], RevJac, for_jac_sparse, rev_hes_sparse
|
||||
);
|
||||
break;
|
||||
// -------------------------------------------------
|
||||
|
||||
case PowvpOp:
|
||||
CPPAD_ASSERT_NARG_NRES(op, 2, 3)
|
||||
reverse_sparse_hessian_nonlinear_unary_op(
|
||||
i_var, arg[0], RevJac, for_jac_sparse, rev_hes_sparse
|
||||
);
|
||||
break;
|
||||
// -------------------------------------------------
|
||||
|
||||
case PowvvOp:
|
||||
CPPAD_ASSERT_NARG_NRES(op, 2, 3)
|
||||
reverse_sparse_hessian_pow_op(
|
||||
i_var, arg, RevJac, for_jac_sparse, rev_hes_sparse
|
||||
);
|
||||
break;
|
||||
// -------------------------------------------------
|
||||
|
||||
case PriOp:
|
||||
CPPAD_ASSERT_NARG_NRES(op, 5, 0);
|
||||
break;
|
||||
// -------------------------------------------------
|
||||
|
||||
case SignOp:
|
||||
CPPAD_ASSERT_NARG_NRES(op, 1, 1);
|
||||
// Derivative is identiaclly zero
|
||||
break;
|
||||
// -------------------------------------------------
|
||||
|
||||
case SinOp:
|
||||
// cos(x), sin(x)
|
||||
CPPAD_ASSERT_NARG_NRES(op, 1, 2)
|
||||
reverse_sparse_hessian_nonlinear_unary_op(
|
||||
i_var, arg[0], RevJac, for_jac_sparse, rev_hes_sparse
|
||||
);
|
||||
break;
|
||||
// -------------------------------------------------
|
||||
|
||||
case SinhOp:
|
||||
// cosh(x), sinh(x)
|
||||
CPPAD_ASSERT_NARG_NRES(op, 1, 2)
|
||||
reverse_sparse_hessian_nonlinear_unary_op(
|
||||
i_var, arg[0], RevJac, for_jac_sparse, rev_hes_sparse
|
||||
);
|
||||
break;
|
||||
// -------------------------------------------------
|
||||
|
||||
case SqrtOp:
|
||||
CPPAD_ASSERT_NARG_NRES(op, 1, 1)
|
||||
reverse_sparse_hessian_nonlinear_unary_op(
|
||||
i_var, arg[0], RevJac, for_jac_sparse, rev_hes_sparse
|
||||
);
|
||||
break;
|
||||
// -------------------------------------------------
|
||||
|
||||
case StppOp:
|
||||
// sparsity cannot propagate through a parameter
|
||||
CPPAD_ASSERT_NARG_NRES(op, 3, 0)
|
||||
break;
|
||||
// -------------------------------------------------
|
||||
|
||||
case StpvOp:
|
||||
reverse_sparse_hessian_store_op(
|
||||
op,
|
||||
arg,
|
||||
num_vecad_ind,
|
||||
vecad_ind.data(),
|
||||
rev_hes_sparse,
|
||||
vecad_sparse,
|
||||
RevJac,
|
||||
vecad_jac.data()
|
||||
);
|
||||
break;
|
||||
// -------------------------------------------------
|
||||
|
||||
case StvpOp:
|
||||
// sparsity cannot propagate through a parameter
|
||||
CPPAD_ASSERT_NARG_NRES(op, 3, 0)
|
||||
break;
|
||||
// -------------------------------------------------
|
||||
|
||||
case StvvOp:
|
||||
reverse_sparse_hessian_store_op(
|
||||
op,
|
||||
arg,
|
||||
num_vecad_ind,
|
||||
vecad_ind.data(),
|
||||
rev_hes_sparse,
|
||||
vecad_sparse,
|
||||
RevJac,
|
||||
vecad_jac.data()
|
||||
);
|
||||
break;
|
||||
// -------------------------------------------------
|
||||
|
||||
case SubvvOp:
|
||||
CPPAD_ASSERT_NARG_NRES(op, 2, 1)
|
||||
reverse_sparse_hessian_addsub_op(
|
||||
i_var, arg, RevJac, for_jac_sparse, rev_hes_sparse
|
||||
);
|
||||
break;
|
||||
// -------------------------------------------------
|
||||
|
||||
case SubpvOp:
|
||||
CPPAD_ASSERT_NARG_NRES(op, 2, 1)
|
||||
reverse_sparse_hessian_linear_unary_op(
|
||||
i_var, arg[1], RevJac, for_jac_sparse, rev_hes_sparse
|
||||
);
|
||||
break;
|
||||
// -------------------------------------------------
|
||||
|
||||
case SubvpOp:
|
||||
CPPAD_ASSERT_NARG_NRES(op, 2, 1)
|
||||
reverse_sparse_hessian_linear_unary_op(
|
||||
i_var, arg[0], RevJac, for_jac_sparse, rev_hes_sparse
|
||||
);
|
||||
break;
|
||||
// -------------------------------------------------
|
||||
|
||||
case TanOp:
|
||||
// tan(x)^2, tan(x)
|
||||
CPPAD_ASSERT_NARG_NRES(op, 1, 2)
|
||||
reverse_sparse_hessian_nonlinear_unary_op(
|
||||
i_var, arg[0], RevJac, for_jac_sparse, rev_hes_sparse
|
||||
);
|
||||
break;
|
||||
// -------------------------------------------------
|
||||
|
||||
case TanhOp:
|
||||
// tanh(x)^2, tanh(x)
|
||||
CPPAD_ASSERT_NARG_NRES(op, 1, 2)
|
||||
reverse_sparse_hessian_nonlinear_unary_op(
|
||||
i_var, arg[0], RevJac, for_jac_sparse, rev_hes_sparse
|
||||
);
|
||||
break;
|
||||
// -------------------------------------------------
|
||||
|
||||
case UserOp:
|
||||
CPPAD_ASSERT_UNKNOWN(
|
||||
user_state == start_user || user_state == end_user
|
||||
);
|
||||
flag = user_state == end_user;
|
||||
user_atom = play->reverse_user(op, user_state,
|
||||
user_old, user_m, user_n, user_i, user_j
|
||||
);
|
||||
if( flag )
|
||||
{ user_x.resize(user_n);
|
||||
user_ix.resize(user_n);
|
||||
user_iy.resize(user_m);
|
||||
}
|
||||
else
|
||||
{ // call users function for this operation
|
||||
user_atom->set_old(user_old);
|
||||
user_atom->rev_sparse_hes(
|
||||
user_x, user_ix, user_iy,
|
||||
for_jac_sparse, RevJac, rev_hes_sparse
|
||||
);
|
||||
}
|
||||
break;
|
||||
|
||||
case UsrapOp:
|
||||
// parameter argument in an atomic operation sequence
|
||||
CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < num_par );
|
||||
play->reverse_user(op, user_state,
|
||||
user_old, user_m, user_n, user_i, user_j
|
||||
);
|
||||
// argument parameter value
|
||||
user_x[user_j] = parameter[arg[0]];
|
||||
// special variable index used for parameters
|
||||
user_ix[user_j] = 0;
|
||||
break;
|
||||
|
||||
case UsravOp:
|
||||
// variable argument in an atomic operation sequence
|
||||
CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) <= i_var );
|
||||
CPPAD_ASSERT_UNKNOWN( 0 < arg[0] );
|
||||
play->reverse_user(op, user_state,
|
||||
user_old, user_m, user_n, user_i, user_j
|
||||
);
|
||||
// argument variables not available during sparsity calculations
|
||||
user_x[user_j] = CppAD::numeric_limits<Base>::quiet_NaN();
|
||||
// variable index for this argument
|
||||
user_ix[user_j] = arg[0];
|
||||
break;
|
||||
|
||||
case UsrrpOp:
|
||||
// parameter result in an atomic operation sequence
|
||||
CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < num_par );
|
||||
play->reverse_user(op, user_state,
|
||||
user_old, user_m, user_n, user_i, user_j
|
||||
);
|
||||
// special variable index used for parameters
|
||||
user_iy[user_i] = 0;
|
||||
break;
|
||||
|
||||
case UsrrvOp:
|
||||
// variable result in an atomic operation sequence
|
||||
play->reverse_user(op, user_state,
|
||||
user_old, user_m, user_n, user_i, user_j
|
||||
);
|
||||
// variable index for this result
|
||||
user_iy[user_i] = i_var;
|
||||
break;
|
||||
// -------------------------------------------------
|
||||
|
||||
case ZmulpvOp:
|
||||
CPPAD_ASSERT_NARG_NRES(op, 2, 1)
|
||||
reverse_sparse_hessian_linear_unary_op(
|
||||
i_var, arg[1], RevJac, for_jac_sparse, rev_hes_sparse
|
||||
);
|
||||
break;
|
||||
// -------------------------------------------------
|
||||
|
||||
case ZmulvpOp:
|
||||
CPPAD_ASSERT_NARG_NRES(op, 2, 1)
|
||||
reverse_sparse_hessian_linear_unary_op(
|
||||
i_var, arg[0], RevJac, for_jac_sparse, rev_hes_sparse
|
||||
);
|
||||
break;
|
||||
// -------------------------------------------------
|
||||
|
||||
case ZmulvvOp:
|
||||
CPPAD_ASSERT_NARG_NRES(op, 2, 1)
|
||||
reverse_sparse_hessian_mul_op(
|
||||
i_var, arg, RevJac, for_jac_sparse, rev_hes_sparse
|
||||
);
|
||||
break;
|
||||
|
||||
// -------------------------------------------------
|
||||
|
||||
default:
|
||||
CPPAD_ASSERT_UNKNOWN(0);
|
||||
}
|
||||
# if CPPAD_REV_HES_SWEEP_TRACE
|
||||
for(j = 0; j < limit; j++)
|
||||
{ zf_value[j] = false;
|
||||
zh_value[j] = false;
|
||||
}
|
||||
typename Vector_set::const_iterator itr_jac(for_jac_sparse, i_var);
|
||||
j = *itr_jac;
|
||||
while( j < limit )
|
||||
{ zf_value[j] = true;
|
||||
j = *(++itr_jac);
|
||||
}
|
||||
typename Vector_set::const_iterator itr_hes(rev_hes_sparse, i_var);
|
||||
j = *itr_hes;
|
||||
while( j < limit )
|
||||
{ zh_value[j] = true;
|
||||
j = *(++itr_hes);
|
||||
}
|
||||
printOp(
|
||||
std::cout,
|
||||
play,
|
||||
i_op,
|
||||
i_var,
|
||||
op,
|
||||
arg
|
||||
);
|
||||
// should also print RevJac[i_var], but printOpResult does not
|
||||
// yet allow for this
|
||||
if( NumRes(op) > 0 && op != BeginOp ) printOpResult(
|
||||
std::cout,
|
||||
1,
|
||||
&zf_value,
|
||||
1,
|
||||
&zh_value
|
||||
);
|
||||
std::cout << std::endl;
|
||||
}
|
||||
std::cout << std::endl;
|
||||
# else
|
||||
}
|
||||
# endif
|
||||
// values corresponding to BeginOp
|
||||
CPPAD_ASSERT_UNKNOWN( i_op == 0 );
|
||||
CPPAD_ASSERT_UNKNOWN( i_var == 0 );
|
||||
|
||||
return;
|
||||
}
|
||||
} } // END_CPPAD_LOCAL_NAMESPACE
|
||||
|
||||
// preprocessor symbols that are local to this file
|
||||
# undef CPPAD_REV_HES_SWEEP_TRACE
|
||||
|
||||
# endif
|
||||
@@ -0,0 +1,758 @@
|
||||
# ifndef CPPAD_LOCAL_REV_JAC_SWEEP_HPP
|
||||
# define CPPAD_LOCAL_REV_JAC_SWEEP_HPP
|
||||
|
||||
/* --------------------------------------------------------------------------
|
||||
CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-17 Bradley M. Bell
|
||||
|
||||
CppAD is distributed under multiple licenses. This distribution is under
|
||||
the terms of the
|
||||
Eclipse Public License Version 1.0.
|
||||
|
||||
A copy of this license is included in the COPYING file of this distribution.
|
||||
Please visit http://www.coin-or.org/CppAD/ for information on other licenses.
|
||||
-------------------------------------------------------------------------- */
|
||||
|
||||
namespace CppAD { namespace local { // BEGIN_CPPAD_LOCAL_NAMESPACE
|
||||
/*!
|
||||
\file rev_jac_sweep.hpp
|
||||
Compute Reverse mode Jacobian sparsity patterns.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\def CPPAD_REV_JAC_SWEEP_TRACE
|
||||
This value is either zero or one.
|
||||
Zero is the normal operational value.
|
||||
If it is one, a trace of every rev_jac_sweep computation is printed.
|
||||
*/
|
||||
# define CPPAD_REV_JAC_SWEEP_TRACE 0
|
||||
|
||||
/*!
|
||||
Given the sparsity pattern for the dependent variables,
|
||||
RevJacSweep computes the sparsity pattern for all the independent variables.
|
||||
|
||||
\tparam Base
|
||||
base type for the operator; i.e., this operation sequence was recorded
|
||||
using AD< \a Base > and computations by this routine are done using type
|
||||
\a Base.
|
||||
|
||||
\tparam Vector_set
|
||||
is the type used for vectors of sets. It can be either
|
||||
sparse_pack or sparse_list.
|
||||
|
||||
\param dependency
|
||||
Are the derivatives with respect to left and right of the expression below
|
||||
considered to be non-zero:
|
||||
\code
|
||||
CondExpRel(left, right, if_true, if_false)
|
||||
\endcode
|
||||
This is used by the optimizer to obtain the correct dependency relations.
|
||||
|
||||
\param n
|
||||
is the number of independent variables on the tape.
|
||||
|
||||
\param numvar
|
||||
is the total number of variables on the tape; i.e.,
|
||||
\a play->num_var_rec().
|
||||
This is also the number of rows in the entire sparsity pattern \a RevJac.
|
||||
|
||||
\param play
|
||||
The information stored in \a play
|
||||
is a recording of the operations corresponding to a function
|
||||
\f[
|
||||
F : {\bf R}^n \rightarrow {\bf R}^m
|
||||
\f]
|
||||
where \f$ n \f$ is the number of independent variables
|
||||
and \f$ m \f$ is the number of dependent variables.
|
||||
The object \a play is effectly constant.
|
||||
It is not declared const because while playing back the tape
|
||||
the object \a play holds information about the current location
|
||||
with in the tape and this changes during playback.
|
||||
|
||||
\param var_sparsity
|
||||
For i = 0 , ... , \a numvar - 1,
|
||||
(all the variables on the tape)
|
||||
the forward Jacobian sparsity pattern for variable i
|
||||
corresponds to the set with index i in \a var_sparsity.
|
||||
\b
|
||||
\b
|
||||
\b Input:
|
||||
For i = 0 , ... , \a numvar - 1,
|
||||
the forward Jacobian sparsity pattern for variable i is an input
|
||||
if i corresponds to a dependent variable.
|
||||
Otherwise the sparsity patten is empty.
|
||||
\n
|
||||
\n
|
||||
\b Output: For j = 1 , ... , \a n,
|
||||
the sparsity pattern for the dependent variable with index (j-1)
|
||||
is given by the set with index index j in \a var_sparsity.
|
||||
*/
|
||||
|
||||
template <class Base, class Vector_set>
|
||||
void RevJacSweep(
|
||||
bool dependency,
|
||||
size_t n,
|
||||
size_t numvar,
|
||||
local::player<Base>* play,
|
||||
Vector_set& var_sparsity
|
||||
)
|
||||
{
|
||||
OpCode op;
|
||||
size_t i_op;
|
||||
size_t i_var;
|
||||
|
||||
const addr_t* arg = CPPAD_NULL;
|
||||
|
||||
size_t i, j, k;
|
||||
|
||||
// length of the parameter vector (used by CppAD assert macros)
|
||||
const size_t num_par = play->num_par_rec();
|
||||
|
||||
// check numvar argument
|
||||
CPPAD_ASSERT_UNKNOWN( numvar > 0 );
|
||||
CPPAD_ASSERT_UNKNOWN( play->num_var_rec() == numvar );
|
||||
CPPAD_ASSERT_UNKNOWN( var_sparsity.n_set() == numvar );
|
||||
|
||||
// upper limit (exclusive) for elements in the set
|
||||
size_t limit = var_sparsity.end();
|
||||
|
||||
// vecad_sparsity contains a sparsity pattern for each VecAD object.
|
||||
// vecad_ind maps a VecAD index (beginning of the VecAD object)
|
||||
// to the index of the corresponding set in vecad_sparsity.
|
||||
size_t num_vecad_ind = play->num_vec_ind_rec();
|
||||
size_t num_vecad_vec = play->num_vecad_vec_rec();
|
||||
Vector_set vecad_sparsity;
|
||||
vecad_sparsity.resize(num_vecad_vec, limit);
|
||||
pod_vector<size_t> vecad_ind;
|
||||
if( num_vecad_vec > 0 )
|
||||
{ size_t length;
|
||||
vecad_ind.extend(num_vecad_ind);
|
||||
j = 0;
|
||||
for(i = 0; i < num_vecad_vec; i++)
|
||||
{ // length of this VecAD
|
||||
length = play->GetVecInd(j);
|
||||
// set to proper index for this VecAD
|
||||
vecad_ind[j] = i;
|
||||
for(k = 1; k <= length; k++)
|
||||
vecad_ind[j+k] = num_vecad_vec; // invalid index
|
||||
// start of next VecAD
|
||||
j += length + 1;
|
||||
}
|
||||
CPPAD_ASSERT_UNKNOWN( j == play->num_vec_ind_rec() );
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// user's atomic op calculator
|
||||
atomic_base<Base>* user_atom = CPPAD_NULL; // user's atomic op calculator
|
||||
//
|
||||
// work space used by UserOp.
|
||||
vector<Base> user_x; // parameters in x as integers
|
||||
vector<size_t> user_ix; // variable indices for argument vector
|
||||
vector<size_t> user_iy; // variable indices for result vector
|
||||
//
|
||||
// information set by forward_user (initialization to avoid warnings)
|
||||
size_t user_old=0, user_m=0, user_n=0, user_i=0, user_j=0;
|
||||
// information set by forward_user (necessary initialization)
|
||||
enum_user_state user_state = end_user; // proper initialization
|
||||
// ----------------------------------------------------------------------
|
||||
//
|
||||
// pointer to the beginning of the parameter vector
|
||||
// (used by atomic functions
|
||||
const Base* parameter = CPPAD_NULL;
|
||||
if( num_par > 0 )
|
||||
parameter = play->GetPar();
|
||||
//
|
||||
// Initialize
|
||||
play->reverse_start(op, arg, i_op, i_var);
|
||||
CPPAD_ASSERT_UNKNOWN( op == EndOp );
|
||||
# if CPPAD_REV_JAC_SWEEP_TRACE
|
||||
std::cout << std::endl;
|
||||
CppAD::vectorBool z_value(limit);
|
||||
# endif
|
||||
bool more_operators = true;
|
||||
while(more_operators)
|
||||
{ bool flag; // temporary for use in switch cases
|
||||
//
|
||||
// next op
|
||||
play->reverse_next(op, arg, i_op, i_var);
|
||||
# ifndef NDEBUG
|
||||
if( i_op <= n )
|
||||
{ CPPAD_ASSERT_UNKNOWN((op == InvOp) | (op == BeginOp));
|
||||
}
|
||||
else CPPAD_ASSERT_UNKNOWN((op != InvOp) & (op != BeginOp));
|
||||
# endif
|
||||
|
||||
// rest of information depends on the case
|
||||
switch( op )
|
||||
{
|
||||
case AbsOp:
|
||||
CPPAD_ASSERT_NARG_NRES(op, 1, 1);
|
||||
reverse_sparse_jacobian_unary_op(
|
||||
i_var, arg[0], var_sparsity
|
||||
);
|
||||
break;
|
||||
// -------------------------------------------------
|
||||
|
||||
case AddvvOp:
|
||||
CPPAD_ASSERT_NARG_NRES(op, 2, 1);
|
||||
reverse_sparse_jacobian_binary_op(
|
||||
i_var, arg, var_sparsity
|
||||
);
|
||||
break;
|
||||
// -------------------------------------------------
|
||||
|
||||
case AddpvOp:
|
||||
CPPAD_ASSERT_NARG_NRES(op, 2, 1);
|
||||
reverse_sparse_jacobian_unary_op(
|
||||
i_var, arg[1], var_sparsity
|
||||
);
|
||||
break;
|
||||
// -------------------------------------------------
|
||||
|
||||
case AcosOp:
|
||||
// sqrt(1 - x * x), acos(x)
|
||||
CPPAD_ASSERT_NARG_NRES(op, 1, 2);
|
||||
reverse_sparse_jacobian_unary_op(
|
||||
i_var, arg[0], var_sparsity
|
||||
);
|
||||
break;
|
||||
// -------------------------------------------------
|
||||
|
||||
# if CPPAD_USE_CPLUSPLUS_2011
|
||||
case AcoshOp:
|
||||
// sqrt(x * x - 1), acosh(x)
|
||||
CPPAD_ASSERT_NARG_NRES(op, 1, 2);
|
||||
reverse_sparse_jacobian_unary_op(
|
||||
i_var, arg[0], var_sparsity
|
||||
);
|
||||
break;
|
||||
# endif
|
||||
// -------------------------------------------------
|
||||
|
||||
case AsinOp:
|
||||
// sqrt(1 - x * x), asin(x)
|
||||
CPPAD_ASSERT_NARG_NRES(op, 1, 2);
|
||||
reverse_sparse_jacobian_unary_op(
|
||||
i_var, arg[0], var_sparsity
|
||||
);
|
||||
break;
|
||||
// -------------------------------------------------
|
||||
|
||||
# if CPPAD_USE_CPLUSPLUS_2011
|
||||
case AsinhOp:
|
||||
// sqrt(1 + x * x), asinh(x)
|
||||
CPPAD_ASSERT_NARG_NRES(op, 1, 2);
|
||||
reverse_sparse_jacobian_unary_op(
|
||||
i_var, arg[0], var_sparsity
|
||||
);
|
||||
break;
|
||||
# endif
|
||||
// -------------------------------------------------
|
||||
|
||||
case AtanOp:
|
||||
// 1 + x * x, atan(x)
|
||||
CPPAD_ASSERT_NARG_NRES(op, 1, 2);
|
||||
reverse_sparse_jacobian_unary_op(
|
||||
i_var, arg[0], var_sparsity
|
||||
);
|
||||
break;
|
||||
// -------------------------------------------------
|
||||
|
||||
# if CPPAD_USE_CPLUSPLUS_2011
|
||||
case AtanhOp:
|
||||
// 1 - x * x, atanh(x)
|
||||
CPPAD_ASSERT_NARG_NRES(op, 1, 2);
|
||||
reverse_sparse_jacobian_unary_op(
|
||||
i_var, arg[0], var_sparsity
|
||||
);
|
||||
break;
|
||||
# endif
|
||||
// -------------------------------------------------
|
||||
|
||||
case BeginOp:
|
||||
CPPAD_ASSERT_NARG_NRES(op, 1, 1);
|
||||
more_operators = false;
|
||||
break;
|
||||
// -------------------------------------------------
|
||||
|
||||
case CSkipOp:
|
||||
// CSkipOp has a variable number of arguments and
|
||||
// reverse_next thinks it one has one argument.
|
||||
// We must inform reverse_next of this special case.
|
||||
play->reverse_cskip(op, arg, i_op, i_var);
|
||||
break;
|
||||
// -------------------------------------------------
|
||||
|
||||
case CSumOp:
|
||||
// CSumOp has a variable number of arguments and
|
||||
// reverse_next thinks it one has one argument.
|
||||
// We must inform reverse_next of this special case.
|
||||
play->reverse_csum(op, arg, i_op, i_var);
|
||||
reverse_sparse_jacobian_csum_op(
|
||||
i_var, arg, var_sparsity
|
||||
);
|
||||
break;
|
||||
// -------------------------------------------------
|
||||
|
||||
case CExpOp:
|
||||
reverse_sparse_jacobian_cond_op(
|
||||
dependency, i_var, arg, num_par, var_sparsity
|
||||
);
|
||||
break;
|
||||
// ---------------------------------------------------
|
||||
|
||||
case CosOp:
|
||||
// sin(x), cos(x)
|
||||
CPPAD_ASSERT_NARG_NRES(op, 1, 2);
|
||||
reverse_sparse_jacobian_unary_op(
|
||||
i_var, arg[0], var_sparsity
|
||||
);
|
||||
break;
|
||||
// ---------------------------------------------------
|
||||
|
||||
case CoshOp:
|
||||
// sinh(x), cosh(x)
|
||||
CPPAD_ASSERT_NARG_NRES(op, 1, 2);
|
||||
reverse_sparse_jacobian_unary_op(
|
||||
i_var, arg[0], var_sparsity
|
||||
);
|
||||
break;
|
||||
// -------------------------------------------------
|
||||
|
||||
case DisOp:
|
||||
CPPAD_ASSERT_NARG_NRES(op, 2, 1);
|
||||
// derivative is identically zero but dependency is not
|
||||
if( dependency ) reverse_sparse_jacobian_unary_op(
|
||||
i_var, arg[1], var_sparsity
|
||||
);
|
||||
break;
|
||||
// -------------------------------------------------
|
||||
|
||||
case DivvvOp:
|
||||
CPPAD_ASSERT_NARG_NRES(op, 2, 1);
|
||||
reverse_sparse_jacobian_binary_op(
|
||||
i_var, arg, var_sparsity
|
||||
);
|
||||
break;
|
||||
// -------------------------------------------------
|
||||
|
||||
case DivpvOp:
|
||||
CPPAD_ASSERT_NARG_NRES(op, 2, 1);
|
||||
reverse_sparse_jacobian_unary_op(
|
||||
i_var, arg[1], var_sparsity
|
||||
);
|
||||
break;
|
||||
// -------------------------------------------------
|
||||
|
||||
case DivvpOp:
|
||||
CPPAD_ASSERT_NARG_NRES(op, 2, 1);
|
||||
reverse_sparse_jacobian_unary_op(
|
||||
i_var, arg[0], var_sparsity
|
||||
);
|
||||
break;
|
||||
// -------------------------------------------------
|
||||
|
||||
case ErfOp:
|
||||
// arg[1] is always the parameter 0
|
||||
// arg[0] is always the parameter 2 / sqrt(pi)
|
||||
CPPAD_ASSERT_NARG_NRES(op, 3, 5);
|
||||
reverse_sparse_jacobian_unary_op(
|
||||
i_var, arg[0], var_sparsity
|
||||
);
|
||||
break;
|
||||
// -------------------------------------------------
|
||||
|
||||
case ExpOp:
|
||||
CPPAD_ASSERT_NARG_NRES(op, 1, 1);
|
||||
reverse_sparse_jacobian_unary_op(
|
||||
i_var, arg[0], var_sparsity
|
||||
);
|
||||
break;
|
||||
// -------------------------------------------------
|
||||
|
||||
# if CPPAD_USE_CPLUSPLUS_2011
|
||||
case Expm1Op:
|
||||
CPPAD_ASSERT_NARG_NRES(op, 1, 1);
|
||||
reverse_sparse_jacobian_unary_op(
|
||||
i_var, arg[0], var_sparsity
|
||||
);
|
||||
break;
|
||||
# endif
|
||||
// -------------------------------------------------
|
||||
|
||||
case InvOp:
|
||||
CPPAD_ASSERT_NARG_NRES(op, 0, 1);
|
||||
break;
|
||||
// -------------------------------------------------
|
||||
|
||||
case LdpOp:
|
||||
reverse_sparse_jacobian_load_op(
|
||||
dependency,
|
||||
op,
|
||||
i_var,
|
||||
arg,
|
||||
num_vecad_ind,
|
||||
vecad_ind.data(),
|
||||
var_sparsity,
|
||||
vecad_sparsity
|
||||
);
|
||||
break;
|
||||
// -------------------------------------------------
|
||||
|
||||
case LdvOp:
|
||||
reverse_sparse_jacobian_load_op(
|
||||
dependency,
|
||||
op,
|
||||
i_var,
|
||||
arg,
|
||||
num_vecad_ind,
|
||||
vecad_ind.data(),
|
||||
var_sparsity,
|
||||
vecad_sparsity
|
||||
);
|
||||
break;
|
||||
// -------------------------------------------------
|
||||
|
||||
case EqpvOp:
|
||||
case EqvvOp:
|
||||
case LtpvOp:
|
||||
case LtvpOp:
|
||||
case LtvvOp:
|
||||
case LepvOp:
|
||||
case LevpOp:
|
||||
case LevvOp:
|
||||
case NepvOp:
|
||||
case NevvOp:
|
||||
CPPAD_ASSERT_NARG_NRES(op, 2, 0);
|
||||
break;
|
||||
// -------------------------------------------------
|
||||
|
||||
case LogOp:
|
||||
CPPAD_ASSERT_NARG_NRES(op, 1, 1);
|
||||
reverse_sparse_jacobian_unary_op(
|
||||
i_var, arg[0], var_sparsity
|
||||
);
|
||||
break;
|
||||
// -------------------------------------------------
|
||||
|
||||
# if CPPAD_USE_CPLUSPLUS_2011
|
||||
case Log1pOp:
|
||||
CPPAD_ASSERT_NARG_NRES(op, 1, 1);
|
||||
reverse_sparse_jacobian_unary_op(
|
||||
i_var, arg[0], var_sparsity
|
||||
);
|
||||
break;
|
||||
# endif
|
||||
// -------------------------------------------------
|
||||
|
||||
case MulpvOp:
|
||||
CPPAD_ASSERT_NARG_NRES(op, 2, 1);
|
||||
reverse_sparse_jacobian_unary_op(
|
||||
i_var, arg[1], var_sparsity
|
||||
);
|
||||
break;
|
||||
// -------------------------------------------------
|
||||
|
||||
case MulvvOp:
|
||||
CPPAD_ASSERT_NARG_NRES(op, 2, 1);
|
||||
reverse_sparse_jacobian_binary_op(
|
||||
i_var, arg, var_sparsity
|
||||
);
|
||||
break;
|
||||
// -------------------------------------------------
|
||||
|
||||
case ParOp:
|
||||
CPPAD_ASSERT_NARG_NRES(op, 1, 1);
|
||||
|
||||
break;
|
||||
// -------------------------------------------------
|
||||
|
||||
case PowvpOp:
|
||||
reverse_sparse_jacobian_unary_op(
|
||||
i_var, arg[0], var_sparsity
|
||||
);
|
||||
break;
|
||||
// -------------------------------------------------
|
||||
|
||||
case PowpvOp:
|
||||
CPPAD_ASSERT_NARG_NRES(op, 2, 3);
|
||||
reverse_sparse_jacobian_unary_op(
|
||||
i_var, arg[1], var_sparsity
|
||||
);
|
||||
break;
|
||||
// -------------------------------------------------
|
||||
|
||||
case PowvvOp:
|
||||
CPPAD_ASSERT_NARG_NRES(op, 2, 3);
|
||||
reverse_sparse_jacobian_binary_op(
|
||||
i_var, arg, var_sparsity
|
||||
);
|
||||
break;
|
||||
// -------------------------------------------------
|
||||
|
||||
case PriOp:
|
||||
CPPAD_ASSERT_NARG_NRES(op, 5, 0);
|
||||
break;
|
||||
// -------------------------------------------------
|
||||
|
||||
case SignOp:
|
||||
CPPAD_ASSERT_NARG_NRES(op, 1, 1);
|
||||
// derivative is identically zero but dependency is not
|
||||
if( dependency ) reverse_sparse_jacobian_unary_op(
|
||||
i_var, arg[0], var_sparsity
|
||||
);
|
||||
break;
|
||||
// -------------------------------------------------
|
||||
|
||||
case SinOp:
|
||||
// cos(x), sin(x)
|
||||
CPPAD_ASSERT_NARG_NRES(op, 1, 2);
|
||||
reverse_sparse_jacobian_unary_op(
|
||||
i_var, arg[0], var_sparsity
|
||||
);
|
||||
break;
|
||||
// -------------------------------------------------
|
||||
|
||||
case SinhOp:
|
||||
// cosh(x), sinh(x)
|
||||
CPPAD_ASSERT_NARG_NRES(op, 1, 2);
|
||||
reverse_sparse_jacobian_unary_op(
|
||||
i_var, arg[0], var_sparsity
|
||||
);
|
||||
break;
|
||||
// -------------------------------------------------
|
||||
|
||||
case SqrtOp:
|
||||
CPPAD_ASSERT_NARG_NRES(op, 1, 1);
|
||||
reverse_sparse_jacobian_unary_op(
|
||||
i_var, arg[0], var_sparsity
|
||||
);
|
||||
break;
|
||||
// -------------------------------------------------
|
||||
|
||||
case StppOp:
|
||||
// does not affect sparsity or dependency when both are parameters
|
||||
CPPAD_ASSERT_NARG_NRES(op, 3, 0);
|
||||
break;
|
||||
// -------------------------------------------------
|
||||
|
||||
case StpvOp:
|
||||
reverse_sparse_jacobian_store_op(
|
||||
dependency,
|
||||
op,
|
||||
arg,
|
||||
num_vecad_ind,
|
||||
vecad_ind.data(),
|
||||
var_sparsity,
|
||||
vecad_sparsity
|
||||
);
|
||||
break;
|
||||
// -------------------------------------------------
|
||||
|
||||
case StvpOp:
|
||||
CPPAD_ASSERT_NARG_NRES(op, 3, 0);
|
||||
// storing a parameter only affects dependency
|
||||
reverse_sparse_jacobian_store_op(
|
||||
dependency,
|
||||
op,
|
||||
arg,
|
||||
num_vecad_ind,
|
||||
vecad_ind.data(),
|
||||
var_sparsity,
|
||||
vecad_sparsity
|
||||
);
|
||||
break;
|
||||
// -------------------------------------------------
|
||||
|
||||
case StvvOp:
|
||||
reverse_sparse_jacobian_store_op(
|
||||
dependency,
|
||||
op,
|
||||
arg,
|
||||
num_vecad_ind,
|
||||
vecad_ind.data(),
|
||||
var_sparsity,
|
||||
vecad_sparsity
|
||||
);
|
||||
break;
|
||||
// -------------------------------------------------
|
||||
|
||||
case SubvvOp:
|
||||
CPPAD_ASSERT_NARG_NRES(op, 2, 1);
|
||||
reverse_sparse_jacobian_binary_op(
|
||||
i_var, arg, var_sparsity
|
||||
);
|
||||
break;
|
||||
// -------------------------------------------------
|
||||
|
||||
case SubpvOp:
|
||||
CPPAD_ASSERT_NARG_NRES(op, 2, 1);
|
||||
reverse_sparse_jacobian_unary_op(
|
||||
i_var, arg[1], var_sparsity
|
||||
);
|
||||
break;
|
||||
// -------------------------------------------------
|
||||
|
||||
case SubvpOp:
|
||||
CPPAD_ASSERT_NARG_NRES(op, 2, 1);
|
||||
reverse_sparse_jacobian_unary_op(
|
||||
i_var, arg[0], var_sparsity
|
||||
);
|
||||
break;
|
||||
// -------------------------------------------------
|
||||
|
||||
case TanOp:
|
||||
// tan(x)^2, tan(x)
|
||||
CPPAD_ASSERT_NARG_NRES(op, 1, 2);
|
||||
reverse_sparse_jacobian_unary_op(
|
||||
i_var, arg[0], var_sparsity
|
||||
);
|
||||
break;
|
||||
// -------------------------------------------------
|
||||
|
||||
case TanhOp:
|
||||
// tanh(x)^2, tanh(x)
|
||||
CPPAD_ASSERT_NARG_NRES(op, 1, 2);
|
||||
reverse_sparse_jacobian_unary_op(
|
||||
i_var, arg[0], var_sparsity
|
||||
);
|
||||
break;
|
||||
// -------------------------------------------------
|
||||
|
||||
case UserOp:
|
||||
CPPAD_ASSERT_UNKNOWN(
|
||||
user_state == start_user || user_state == end_user
|
||||
);
|
||||
flag = user_state == end_user;
|
||||
user_atom = play->reverse_user(op, user_state,
|
||||
user_old, user_m, user_n, user_i, user_j
|
||||
);
|
||||
if( flag )
|
||||
{ // start of user atomic operation sequence
|
||||
user_x.resize( user_n );
|
||||
user_ix.resize( user_n );
|
||||
user_iy.resize( user_m );
|
||||
}
|
||||
else
|
||||
{ // end of users atomic operation sequence
|
||||
user_atom->set_old(user_old);
|
||||
user_atom->rev_sparse_jac(
|
||||
user_x, user_ix, user_iy, var_sparsity
|
||||
);
|
||||
}
|
||||
break;
|
||||
|
||||
case UsrapOp:
|
||||
CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < num_par );
|
||||
play->reverse_user(op, user_state,
|
||||
user_old, user_m, user_n, user_i, user_j
|
||||
);
|
||||
// argument parameter value
|
||||
user_x[user_j] = parameter[arg[0]];
|
||||
// special variable index used for parameters
|
||||
user_ix[user_j] = 0;
|
||||
//
|
||||
break;
|
||||
|
||||
case UsravOp:
|
||||
CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) <= i_var );
|
||||
CPPAD_ASSERT_UNKNOWN( 0 < arg[0] );
|
||||
play->reverse_user(op, user_state,
|
||||
user_old, user_m, user_n, user_i, user_j
|
||||
);
|
||||
// argument variables not available during sparsity calculations
|
||||
user_x[user_j] = CppAD::numeric_limits<Base>::quiet_NaN();
|
||||
// variable index for this argument
|
||||
user_ix[user_j] = arg[0];
|
||||
break;
|
||||
|
||||
case UsrrpOp:
|
||||
// parameter result in an atomic operation sequence
|
||||
CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < num_par );
|
||||
play->reverse_user(op, user_state,
|
||||
user_old, user_m, user_n, user_i, user_j
|
||||
);
|
||||
// special variable index used for parameters
|
||||
user_iy[user_i] = 0;
|
||||
break;
|
||||
|
||||
case UsrrvOp:
|
||||
play->reverse_user(op, user_state,
|
||||
user_old, user_m, user_n, user_i, user_j
|
||||
);
|
||||
// variable index for this result
|
||||
user_iy[user_i] = i_var;
|
||||
break;
|
||||
// -------------------------------------------------
|
||||
|
||||
case ZmulpvOp:
|
||||
CPPAD_ASSERT_NARG_NRES(op, 2, 1);
|
||||
reverse_sparse_jacobian_unary_op(
|
||||
i_var, arg[1], var_sparsity
|
||||
);
|
||||
break;
|
||||
// -------------------------------------------------
|
||||
|
||||
case ZmulvpOp:
|
||||
CPPAD_ASSERT_NARG_NRES(op, 2, 1);
|
||||
reverse_sparse_jacobian_unary_op(
|
||||
i_var, arg[0], var_sparsity
|
||||
);
|
||||
break;
|
||||
// -------------------------------------------------
|
||||
|
||||
case ZmulvvOp:
|
||||
CPPAD_ASSERT_NARG_NRES(op, 2, 1);
|
||||
reverse_sparse_jacobian_binary_op(
|
||||
i_var, arg, var_sparsity
|
||||
);
|
||||
break;
|
||||
// -------------------------------------------------
|
||||
|
||||
default:
|
||||
CPPAD_ASSERT_UNKNOWN(0);
|
||||
}
|
||||
# if CPPAD_REV_JAC_SWEEP_TRACE
|
||||
for(j = 0; j < limit; j++)
|
||||
z_value[j] = false;
|
||||
typename Vector_set::const_iterator itr(var_sparsity, i_var);
|
||||
j = *itr;
|
||||
while( j < limit )
|
||||
{ z_value[j] = true;
|
||||
j = *(++itr);
|
||||
}
|
||||
printOp(
|
||||
std::cout,
|
||||
play,
|
||||
i_op,
|
||||
i_var,
|
||||
op,
|
||||
arg
|
||||
);
|
||||
// Note that sparsity for UsrrvOp are computed before call to
|
||||
// atomic function so no need to delay printing (as in forward mode)
|
||||
if( NumRes(op) > 0 && op != BeginOp ) printOpResult(
|
||||
std::cout,
|
||||
0,
|
||||
(CppAD::vectorBool *) CPPAD_NULL,
|
||||
1,
|
||||
&z_value
|
||||
);
|
||||
std::cout << std::endl;
|
||||
}
|
||||
std::cout << std::endl;
|
||||
# else
|
||||
}
|
||||
# endif
|
||||
// values corresponding to BeginOp
|
||||
CPPAD_ASSERT_UNKNOWN( i_op == 0 );
|
||||
CPPAD_ASSERT_UNKNOWN( i_var == 0 );
|
||||
|
||||
return;
|
||||
}
|
||||
} } // END_CPPAD_LOCAL_NAMESPACE
|
||||
|
||||
// preprocessor symbols that are local to this file
|
||||
# undef CPPAD_REV_JAC_SWEEP_TRACE
|
||||
# undef CPPAD_ATOMIC_CALL
|
||||
|
||||
# endif
|
||||
@@ -0,0 +1,824 @@
|
||||
// $Id: reverse_sweep.hpp 3853 2016-12-14 14:40:11Z bradbell $
|
||||
# ifndef CPPAD_LOCAL_REVERSE_SWEEP_HPP
|
||||
# define CPPAD_LOCAL_REVERSE_SWEEP_HPP
|
||||
|
||||
/* --------------------------------------------------------------------------
|
||||
CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-16 Bradley M. Bell
|
||||
|
||||
CppAD is distributed under multiple licenses. This distribution is under
|
||||
the terms of the
|
||||
Eclipse Public License Version 1.0.
|
||||
|
||||
A copy of this license is included in the COPYING file of this distribution.
|
||||
Please visit http://www.coin-or.org/CppAD/ for information on other licenses.
|
||||
-------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
namespace CppAD { namespace local { // BEGIN_CPPAD_LOCAL_NAMESPACE
|
||||
/*!
|
||||
\file reverse_sweep.hpp
|
||||
Compute derivatives of arbitrary order Taylor coefficients.
|
||||
*/
|
||||
|
||||
/*
|
||||
\def CPPAD_ATOMIC_CALL
|
||||
This avoids warnings when NDEBUG is defined and user_ok is not used.
|
||||
If \c NDEBUG is defined, this resolves to
|
||||
\code
|
||||
user_atom->reverse
|
||||
\endcode
|
||||
otherwise, it respolves to
|
||||
\code
|
||||
user_ok = user_atom->reverse
|
||||
\endcode
|
||||
This maco is undefined at the end of this file to facillitate is
|
||||
use with a different definition in other files.
|
||||
*/
|
||||
# ifdef NDEBUG
|
||||
# define CPPAD_ATOMIC_CALL user_atom->reverse
|
||||
# else
|
||||
# define CPPAD_ATOMIC_CALL user_ok = user_atom->reverse
|
||||
# endif
|
||||
|
||||
/*!
|
||||
\def CPPAD_REVERSE_SWEEP_TRACE
|
||||
This value is either zero or one.
|
||||
Zero is the normal operational value.
|
||||
If it is one, a trace of every reverse_sweep computation is printed.
|
||||
*/
|
||||
# define CPPAD_REVERSE_SWEEP_TRACE 0
|
||||
|
||||
/*!
|
||||
Compute derivative of arbitrary order forward mode Taylor coefficients.
|
||||
|
||||
\tparam Base
|
||||
base type for the operator; i.e., this operation sequence was recorded
|
||||
using AD< \a Base > and computations by this routine are done using type
|
||||
\a Base.
|
||||
|
||||
\param d
|
||||
is the highest order Taylor coefficients that
|
||||
we are computing the derivative of.
|
||||
|
||||
\param n
|
||||
is the number of independent variables on the tape.
|
||||
|
||||
\param numvar
|
||||
is the total number of variables on the tape.
|
||||
This is also equal to the number of rows in the matrix \a Taylor; i.e.,
|
||||
play->num_var_rec().
|
||||
|
||||
\param play
|
||||
The information stored in \a play
|
||||
is a recording of the operations corresponding to the function
|
||||
\f[
|
||||
F : {\bf R}^n \rightarrow {\bf R}^m
|
||||
\f]
|
||||
where \f$ n \f$ is the number of independent variables and
|
||||
\f$ m \f$ is the number of dependent variables.
|
||||
We define \f$ u^{(k)} \f$ as the value of <code>x_k</code> in the previous call
|
||||
of the form
|
||||
<code>
|
||||
f.Forward(k, x_k)
|
||||
</code>
|
||||
We define
|
||||
\f$ X : {\bf R}^{n \times d} \rightarrow {\bf R}^n \f$ by
|
||||
\f[
|
||||
X(t, u) = u^{(0)} + u^{(1)} t + \cdots + u^{(d)} t^d
|
||||
\f]
|
||||
We define
|
||||
\f$ Y : {\bf R}^{n \times d} \rightarrow {\bf R}^m \f$ by
|
||||
\f[
|
||||
Y(t, u) = F[ X(t, u) ]
|
||||
\f]
|
||||
We define the function
|
||||
\f$ W : {\bf R}^{n \times d} \rightarrow {\bf R} \f$ by
|
||||
\f[
|
||||
W(u)
|
||||
=
|
||||
\sum_{k=0}^{d} ( w^{(k)} )^{\rm T}
|
||||
\frac{1}{k !} \frac{\partial^k}{\partial t^k} Y(0, u)
|
||||
\f]
|
||||
(The matrix \f$ w \in {\bf R}^m \f$,
|
||||
is defined below under the heading Partial.)
|
||||
Note that the scale factor 1 / k converts
|
||||
the k-th partial derivative to the k-th order Taylor coefficient.
|
||||
This routine computes the derivative of \f$ W(u) \f$
|
||||
with respect to all the Taylor coefficients
|
||||
\f$ u^{(k)} \f$ for \f$ k = 0 , ... , d \f$.
|
||||
\n
|
||||
\n
|
||||
The object \a play is effectly constant.
|
||||
There is an exception to this,
|
||||
while palying back the tape
|
||||
the object \a play holds information about the current location
|
||||
with in the tape and this changes during palyback.
|
||||
|
||||
\param J
|
||||
Is the number of columns in the coefficient matrix \a Taylor.
|
||||
This must be greater than or equal \a d + 1.
|
||||
|
||||
\param Taylor
|
||||
For i = 1 , ... , \a numvar, and for k = 0 , ... , \a d,
|
||||
\a Taylor [ i * J + k ]
|
||||
is the k-th order Taylor coefficient corresponding to
|
||||
variable with index i on the tape.
|
||||
The value \f$ u \in {\bf R}^{n \times d} \f$,
|
||||
at which the derivative is computed,
|
||||
is defined by
|
||||
\f$ u_j^{(k)} \f$ = \a Taylor [ j * J + k ]
|
||||
for j = 1 , ... , \a n, and for k = 0 , ... , \a d.
|
||||
|
||||
\param K
|
||||
Is the number of columns in the partial derivative matrix \a Partial.
|
||||
It must be greater than or equal \a d + 1.
|
||||
|
||||
\param Partial
|
||||
\b Input:
|
||||
The last \f$ m \f$ rows of \a Partial are inputs.
|
||||
The matrix \f$ w \f$, used to define \f$ W(u) \f$,
|
||||
is specified by these rows.
|
||||
For i = 0 , ... , m - 1,
|
||||
for k = 0 , ... , d,
|
||||
<code>Partial [ (numvar - m + i ) * K + k ] = w[i,k]</code>.
|
||||
\n
|
||||
\n
|
||||
\b Temporary:
|
||||
For i = n+1 , ... , \a numvar - 1 and for k = 0 , ... , d,
|
||||
the value of \a Partial [ i * K + k ] is used for temporary work space
|
||||
and its output value is not defined.
|
||||
\n
|
||||
\n
|
||||
\b Output:
|
||||
For j = 1 , ... , n and for k = 0 , ... , d,
|
||||
\a Partial [ j * K + k ]
|
||||
is the partial derivative of \f$ W( u ) \f$ with
|
||||
respect to \f$ u_j^{(k)} \f$.
|
||||
|
||||
\param cskip_op
|
||||
Is a vector with size play->num_op_rec().
|
||||
If cskip_op[i] is true, the operator index i in the recording
|
||||
does not affect any of the dependent variable (given the value
|
||||
of the independent variables).
|
||||
Note that all the operators in an atomic function call are skipped as a block,
|
||||
so only the last UserOp fore each call needs to have cskip_op[i] true.
|
||||
|
||||
\param var_by_load_op
|
||||
is a vector with size play->num_load_op_rec().
|
||||
Is the variable index corresponding to each load instruction.
|
||||
In the case where the index is zero,
|
||||
the instruction corresponds to a parameter (not variable).
|
||||
|
||||
\par Assumptions
|
||||
The first operator on the tape is a BeginOp,
|
||||
and the next \a n operators are InvOp operations for the
|
||||
corresponding independent variables.
|
||||
*/
|
||||
template <class Base>
|
||||
void ReverseSweep(
|
||||
size_t d,
|
||||
size_t n,
|
||||
size_t numvar,
|
||||
local::player<Base>* play,
|
||||
size_t J,
|
||||
const Base* Taylor,
|
||||
size_t K,
|
||||
Base* Partial,
|
||||
bool* cskip_op,
|
||||
const pod_vector<addr_t>& var_by_load_op
|
||||
)
|
||||
{
|
||||
OpCode op;
|
||||
size_t i_op;
|
||||
size_t i_var;
|
||||
|
||||
const addr_t* arg = CPPAD_NULL;
|
||||
|
||||
// check numvar argument
|
||||
CPPAD_ASSERT_UNKNOWN( play->num_var_rec() == numvar );
|
||||
CPPAD_ASSERT_UNKNOWN( numvar > 0 );
|
||||
|
||||
// length of the parameter vector (used by CppAD assert macros)
|
||||
const size_t num_par = play->num_par_rec();
|
||||
|
||||
// pointer to the beginning of the parameter vector
|
||||
const Base* parameter = CPPAD_NULL;
|
||||
if( num_par > 0 )
|
||||
parameter = play->GetPar();
|
||||
|
||||
// work space used by UserOp.
|
||||
const size_t user_k = d; // highest order we are differentiating
|
||||
const size_t user_k1 = d+1; // number of orders for this calculation
|
||||
vector<size_t> user_ix; // variable indices for argument vector
|
||||
vector<Base> user_tx; // argument vector Taylor coefficients
|
||||
vector<Base> user_ty; // result vector Taylor coefficients
|
||||
vector<Base> user_px; // partials w.r.t argument vector
|
||||
vector<Base> user_py; // partials w.r.t. result vector
|
||||
//
|
||||
atomic_base<Base>* user_atom = CPPAD_NULL; // user's atomic op calculator
|
||||
# ifndef NDEBUG
|
||||
bool user_ok = false; // atomic op return value
|
||||
# endif
|
||||
//
|
||||
// information defined by forward_user
|
||||
size_t user_old=0, user_m=0, user_n=0, user_i=0, user_j=0;
|
||||
enum_user_state user_state = end_user; // proper initialization
|
||||
|
||||
// temporary indices
|
||||
size_t j, ell;
|
||||
|
||||
// Initialize
|
||||
play->reverse_start(op, arg, i_op, i_var);
|
||||
CPPAD_ASSERT_UNKNOWN( op == EndOp );
|
||||
# if CPPAD_REVERSE_SWEEP_TRACE
|
||||
std::cout << std::endl;
|
||||
# endif
|
||||
bool more_operators = true;
|
||||
while(more_operators)
|
||||
{ bool flag; // temporary for use in switch cases
|
||||
//
|
||||
// next op
|
||||
play->reverse_next(op, arg, i_op, i_var);
|
||||
CPPAD_ASSERT_UNKNOWN((i_op > n) | (op == InvOp) | (op == BeginOp));
|
||||
CPPAD_ASSERT_UNKNOWN((i_op <= n) | (op != InvOp) | (op != BeginOp));
|
||||
CPPAD_ASSERT_UNKNOWN( i_op < play->num_op_rec() );
|
||||
|
||||
// check if we are skipping this operation
|
||||
while( cskip_op[i_op] )
|
||||
{ switch(op)
|
||||
{ case CSumOp:
|
||||
// CSumOp has a variable number of arguments
|
||||
play->reverse_csum(op, arg, i_op, i_var);
|
||||
break;
|
||||
|
||||
case CSkipOp:
|
||||
// CSkip has a variable number of arguments
|
||||
play->reverse_cskip(op, arg, i_op, i_var);
|
||||
break;
|
||||
|
||||
case UserOp:
|
||||
{ // skip all operations in this user atomic call
|
||||
CPPAD_ASSERT_UNKNOWN( user_state == end_user );
|
||||
play->reverse_user(op, user_state,
|
||||
user_old, user_m, user_n, user_i, user_j
|
||||
);
|
||||
size_t n_skip = user_m + user_n + 1;
|
||||
for(size_t i = 0; i < n_skip; i++)
|
||||
{ play->reverse_next(op, arg, i_op, i_var);
|
||||
play->reverse_user(op, user_state,
|
||||
user_old, user_m, user_n, user_i, user_j
|
||||
);
|
||||
}
|
||||
CPPAD_ASSERT_UNKNOWN( user_state == end_user );
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
play->reverse_next(op, arg, i_op, i_var);
|
||||
CPPAD_ASSERT_UNKNOWN( i_op < play->num_op_rec() );
|
||||
}
|
||||
|
||||
// rest of informaiton depends on the case
|
||||
# if CPPAD_REVERSE_SWEEP_TRACE
|
||||
if( op == CSumOp )
|
||||
{ // CSumOp has a variable number of arguments
|
||||
play->reverse_csum(op, arg, i_op, i_var);
|
||||
}
|
||||
if( op == CSkipOp )
|
||||
{ // CSkip has a variable number of arguments
|
||||
play->reverse_cskip(op, arg, i_op, i_var);
|
||||
}
|
||||
size_t i_tmp = i_var;
|
||||
const Base* Z_tmp = Taylor + i_var * J;
|
||||
const Base* pZ_tmp = Partial + i_var * K;
|
||||
printOp(
|
||||
std::cout,
|
||||
play,
|
||||
i_op,
|
||||
i_tmp,
|
||||
op,
|
||||
arg
|
||||
);
|
||||
if( NumRes(op) > 0 && op != BeginOp ) printOpResult(
|
||||
std::cout,
|
||||
d + 1,
|
||||
Z_tmp,
|
||||
d + 1,
|
||||
pZ_tmp
|
||||
);
|
||||
std::cout << std::endl;
|
||||
# endif
|
||||
switch( op )
|
||||
{
|
||||
|
||||
case AbsOp:
|
||||
reverse_abs_op(
|
||||
d, i_var, arg[0], J, Taylor, K, Partial
|
||||
);
|
||||
break;
|
||||
// --------------------------------------------------
|
||||
|
||||
case AcosOp:
|
||||
// sqrt(1 - x * x), acos(x)
|
||||
CPPAD_ASSERT_UNKNOWN( i_var < numvar );
|
||||
reverse_acos_op(
|
||||
d, i_var, arg[0], J, Taylor, K, Partial
|
||||
);
|
||||
break;
|
||||
// --------------------------------------------------
|
||||
|
||||
# if CPPAD_USE_CPLUSPLUS_2011
|
||||
case AcoshOp:
|
||||
// sqrt(x * x - 1), acosh(x)
|
||||
CPPAD_ASSERT_UNKNOWN( i_var < numvar );
|
||||
reverse_acosh_op(
|
||||
d, i_var, arg[0], J, Taylor, K, Partial
|
||||
);
|
||||
break;
|
||||
# endif
|
||||
// --------------------------------------------------
|
||||
|
||||
case AddvvOp:
|
||||
reverse_addvv_op(
|
||||
d, i_var, arg, parameter, J, Taylor, K, Partial
|
||||
);
|
||||
break;
|
||||
// --------------------------------------------------
|
||||
|
||||
case AddpvOp:
|
||||
CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < num_par );
|
||||
reverse_addpv_op(
|
||||
d, i_var, arg, parameter, J, Taylor, K, Partial
|
||||
);
|
||||
break;
|
||||
// --------------------------------------------------
|
||||
|
||||
case AsinOp:
|
||||
// sqrt(1 - x * x), asin(x)
|
||||
CPPAD_ASSERT_UNKNOWN( i_var < numvar );
|
||||
reverse_asin_op(
|
||||
d, i_var, arg[0], J, Taylor, K, Partial
|
||||
);
|
||||
break;
|
||||
// --------------------------------------------------
|
||||
|
||||
# if CPPAD_USE_CPLUSPLUS_2011
|
||||
case AsinhOp:
|
||||
// sqrt(1 + x * x), asinh(x)
|
||||
CPPAD_ASSERT_UNKNOWN( i_var < numvar );
|
||||
reverse_asinh_op(
|
||||
d, i_var, arg[0], J, Taylor, K, Partial
|
||||
);
|
||||
break;
|
||||
# endif
|
||||
// --------------------------------------------------
|
||||
|
||||
case AtanOp:
|
||||
// 1 + x * x, atan(x)
|
||||
CPPAD_ASSERT_UNKNOWN( i_var < numvar );
|
||||
reverse_atan_op(
|
||||
d, i_var, arg[0], J, Taylor, K, Partial
|
||||
);
|
||||
break;
|
||||
// -------------------------------------------------
|
||||
|
||||
# if CPPAD_USE_CPLUSPLUS_2011
|
||||
case AtanhOp:
|
||||
// 1 - x * x, atanh(x)
|
||||
CPPAD_ASSERT_UNKNOWN( i_var < numvar );
|
||||
reverse_atanh_op(
|
||||
d, i_var, arg[0], J, Taylor, K, Partial
|
||||
);
|
||||
break;
|
||||
# endif
|
||||
// -------------------------------------------------
|
||||
|
||||
case BeginOp:
|
||||
CPPAD_ASSERT_NARG_NRES(op, 1, 1);
|
||||
more_operators = false;
|
||||
break;
|
||||
// --------------------------------------------------
|
||||
|
||||
case CSkipOp:
|
||||
// CSkipOp has a variable number of arguments and
|
||||
// forward_next thinks it one has one argument.
|
||||
// we must inform reverse_next of this special case.
|
||||
# if ! CPPAD_REVERSE_SWEEP_TRACE
|
||||
play->reverse_cskip(op, arg, i_op, i_var);
|
||||
# endif
|
||||
break;
|
||||
// -------------------------------------------------
|
||||
|
||||
case CSumOp:
|
||||
// CSumOp has a variable number of arguments and
|
||||
// reverse_next thinks it one has one argument.
|
||||
// We must inform reverse_next of this special case.
|
||||
# if ! CPPAD_REVERSE_SWEEP_TRACE
|
||||
play->reverse_csum(op, arg, i_op, i_var);
|
||||
# endif
|
||||
reverse_csum_op(
|
||||
d, i_var, arg, K, Partial
|
||||
);
|
||||
// end of a cummulative summation
|
||||
break;
|
||||
// -------------------------------------------------
|
||||
|
||||
case CExpOp:
|
||||
reverse_cond_op(
|
||||
d,
|
||||
i_var,
|
||||
arg,
|
||||
num_par,
|
||||
parameter,
|
||||
J,
|
||||
Taylor,
|
||||
K,
|
||||
Partial
|
||||
);
|
||||
break;
|
||||
// --------------------------------------------------
|
||||
|
||||
case CosOp:
|
||||
CPPAD_ASSERT_UNKNOWN( i_var < numvar );
|
||||
reverse_cos_op(
|
||||
d, i_var, arg[0], J, Taylor, K, Partial
|
||||
);
|
||||
break;
|
||||
// --------------------------------------------------
|
||||
|
||||
case CoshOp:
|
||||
CPPAD_ASSERT_UNKNOWN( i_var < numvar );
|
||||
reverse_cosh_op(
|
||||
d, i_var, arg[0], J, Taylor, K, Partial
|
||||
);
|
||||
break;
|
||||
// --------------------------------------------------
|
||||
|
||||
case DisOp:
|
||||
// Derivative of discrete operation is zero so no
|
||||
// contribution passes through this operation.
|
||||
break;
|
||||
// --------------------------------------------------
|
||||
|
||||
case DivvvOp:
|
||||
reverse_divvv_op(
|
||||
d, i_var, arg, parameter, J, Taylor, K, Partial
|
||||
);
|
||||
break;
|
||||
// --------------------------------------------------
|
||||
|
||||
case DivpvOp:
|
||||
CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < num_par );
|
||||
reverse_divpv_op(
|
||||
d, i_var, arg, parameter, J, Taylor, K, Partial
|
||||
);
|
||||
break;
|
||||
// --------------------------------------------------
|
||||
|
||||
case DivvpOp:
|
||||
CPPAD_ASSERT_UNKNOWN( size_t(arg[1]) < num_par );
|
||||
reverse_divvp_op(
|
||||
d, i_var, arg, parameter, J, Taylor, K, Partial
|
||||
);
|
||||
break;
|
||||
// --------------------------------------------------
|
||||
|
||||
# if CPPAD_USE_CPLUSPLUS_2011
|
||||
case ErfOp:
|
||||
reverse_erf_op(
|
||||
d, i_var, arg, parameter, J, Taylor, K, Partial
|
||||
);
|
||||
break;
|
||||
# endif
|
||||
// --------------------------------------------------
|
||||
|
||||
case ExpOp:
|
||||
reverse_exp_op(
|
||||
d, i_var, arg[0], J, Taylor, K, Partial
|
||||
);
|
||||
break;
|
||||
// --------------------------------------------------
|
||||
|
||||
# if CPPAD_USE_CPLUSPLUS_2011
|
||||
case Expm1Op:
|
||||
reverse_expm1_op(
|
||||
d, i_var, arg[0], J, Taylor, K, Partial
|
||||
);
|
||||
break;
|
||||
# endif
|
||||
// --------------------------------------------------
|
||||
|
||||
case InvOp:
|
||||
break;
|
||||
// --------------------------------------------------
|
||||
|
||||
case LdpOp:
|
||||
reverse_load_op(
|
||||
op, d, i_var, arg, J, Taylor, K, Partial, var_by_load_op.data()
|
||||
);
|
||||
break;
|
||||
// -------------------------------------------------
|
||||
|
||||
case LdvOp:
|
||||
reverse_load_op(
|
||||
op, d, i_var, arg, J, Taylor, K, Partial, var_by_load_op.data()
|
||||
);
|
||||
break;
|
||||
// --------------------------------------------------
|
||||
|
||||
case EqpvOp:
|
||||
case EqvvOp:
|
||||
case LtpvOp:
|
||||
case LtvpOp:
|
||||
case LtvvOp:
|
||||
case LepvOp:
|
||||
case LevpOp:
|
||||
case LevvOp:
|
||||
case NepvOp:
|
||||
case NevvOp:
|
||||
break;
|
||||
// -------------------------------------------------
|
||||
|
||||
case LogOp:
|
||||
reverse_log_op(
|
||||
d, i_var, arg[0], J, Taylor, K, Partial
|
||||
);
|
||||
break;
|
||||
// --------------------------------------------------
|
||||
|
||||
# if CPPAD_USE_CPLUSPLUS_2011
|
||||
case Log1pOp:
|
||||
reverse_log1p_op(
|
||||
d, i_var, arg[0], J, Taylor, K, Partial
|
||||
);
|
||||
break;
|
||||
# endif
|
||||
// --------------------------------------------------
|
||||
|
||||
case MulpvOp:
|
||||
CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < num_par );
|
||||
reverse_mulpv_op(
|
||||
d, i_var, arg, parameter, J, Taylor, K, Partial
|
||||
);
|
||||
break;
|
||||
// --------------------------------------------------
|
||||
|
||||
case MulvvOp:
|
||||
reverse_mulvv_op(
|
||||
d, i_var, arg, parameter, J, Taylor, K, Partial
|
||||
);
|
||||
break;
|
||||
// --------------------------------------------------
|
||||
|
||||
case ParOp:
|
||||
break;
|
||||
// --------------------------------------------------
|
||||
|
||||
case PowvpOp:
|
||||
CPPAD_ASSERT_UNKNOWN( size_t(arg[1]) < num_par );
|
||||
reverse_powvp_op(
|
||||
d, i_var, arg, parameter, J, Taylor, K, Partial
|
||||
);
|
||||
break;
|
||||
// -------------------------------------------------
|
||||
|
||||
case PowpvOp:
|
||||
CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < num_par );
|
||||
reverse_powpv_op(
|
||||
d, i_var, arg, parameter, J, Taylor, K, Partial
|
||||
);
|
||||
break;
|
||||
// -------------------------------------------------
|
||||
|
||||
case PowvvOp:
|
||||
reverse_powvv_op(
|
||||
d, i_var, arg, parameter, J, Taylor, K, Partial
|
||||
);
|
||||
break;
|
||||
// --------------------------------------------------
|
||||
|
||||
case PriOp:
|
||||
// no result so nothing to do
|
||||
break;
|
||||
// --------------------------------------------------
|
||||
|
||||
case SignOp:
|
||||
CPPAD_ASSERT_UNKNOWN( i_var < numvar );
|
||||
reverse_sign_op(
|
||||
d, i_var, arg[0], J, Taylor, K, Partial
|
||||
);
|
||||
break;
|
||||
// -------------------------------------------------
|
||||
|
||||
case SinOp:
|
||||
CPPAD_ASSERT_UNKNOWN( i_var < numvar );
|
||||
reverse_sin_op(
|
||||
d, i_var, arg[0], J, Taylor, K, Partial
|
||||
);
|
||||
break;
|
||||
// -------------------------------------------------
|
||||
|
||||
case SinhOp:
|
||||
CPPAD_ASSERT_UNKNOWN( i_var < numvar );
|
||||
reverse_sinh_op(
|
||||
d, i_var, arg[0], J, Taylor, K, Partial
|
||||
);
|
||||
break;
|
||||
// --------------------------------------------------
|
||||
|
||||
case SqrtOp:
|
||||
reverse_sqrt_op(
|
||||
d, i_var, arg[0], J, Taylor, K, Partial
|
||||
);
|
||||
break;
|
||||
// --------------------------------------------------
|
||||
|
||||
case StppOp:
|
||||
break;
|
||||
// --------------------------------------------------
|
||||
|
||||
case StpvOp:
|
||||
break;
|
||||
// -------------------------------------------------
|
||||
|
||||
case StvpOp:
|
||||
break;
|
||||
// -------------------------------------------------
|
||||
|
||||
case StvvOp:
|
||||
break;
|
||||
// --------------------------------------------------
|
||||
|
||||
case SubvvOp:
|
||||
reverse_subvv_op(
|
||||
d, i_var, arg, parameter, J, Taylor, K, Partial
|
||||
);
|
||||
break;
|
||||
// --------------------------------------------------
|
||||
|
||||
case SubpvOp:
|
||||
CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < num_par );
|
||||
reverse_subpv_op(
|
||||
d, i_var, arg, parameter, J, Taylor, K, Partial
|
||||
);
|
||||
break;
|
||||
// --------------------------------------------------
|
||||
|
||||
case SubvpOp:
|
||||
CPPAD_ASSERT_UNKNOWN( size_t(arg[1]) < num_par );
|
||||
reverse_subvp_op(
|
||||
d, i_var, arg, parameter, J, Taylor, K, Partial
|
||||
);
|
||||
break;
|
||||
// -------------------------------------------------
|
||||
|
||||
case TanOp:
|
||||
CPPAD_ASSERT_UNKNOWN( i_var < numvar );
|
||||
reverse_tan_op(
|
||||
d, i_var, arg[0], J, Taylor, K, Partial
|
||||
);
|
||||
break;
|
||||
// -------------------------------------------------
|
||||
|
||||
case TanhOp:
|
||||
CPPAD_ASSERT_UNKNOWN( i_var < numvar );
|
||||
reverse_tanh_op(
|
||||
d, i_var, arg[0], J, Taylor, K, Partial
|
||||
);
|
||||
break;
|
||||
// --------------------------------------------------
|
||||
|
||||
case UserOp:
|
||||
// start or end an atomic operation sequence
|
||||
flag = user_state == end_user;
|
||||
user_atom = play->reverse_user(op, user_state,
|
||||
user_old, user_m, user_n, user_i, user_j
|
||||
);
|
||||
if( flag )
|
||||
{ user_ix.resize(user_n);
|
||||
if(user_tx.size() != user_n * user_k1)
|
||||
{ user_tx.resize(user_n * user_k1);
|
||||
user_px.resize(user_n * user_k1);
|
||||
}
|
||||
if(user_ty.size() != user_m * user_k1)
|
||||
{ user_ty.resize(user_m * user_k1);
|
||||
user_py.resize(user_m * user_k1);
|
||||
}
|
||||
}
|
||||
else
|
||||
{ // call users function for this operation
|
||||
user_atom->set_old(user_old);
|
||||
CPPAD_ATOMIC_CALL(
|
||||
user_k, user_tx, user_ty, user_px, user_py
|
||||
);
|
||||
# ifndef NDEBUG
|
||||
if( ! user_ok )
|
||||
{ std::string msg =
|
||||
user_atom->afun_name()
|
||||
+ ": atomic_base.reverse: returned false";
|
||||
CPPAD_ASSERT_KNOWN(false, msg.c_str() );
|
||||
}
|
||||
# endif
|
||||
for(j = 0; j < user_n; j++) if( user_ix[j] > 0 )
|
||||
{ for(ell = 0; ell < user_k1; ell++)
|
||||
Partial[user_ix[j] * K + ell] +=
|
||||
user_px[j * user_k1 + ell];
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case UsrapOp:
|
||||
// parameter argument in an atomic operation sequence
|
||||
CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < num_par );
|
||||
play->reverse_user(op, user_state,
|
||||
user_old, user_m, user_n, user_i, user_j
|
||||
);
|
||||
user_ix[user_j] = 0;
|
||||
user_tx[user_j * user_k1 + 0] = parameter[ arg[0]];
|
||||
for(ell = 1; ell < user_k1; ell++)
|
||||
user_tx[user_j * user_k1 + ell] = Base(0.);
|
||||
break;
|
||||
|
||||
case UsravOp:
|
||||
// variable argument in an atomic operation sequence
|
||||
CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) <= i_var );
|
||||
CPPAD_ASSERT_UNKNOWN( 0 < arg[0] );
|
||||
play->reverse_user(op, user_state,
|
||||
user_old, user_m, user_n, user_i, user_j
|
||||
);
|
||||
user_ix[user_j] = arg[0];
|
||||
for(ell = 0; ell < user_k1; ell++)
|
||||
user_tx[user_j*user_k1 + ell] = Taylor[ arg[0] * J + ell];
|
||||
break;
|
||||
|
||||
case UsrrpOp:
|
||||
// parameter result in an atomic operation sequence
|
||||
CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < num_par );
|
||||
play->reverse_user(op, user_state,
|
||||
user_old, user_m, user_n, user_i, user_j
|
||||
);
|
||||
for(ell = 0; ell < user_k1; ell++)
|
||||
{ user_py[user_i * user_k1 + ell] = Base(0.);
|
||||
user_ty[user_i * user_k1 + ell] = Base(0.);
|
||||
}
|
||||
user_ty[user_i * user_k1 + 0] = parameter[ arg[0] ];
|
||||
break;
|
||||
|
||||
case UsrrvOp:
|
||||
// variable result in an atomic operation sequence
|
||||
play->reverse_user(op, user_state,
|
||||
user_old, user_m, user_n, user_i, user_j
|
||||
);
|
||||
for(ell = 0; ell < user_k1; ell++)
|
||||
{ user_py[user_i * user_k1 + ell] =
|
||||
Partial[i_var * K + ell];
|
||||
user_ty[user_i * user_k1 + ell] =
|
||||
Taylor[i_var * J + ell];
|
||||
}
|
||||
break;
|
||||
// ------------------------------------------------------------
|
||||
|
||||
case ZmulpvOp:
|
||||
CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < num_par );
|
||||
reverse_zmulpv_op(
|
||||
d, i_var, arg, parameter, J, Taylor, K, Partial
|
||||
);
|
||||
break;
|
||||
// --------------------------------------------------
|
||||
|
||||
case ZmulvpOp:
|
||||
CPPAD_ASSERT_UNKNOWN( size_t(arg[1]) < num_par );
|
||||
reverse_zmulvp_op(
|
||||
d, i_var, arg, parameter, J, Taylor, K, Partial
|
||||
);
|
||||
break;
|
||||
// --------------------------------------------------
|
||||
|
||||
case ZmulvvOp:
|
||||
reverse_zmulvv_op(
|
||||
d, i_var, arg, parameter, J, Taylor, K, Partial
|
||||
);
|
||||
break;
|
||||
// --------------------------------------------------
|
||||
|
||||
default:
|
||||
CPPAD_ASSERT_UNKNOWN(false);
|
||||
}
|
||||
}
|
||||
# if CPPAD_REVERSE_SWEEP_TRACE
|
||||
std::cout << std::endl;
|
||||
# endif
|
||||
// values corresponding to BeginOp
|
||||
CPPAD_ASSERT_UNKNOWN( i_op == 0 );
|
||||
CPPAD_ASSERT_UNKNOWN( i_var == 0 );
|
||||
}
|
||||
|
||||
} } // END_CPPAD_LOCAL_NAMESPACE
|
||||
|
||||
// preprocessor symbols that are local to this file
|
||||
# undef CPPAD_REVERSE_SWEEP_TRACE
|
||||
# undef CPPAD_ATOMIC_CALL
|
||||
|
||||
# endif
|
||||
@@ -0,0 +1,67 @@
|
||||
// $Id$
|
||||
# ifndef CPPAD_LOCAL_SET_GET_IN_PARALLEL_HPP
|
||||
# define CPPAD_LOCAL_SET_GET_IN_PARALLEL_HPP
|
||||
|
||||
/* --------------------------------------------------------------------------
|
||||
CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-16 Bradley M. Bell
|
||||
|
||||
CppAD is distributed under multiple licenses. This distribution is under
|
||||
the terms of the
|
||||
Eclipse Public License Version 1.0.
|
||||
|
||||
A copy of this license is included in the COPYING file of this distribution.
|
||||
Please visit http://www.coin-or.org/CppAD/ for information on other licenses.
|
||||
-------------------------------------------------------------------------- */
|
||||
|
||||
# include <cassert>
|
||||
# include <cppad/configure.hpp>
|
||||
namespace CppAD { namespace local { // BEGIN_CPPAD_LOCAL_NAMESPACE
|
||||
|
||||
/*!
|
||||
\file set_get_in_parallel.hpp
|
||||
File used to set and get user in_parallel routine.
|
||||
*/
|
||||
/*!
|
||||
Set and call the routine that determine if we are in parallel execution mode.
|
||||
|
||||
\return
|
||||
value retuned by most recent setting for in_parallel_new.
|
||||
If set is true,
|
||||
or the most recent setting is CPPAD_NULL (its initial value),
|
||||
the return value is false.
|
||||
Otherwise the function corresponding to the most recent setting
|
||||
is called and its value returned by set_get_in_parallel.
|
||||
|
||||
\param in_parallel_new [in]
|
||||
If set is false, in_parallel_new it is not used.
|
||||
Otherwise, the current value of in_parallel_new becomes the
|
||||
most recent setting for in_parallel_user.
|
||||
|
||||
\param set
|
||||
If set is true, then parallel_new is becomes the most
|
||||
recent setting for this set_get_in_parallel.
|
||||
In this case, it is assumed that we are currently in sequential execution mode.
|
||||
*/
|
||||
static bool set_get_in_parallel(
|
||||
bool (*in_parallel_new)(void) ,
|
||||
bool set = false )
|
||||
{ static bool (*in_parallel_user)(void) = CPPAD_NULL;
|
||||
|
||||
if( set )
|
||||
{ in_parallel_user = in_parallel_new;
|
||||
// Doing a raw assert in this case because set_get_in_parallel is used
|
||||
// by ErrorHandler and hence cannot use ErrorHandler.
|
||||
// CPPAD_ASSERT_UNKNOWN( in_parallel_user() == false )
|
||||
assert(in_parallel_user == CPPAD_NULL || in_parallel_user() == false);
|
||||
return false;
|
||||
}
|
||||
//
|
||||
if( in_parallel_user == CPPAD_NULL )
|
||||
return false;
|
||||
//
|
||||
return in_parallel_user();
|
||||
}
|
||||
|
||||
} } // END_CPPAD_LOCAL_NAMESPACE
|
||||
|
||||
# endif
|
||||
+154
@@ -0,0 +1,154 @@
|
||||
// $Id: sign_op.hpp 3865 2017-01-19 01:57:55Z bradbell $
|
||||
# ifndef CPPAD_LOCAL_SIGN_OP_HPP
|
||||
# define CPPAD_LOCAL_SIGN_OP_HPP
|
||||
|
||||
/* --------------------------------------------------------------------------
|
||||
CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-17 Bradley M. Bell
|
||||
|
||||
CppAD is distributed under multiple licenses. This distribution is under
|
||||
the terms of the
|
||||
Eclipse Public License Version 1.0.
|
||||
|
||||
A copy of this license is included in the COPYING file of this distribution.
|
||||
Please visit http://www.coin-or.org/CppAD/ for information on other licenses.
|
||||
-------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
namespace CppAD { namespace local { // BEGIN_CPPAD_LOCAL_NAMESPACE
|
||||
/*!
|
||||
\file sign_op.hpp
|
||||
Forward and reverse mode calculations for z = sign(x).
|
||||
*/
|
||||
|
||||
/*!
|
||||
Compute forward mode Taylor coefficient for result of op = SignOp.
|
||||
|
||||
The C++ source code corresponding to this operation is
|
||||
\verbatim
|
||||
z = sign(x)
|
||||
\endverbatim
|
||||
|
||||
\copydetails CppAD::local::forward_unary1_op
|
||||
*/
|
||||
template <class Base>
|
||||
inline void forward_sign_op(
|
||||
size_t p ,
|
||||
size_t q ,
|
||||
size_t i_z ,
|
||||
size_t i_x ,
|
||||
size_t cap_order ,
|
||||
Base* taylor )
|
||||
{
|
||||
// check assumptions
|
||||
CPPAD_ASSERT_UNKNOWN( NumArg(SignOp) == 1 );
|
||||
CPPAD_ASSERT_UNKNOWN( NumRes(SignOp) == 1 );
|
||||
CPPAD_ASSERT_UNKNOWN( q < cap_order );
|
||||
CPPAD_ASSERT_UNKNOWN( p <= q );
|
||||
|
||||
// Taylor coefficients corresponding to argument and result
|
||||
Base* x = taylor + i_x * cap_order;
|
||||
Base* z = taylor + i_z * cap_order;
|
||||
|
||||
if( p == 0 )
|
||||
{ z[0] = sign(x[0]);
|
||||
p++;
|
||||
}
|
||||
for(size_t j = p; j <= q; j++)
|
||||
z[j] = Base(0.);
|
||||
}
|
||||
/*!
|
||||
Multiple direction forward mode Taylor coefficient for op = SignOp.
|
||||
|
||||
The C++ source code corresponding to this operation is
|
||||
\verbatim
|
||||
z = sign(x)
|
||||
\endverbatim
|
||||
|
||||
\copydetails CppAD::local::forward_unary1_op_dir
|
||||
*/
|
||||
template <class Base>
|
||||
inline void forward_sign_op_dir(
|
||||
size_t q ,
|
||||
size_t r ,
|
||||
size_t i_z ,
|
||||
size_t i_x ,
|
||||
size_t cap_order ,
|
||||
Base* taylor )
|
||||
{
|
||||
// check assumptions
|
||||
CPPAD_ASSERT_UNKNOWN( NumArg(SignOp) == 1 );
|
||||
CPPAD_ASSERT_UNKNOWN( NumRes(SignOp) == 1 );
|
||||
CPPAD_ASSERT_UNKNOWN( 0 < q );
|
||||
CPPAD_ASSERT_UNKNOWN( q < cap_order );
|
||||
|
||||
// Taylor coefficients corresponding to argument and result
|
||||
size_t num_taylor_per_var = (cap_order-1) * r + 1;
|
||||
size_t m = (q - 1) * r + 1;
|
||||
Base* z = taylor + i_z * num_taylor_per_var;
|
||||
|
||||
for(size_t ell = 0; ell < r; ell++)
|
||||
z[m+ell] = Base(0.);
|
||||
}
|
||||
|
||||
/*!
|
||||
Compute zero order forward mode Taylor coefficient for result of op = SignOp.
|
||||
|
||||
The C++ source code corresponding to this operation is
|
||||
\verbatim
|
||||
z = sign(x)
|
||||
\endverbatim
|
||||
|
||||
\copydetails CppAD::local::forward_unary1_op_0
|
||||
*/
|
||||
template <class Base>
|
||||
inline void forward_sign_op_0(
|
||||
size_t i_z ,
|
||||
size_t i_x ,
|
||||
size_t cap_order ,
|
||||
Base* taylor )
|
||||
{
|
||||
|
||||
// check assumptions
|
||||
CPPAD_ASSERT_UNKNOWN( NumArg(SignOp) == 1 );
|
||||
CPPAD_ASSERT_UNKNOWN( NumRes(SignOp) == 1 );
|
||||
CPPAD_ASSERT_UNKNOWN( 0 < cap_order );
|
||||
|
||||
// Taylor coefficients corresponding to argument and result
|
||||
Base x0 = *(taylor + i_x * cap_order);
|
||||
Base* z = taylor + i_z * cap_order;
|
||||
|
||||
z[0] = sign(x0);
|
||||
}
|
||||
/*!
|
||||
Compute reverse mode partial derivatives for result of op = SignOp.
|
||||
|
||||
The C++ source code corresponding to this operation is
|
||||
\verbatim
|
||||
z = sign(x)
|
||||
\endverbatim
|
||||
|
||||
\copydetails CppAD::local::reverse_unary1_op
|
||||
*/
|
||||
|
||||
template <class Base>
|
||||
inline void reverse_sign_op(
|
||||
size_t d ,
|
||||
size_t i_z ,
|
||||
size_t i_x ,
|
||||
size_t cap_order ,
|
||||
const Base* taylor ,
|
||||
size_t nc_partial ,
|
||||
Base* partial )
|
||||
{
|
||||
// check assumptions
|
||||
CPPAD_ASSERT_UNKNOWN( NumArg(SignOp) == 1 );
|
||||
CPPAD_ASSERT_UNKNOWN( NumRes(SignOp) == 1 );
|
||||
CPPAD_ASSERT_UNKNOWN( d < cap_order );
|
||||
CPPAD_ASSERT_UNKNOWN( d < nc_partial );
|
||||
|
||||
// nothing to do because partials of sign are zero
|
||||
return;
|
||||
}
|
||||
|
||||
} } // END_CPPAD_LOCAL_NAMESPACE
|
||||
# endif
|
||||
+240
@@ -0,0 +1,240 @@
|
||||
# ifndef CPPAD_LOCAL_SIN_OP_HPP
|
||||
# define CPPAD_LOCAL_SIN_OP_HPP
|
||||
|
||||
/* --------------------------------------------------------------------------
|
||||
CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-17 Bradley M. Bell
|
||||
|
||||
CppAD is distributed under multiple licenses. This distribution is under
|
||||
the terms of the
|
||||
Eclipse Public License Version 1.0.
|
||||
|
||||
A copy of this license is included in the COPYING file of this distribution.
|
||||
Please visit http://www.coin-or.org/CppAD/ for information on other licenses.
|
||||
-------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
namespace CppAD { namespace local { // BEGIN_CPPAD_LOCAL_NAMESPACE
|
||||
/*!
|
||||
\file sin_op.hpp
|
||||
Forward and reverse mode calculations for z = sin(x).
|
||||
*/
|
||||
|
||||
|
||||
/*!
|
||||
Compute forward mode Taylor coefficient for result of op = SinOp.
|
||||
|
||||
The C++ source code corresponding to this operation is
|
||||
\verbatim
|
||||
z = sin(x)
|
||||
\endverbatim
|
||||
The auxillary result is
|
||||
\verbatim
|
||||
y = cos(x)
|
||||
\endverbatim
|
||||
The value of y, and its derivatives, are computed along with the value
|
||||
and derivatives of z.
|
||||
|
||||
\copydetails CppAD::local::forward_unary2_op
|
||||
*/
|
||||
template <class Base>
|
||||
inline void forward_sin_op(
|
||||
size_t p ,
|
||||
size_t q ,
|
||||
size_t i_z ,
|
||||
size_t i_x ,
|
||||
size_t cap_order ,
|
||||
Base* taylor )
|
||||
{
|
||||
// check assumptions
|
||||
CPPAD_ASSERT_UNKNOWN( NumArg(SinOp) == 1 );
|
||||
CPPAD_ASSERT_UNKNOWN( NumRes(SinOp) == 2 );
|
||||
CPPAD_ASSERT_UNKNOWN( q < cap_order );
|
||||
CPPAD_ASSERT_UNKNOWN( p <= q );
|
||||
|
||||
// Taylor coefficients corresponding to argument and result
|
||||
Base* x = taylor + i_x * cap_order;
|
||||
Base* s = taylor + i_z * cap_order;
|
||||
Base* c = s - cap_order;
|
||||
|
||||
// rest of this routine is identical for the following cases:
|
||||
// forward_sin_op, forward_cos_op, forward_sinh_op, forward_cosh_op.
|
||||
// (except that there is a sign difference for the hyperbolic case).
|
||||
size_t k;
|
||||
if( p == 0 )
|
||||
{ s[0] = sin( x[0] );
|
||||
c[0] = cos( x[0] );
|
||||
p++;
|
||||
}
|
||||
for(size_t j = p; j <= q; j++)
|
||||
{
|
||||
s[j] = Base(0.0);
|
||||
c[j] = Base(0.0);
|
||||
for(k = 1; k <= j; k++)
|
||||
{ s[j] += Base(double(k)) * x[k] * c[j-k];
|
||||
c[j] -= Base(double(k)) * x[k] * s[j-k];
|
||||
}
|
||||
s[j] /= Base(double(j));
|
||||
c[j] /= Base(double(j));
|
||||
}
|
||||
}
|
||||
/*!
|
||||
Compute forward mode Taylor coefficient for result of op = SinOp.
|
||||
|
||||
The C++ source code corresponding to this operation is
|
||||
\verbatim
|
||||
z = sin(x)
|
||||
\endverbatim
|
||||
The auxillary result is
|
||||
\verbatim
|
||||
y = cos(x)
|
||||
\endverbatim
|
||||
The value of y, and its derivatives, are computed along with the value
|
||||
and derivatives of z.
|
||||
|
||||
\copydetails CppAD::local::forward_unary2_op_dir
|
||||
*/
|
||||
template <class Base>
|
||||
inline void forward_sin_op_dir(
|
||||
size_t q ,
|
||||
size_t r ,
|
||||
size_t i_z ,
|
||||
size_t i_x ,
|
||||
size_t cap_order ,
|
||||
Base* taylor )
|
||||
{
|
||||
// check assumptions
|
||||
CPPAD_ASSERT_UNKNOWN( NumArg(SinOp) == 1 );
|
||||
CPPAD_ASSERT_UNKNOWN( NumRes(SinOp) == 2 );
|
||||
CPPAD_ASSERT_UNKNOWN( 0 < q );
|
||||
CPPAD_ASSERT_UNKNOWN( q < cap_order );
|
||||
|
||||
// Taylor coefficients corresponding to argument and result
|
||||
size_t num_taylor_per_var = (cap_order-1) * r + 1;
|
||||
Base* x = taylor + i_x * num_taylor_per_var;
|
||||
Base* s = taylor + i_z * num_taylor_per_var;
|
||||
Base* c = s - num_taylor_per_var;
|
||||
|
||||
|
||||
// rest of this routine is identical for the following cases:
|
||||
// forward_sin_op, forward_cos_op, forward_sinh_op, forward_cosh_op
|
||||
// (except that there is a sign difference for the hyperbolic case).
|
||||
size_t m = (q-1) * r + 1;
|
||||
for(size_t ell = 0; ell < r; ell++)
|
||||
{ s[m+ell] = Base(double(q)) * x[m + ell] * c[0];
|
||||
c[m+ell] = - Base(double(q)) * x[m + ell] * s[0];
|
||||
for(size_t k = 1; k < q; k++)
|
||||
{ s[m+ell] += Base(double(k)) * x[(k-1)*r+1+ell] * c[(q-k-1)*r+1+ell];
|
||||
c[m+ell] -= Base(double(k)) * x[(k-1)*r+1+ell] * s[(q-k-1)*r+1+ell];
|
||||
}
|
||||
s[m+ell] /= Base(double(q));
|
||||
c[m+ell] /= Base(double(q));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
Compute zero order forward mode Taylor coefficient for result of op = SinOp.
|
||||
|
||||
The C++ source code corresponding to this operation is
|
||||
\verbatim
|
||||
z = sin(x)
|
||||
\endverbatim
|
||||
The auxillary result is
|
||||
\verbatim
|
||||
y = cos(x)
|
||||
\endverbatim
|
||||
The value of y is computed along with the value of z.
|
||||
|
||||
\copydetails CppAD::local::forward_unary2_op_0
|
||||
*/
|
||||
template <class Base>
|
||||
inline void forward_sin_op_0(
|
||||
size_t i_z ,
|
||||
size_t i_x ,
|
||||
size_t cap_order ,
|
||||
Base* taylor )
|
||||
{
|
||||
// check assumptions
|
||||
CPPAD_ASSERT_UNKNOWN( NumArg(SinOp) == 1 );
|
||||
CPPAD_ASSERT_UNKNOWN( NumRes(SinOp) == 2 );
|
||||
CPPAD_ASSERT_UNKNOWN( 0 < cap_order );
|
||||
|
||||
// Taylor coefficients corresponding to argument and result
|
||||
Base* x = taylor + i_x * cap_order;
|
||||
Base* s = taylor + i_z * cap_order; // called z in documentation
|
||||
Base* c = s - cap_order; // called y in documentation
|
||||
|
||||
s[0] = sin( x[0] );
|
||||
c[0] = cos( x[0] );
|
||||
}
|
||||
|
||||
/*!
|
||||
Compute reverse mode partial derivatives for result of op = SinOp.
|
||||
|
||||
The C++ source code corresponding to this operation is
|
||||
\verbatim
|
||||
z = sin(x)
|
||||
\endverbatim
|
||||
The auxillary result is
|
||||
\verbatim
|
||||
y = cos(x)
|
||||
\endverbatim
|
||||
The value of y is computed along with the value of z.
|
||||
|
||||
\copydetails CppAD::local::reverse_unary2_op
|
||||
*/
|
||||
|
||||
template <class Base>
|
||||
inline void reverse_sin_op(
|
||||
size_t d ,
|
||||
size_t i_z ,
|
||||
size_t i_x ,
|
||||
size_t cap_order ,
|
||||
const Base* taylor ,
|
||||
size_t nc_partial ,
|
||||
Base* partial )
|
||||
{
|
||||
// check assumptions
|
||||
CPPAD_ASSERT_UNKNOWN( NumArg(SinOp) == 1 );
|
||||
CPPAD_ASSERT_UNKNOWN( NumRes(SinOp) == 2 );
|
||||
CPPAD_ASSERT_UNKNOWN( d < cap_order );
|
||||
CPPAD_ASSERT_UNKNOWN( d < nc_partial );
|
||||
|
||||
// Taylor coefficients and partials corresponding to argument
|
||||
const Base* x = taylor + i_x * cap_order;
|
||||
Base* px = partial + i_x * nc_partial;
|
||||
|
||||
// Taylor coefficients and partials corresponding to first result
|
||||
const Base* s = taylor + i_z * cap_order; // called z in doc
|
||||
Base* ps = partial + i_z * nc_partial;
|
||||
|
||||
// Taylor coefficients and partials corresponding to auxillary result
|
||||
const Base* c = s - cap_order; // called y in documentation
|
||||
Base* pc = ps - nc_partial;
|
||||
|
||||
|
||||
// rest of this routine is identical for the following cases:
|
||||
// reverse_sin_op, reverse_cos_op, reverse_sinh_op, reverse_cosh_op.
|
||||
size_t j = d;
|
||||
size_t k;
|
||||
while(j)
|
||||
{
|
||||
ps[j] /= Base(double(j));
|
||||
pc[j] /= Base(double(j));
|
||||
for(k = 1; k <= j; k++)
|
||||
{
|
||||
px[k] += Base(double(k)) * azmul(ps[j], c[j-k]);
|
||||
px[k] -= Base(double(k)) * azmul(pc[j], s[j-k]);
|
||||
|
||||
ps[j-k] -= Base(double(k)) * azmul(pc[j], x[k]);
|
||||
pc[j-k] += Base(double(k)) * azmul(ps[j], x[k]);
|
||||
|
||||
}
|
||||
--j;
|
||||
}
|
||||
px[0] += azmul(ps[0], c[0]);
|
||||
px[0] -= azmul(pc[0], s[0]);
|
||||
}
|
||||
|
||||
} } // END_CPPAD_LOCAL_NAMESPACE
|
||||
# endif
|
||||
+239
@@ -0,0 +1,239 @@
|
||||
# ifndef CPPAD_LOCAL_SINH_OP_HPP
|
||||
# define CPPAD_LOCAL_SINH_OP_HPP
|
||||
|
||||
/* --------------------------------------------------------------------------
|
||||
CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-17 Bradley M. Bell
|
||||
|
||||
CppAD is distributed under multiple licenses. This distribution is under
|
||||
the terms of the
|
||||
Eclipse Public License Version 1.0.
|
||||
|
||||
A copy of this license is included in the COPYING file of this distribution.
|
||||
Please visit http://www.coin-or.org/CppAD/ for information on other licenses.
|
||||
-------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
namespace CppAD { namespace local { // BEGIN_CPPAD_LOCAL_NAMESPACE
|
||||
/*!
|
||||
\file sinh_op.hpp
|
||||
Forward and reverse mode calculations for z = sinh(x).
|
||||
*/
|
||||
|
||||
|
||||
/*!
|
||||
Compute forward mode Taylor coefficient for result of op = SinhOp.
|
||||
|
||||
The C++ source code corresponding to this operation is
|
||||
\verbatim
|
||||
z = sinh(x)
|
||||
\endverbatim
|
||||
The auxillary result is
|
||||
\verbatim
|
||||
y = cosh(x)
|
||||
\endverbatim
|
||||
The value of y, and its derivatives, are computed along with the value
|
||||
and derivatives of z.
|
||||
|
||||
\copydetails CppAD::local::forward_unary2_op
|
||||
*/
|
||||
template <class Base>
|
||||
inline void forward_sinh_op(
|
||||
size_t p ,
|
||||
size_t q ,
|
||||
size_t i_z ,
|
||||
size_t i_x ,
|
||||
size_t cap_order ,
|
||||
Base* taylor )
|
||||
{
|
||||
// check assumptions
|
||||
CPPAD_ASSERT_UNKNOWN( NumArg(SinhOp) == 1 );
|
||||
CPPAD_ASSERT_UNKNOWN( NumRes(SinhOp) == 2 );
|
||||
CPPAD_ASSERT_UNKNOWN( q < cap_order );
|
||||
CPPAD_ASSERT_UNKNOWN( p <= q );
|
||||
|
||||
// Taylor coefficients corresponding to argument and result
|
||||
Base* x = taylor + i_x * cap_order;
|
||||
Base* s = taylor + i_z * cap_order;
|
||||
Base* c = s - cap_order;
|
||||
|
||||
|
||||
// rest of this routine is identical for the following cases:
|
||||
// forward_sin_op, forward_cos_op, forward_sinh_op, forward_cosh_op
|
||||
// (except that there is a sign difference for hyperbolic case).
|
||||
size_t k;
|
||||
if( p == 0 )
|
||||
{ s[0] = sinh( x[0] );
|
||||
c[0] = cosh( x[0] );
|
||||
p++;
|
||||
}
|
||||
for(size_t j = p; j <= q; j++)
|
||||
{
|
||||
s[j] = Base(0.0);
|
||||
c[j] = Base(0.0);
|
||||
for(k = 1; k <= j; k++)
|
||||
{ s[j] += Base(double(k)) * x[k] * c[j-k];
|
||||
c[j] += Base(double(k)) * x[k] * s[j-k];
|
||||
}
|
||||
s[j] /= Base(double(j));
|
||||
c[j] /= Base(double(j));
|
||||
}
|
||||
}
|
||||
/*!
|
||||
Compute forward mode Taylor coefficient for result of op = SinhOp.
|
||||
|
||||
The C++ source code corresponding to this operation is
|
||||
\verbatim
|
||||
z = sinh(x)
|
||||
\endverbatim
|
||||
The auxillary result is
|
||||
\verbatim
|
||||
y = cosh(x)
|
||||
\endverbatim
|
||||
The value of y, and its derivatives, are computed along with the value
|
||||
and derivatives of z.
|
||||
|
||||
\copydetails CppAD::local::forward_unary2_op_dir
|
||||
*/
|
||||
template <class Base>
|
||||
inline void forward_sinh_op_dir(
|
||||
size_t q ,
|
||||
size_t r ,
|
||||
size_t i_z ,
|
||||
size_t i_x ,
|
||||
size_t cap_order ,
|
||||
Base* taylor )
|
||||
{
|
||||
// check assumptions
|
||||
CPPAD_ASSERT_UNKNOWN( NumArg(SinhOp) == 1 );
|
||||
CPPAD_ASSERT_UNKNOWN( NumRes(SinhOp) == 2 );
|
||||
CPPAD_ASSERT_UNKNOWN( 0 < q );
|
||||
CPPAD_ASSERT_UNKNOWN( q < cap_order );
|
||||
|
||||
// Taylor coefficients corresponding to argument and result
|
||||
size_t num_taylor_per_var = (cap_order-1) * r + 1;
|
||||
Base* x = taylor + i_x * num_taylor_per_var;
|
||||
Base* s = taylor + i_z * num_taylor_per_var;
|
||||
Base* c = s - num_taylor_per_var;
|
||||
|
||||
|
||||
// rest of this routine is identical for the following cases:
|
||||
// forward_sin_op, forward_cos_op, forward_sinh_op, forward_cosh_op
|
||||
// (except that there is a sign difference for the hyperbolic case).
|
||||
size_t m = (q-1) * r + 1;
|
||||
for(size_t ell = 0; ell < r; ell++)
|
||||
{ s[m+ell] = Base(double(q)) * x[m + ell] * c[0];
|
||||
c[m+ell] = Base(double(q)) * x[m + ell] * s[0];
|
||||
for(size_t k = 1; k < q; k++)
|
||||
{ s[m+ell] += Base(double(k)) * x[(k-1)*r+1+ell] * c[(q-k-1)*r+1+ell];
|
||||
c[m+ell] += Base(double(k)) * x[(k-1)*r+1+ell] * s[(q-k-1)*r+1+ell];
|
||||
}
|
||||
s[m+ell] /= Base(double(q));
|
||||
c[m+ell] /= Base(double(q));
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
Compute zero order forward mode Taylor coefficient for result of op = SinhOp.
|
||||
|
||||
The C++ source code corresponding to this operation is
|
||||
\verbatim
|
||||
z = sinh(x)
|
||||
\endverbatim
|
||||
The auxillary result is
|
||||
\verbatim
|
||||
y = cosh(x)
|
||||
\endverbatim
|
||||
The value of y is computed along with the value of z.
|
||||
|
||||
\copydetails CppAD::local::forward_unary2_op_0
|
||||
*/
|
||||
template <class Base>
|
||||
inline void forward_sinh_op_0(
|
||||
size_t i_z ,
|
||||
size_t i_x ,
|
||||
size_t cap_order ,
|
||||
Base* taylor )
|
||||
{
|
||||
// check assumptions
|
||||
CPPAD_ASSERT_UNKNOWN( NumArg(SinhOp) == 1 );
|
||||
CPPAD_ASSERT_UNKNOWN( NumRes(SinhOp) == 2 );
|
||||
CPPAD_ASSERT_UNKNOWN( 0 < cap_order );
|
||||
|
||||
// Taylor coefficients corresponding to argument and result
|
||||
Base* x = taylor + i_x * cap_order;
|
||||
Base* s = taylor + i_z * cap_order; // called z in documentation
|
||||
Base* c = s - cap_order; // called y in documentation
|
||||
|
||||
s[0] = sinh( x[0] );
|
||||
c[0] = cosh( x[0] );
|
||||
}
|
||||
/*!
|
||||
Compute reverse mode partial derivatives for result of op = SinhOp.
|
||||
|
||||
The C++ source code corresponding to this operation is
|
||||
\verbatim
|
||||
z = sinh(x)
|
||||
\endverbatim
|
||||
The auxillary result is
|
||||
\verbatim
|
||||
y = cosh(x)
|
||||
\endverbatim
|
||||
The value of y is computed along with the value of z.
|
||||
|
||||
\copydetails CppAD::local::reverse_unary2_op
|
||||
*/
|
||||
|
||||
template <class Base>
|
||||
inline void reverse_sinh_op(
|
||||
size_t d ,
|
||||
size_t i_z ,
|
||||
size_t i_x ,
|
||||
size_t cap_order ,
|
||||
const Base* taylor ,
|
||||
size_t nc_partial ,
|
||||
Base* partial )
|
||||
{
|
||||
// check assumptions
|
||||
CPPAD_ASSERT_UNKNOWN( NumArg(SinhOp) == 1 );
|
||||
CPPAD_ASSERT_UNKNOWN( NumRes(SinhOp) == 2 );
|
||||
CPPAD_ASSERT_UNKNOWN( d < cap_order );
|
||||
CPPAD_ASSERT_UNKNOWN( d < nc_partial );
|
||||
|
||||
// Taylor coefficients and partials corresponding to argument
|
||||
const Base* x = taylor + i_x * cap_order;
|
||||
Base* px = partial + i_x * nc_partial;
|
||||
|
||||
// Taylor coefficients and partials corresponding to first result
|
||||
const Base* s = taylor + i_z * cap_order; // called z in doc
|
||||
Base* ps = partial + i_z * nc_partial;
|
||||
|
||||
// Taylor coefficients and partials corresponding to auxillary result
|
||||
const Base* c = s - cap_order; // called y in documentation
|
||||
Base* pc = ps - nc_partial;
|
||||
|
||||
|
||||
// rest of this routine is identical for the following cases:
|
||||
// reverse_sin_op, reverse_cos_op, reverse_sinh_op, reverse_cosh_op.
|
||||
size_t j = d;
|
||||
size_t k;
|
||||
while(j)
|
||||
{
|
||||
ps[j] /= Base(double(j));
|
||||
pc[j] /= Base(double(j));
|
||||
for(k = 1; k <= j; k++)
|
||||
{
|
||||
px[k] += Base(double(k)) * azmul(ps[j], c[j-k]);
|
||||
px[k] += Base(double(k)) * azmul(pc[j], s[j-k]);
|
||||
|
||||
ps[j-k] += Base(double(k)) * azmul(pc[j], x[k]);
|
||||
pc[j-k] += Base(double(k)) * azmul(ps[j], x[k]);
|
||||
|
||||
}
|
||||
--j;
|
||||
}
|
||||
px[0] += azmul(ps[0], c[0]);
|
||||
px[0] += azmul(pc[0], s[0]);
|
||||
}
|
||||
|
||||
} } // END_CPPAD_LOCAL_NAMESPACE
|
||||
# endif
|
||||
@@ -0,0 +1,485 @@
|
||||
// $Id: sparse_binary_op.hpp 3865 2017-01-19 01:57:55Z bradbell $
|
||||
# ifndef CPPAD_LOCAL_SPARSE_BINARY_OP_HPP
|
||||
# define CPPAD_LOCAL_SPARSE_BINARY_OP_HPP
|
||||
/* --------------------------------------------------------------------------
|
||||
CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-17 Bradley M. Bell
|
||||
|
||||
CppAD is distributed under multiple licenses. This distribution is under
|
||||
the terms of the
|
||||
Eclipse Public License Version 1.0.
|
||||
|
||||
A copy of this license is included in the COPYING file of this distribution.
|
||||
Please visit http://www.coin-or.org/CppAD/ for information on other licenses.
|
||||
-------------------------------------------------------------------------- */
|
||||
|
||||
namespace CppAD { namespace local { // BEGIN_CPPAD_LOCAL_NAMESPACE
|
||||
/*!
|
||||
\file sparse_binary_op.hpp
|
||||
Forward and reverse mode sparsity patterns for binary operators.
|
||||
*/
|
||||
|
||||
|
||||
/*!
|
||||
Forward mode Jacobian sparsity pattern for all binary operators.
|
||||
|
||||
The C++ source code corresponding to a binary operation has the form
|
||||
\verbatim
|
||||
z = fun(x, y)
|
||||
\endverbatim
|
||||
where fun is a C++ binary function and both x and y are variables,
|
||||
or it has the form
|
||||
\verbatim
|
||||
z = x op y
|
||||
\endverbatim
|
||||
where op is a C++ binary unary operator and both x and y are variables.
|
||||
|
||||
\tparam Vector_set
|
||||
is the type used for vectors of sets. It can be either
|
||||
sparse_pack or sparse_list.
|
||||
|
||||
\param i_z
|
||||
variable index corresponding to the result for this operation;
|
||||
i.e., z.
|
||||
|
||||
\param arg
|
||||
\a arg[0]
|
||||
variable index corresponding to the left operand for this operator;
|
||||
i.e., x.
|
||||
\n
|
||||
\n arg[1]
|
||||
variable index corresponding to the right operand for this operator;
|
||||
i.e., y.
|
||||
|
||||
\param sparsity
|
||||
\b Input:
|
||||
The set with index \a arg[0] in \a sparsity
|
||||
is the sparsity bit pattern for x.
|
||||
This identifies which of the independent variables the variable x
|
||||
depends on.
|
||||
\n
|
||||
\n
|
||||
\b Input:
|
||||
The set with index \a arg[1] in \a sparsity
|
||||
is the sparsity bit pattern for y.
|
||||
This identifies which of the independent variables the variable y
|
||||
depends on.
|
||||
\n
|
||||
\n
|
||||
\b Output:
|
||||
The set with index \a i_z in \a sparsity
|
||||
is the sparsity bit pattern for z.
|
||||
This identifies which of the independent variables the variable z
|
||||
depends on.
|
||||
|
||||
\par Checked Assertions:
|
||||
\li \a arg[0] < \a i_z
|
||||
\li \a arg[1] < \a i_z
|
||||
*/
|
||||
|
||||
template <class Vector_set>
|
||||
inline void forward_sparse_jacobian_binary_op(
|
||||
size_t i_z ,
|
||||
const addr_t* arg ,
|
||||
Vector_set& sparsity )
|
||||
{
|
||||
// check assumptions
|
||||
CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < i_z );
|
||||
CPPAD_ASSERT_UNKNOWN( size_t(arg[1]) < i_z );
|
||||
|
||||
sparsity.binary_union(i_z, arg[0], arg[1], sparsity);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/*!
|
||||
Reverse mode Jacobian sparsity pattern for all binary operators.
|
||||
|
||||
The C++ source code corresponding to a unary operation has the form
|
||||
\verbatim
|
||||
z = fun(x, y)
|
||||
\endverbatim
|
||||
where fun is a C++ unary function and x and y are variables,
|
||||
or it has the form
|
||||
\verbatim
|
||||
z = x op y
|
||||
\endverbatim
|
||||
where op is a C++ bianry operator and x and y are variables.
|
||||
|
||||
This routine is given the sparsity patterns
|
||||
for a function G(z, y, x, ... )
|
||||
and it uses them to compute the sparsity patterns for
|
||||
\verbatim
|
||||
H( y, x, w , u , ... ) = G[ z(x,y) , y , x , w , u , ... ]
|
||||
\endverbatim
|
||||
|
||||
\tparam Vector_set
|
||||
is the type used for vectors of sets. It can be either
|
||||
sparse_pack or sparse_list.
|
||||
|
||||
\param i_z
|
||||
variable index corresponding to the result for this operation;
|
||||
i.e., z.
|
||||
|
||||
\param arg
|
||||
\a arg[0]
|
||||
variable index corresponding to the left operand for this operator;
|
||||
i.e., x.
|
||||
|
||||
\n
|
||||
\n arg[1]
|
||||
variable index corresponding to the right operand for this operator;
|
||||
i.e., y.
|
||||
|
||||
\param sparsity
|
||||
The set with index \a i_z in \a sparsity
|
||||
is the sparsity pattern for z corresponding ot the function G.
|
||||
\n
|
||||
\n
|
||||
The set with index \a arg[0] in \a sparsity
|
||||
is the sparsity pattern for x.
|
||||
On input, it corresponds to the function G,
|
||||
and on output it corresponds to H.
|
||||
\n
|
||||
\n
|
||||
The set with index \a arg[1] in \a sparsity
|
||||
is the sparsity pattern for y.
|
||||
On input, it corresponds to the function G,
|
||||
and on output it corresponds to H.
|
||||
\n
|
||||
\n
|
||||
|
||||
\par Checked Assertions:
|
||||
\li \a arg[0] < \a i_z
|
||||
\li \a arg[1] < \a i_z
|
||||
*/
|
||||
template <class Vector_set>
|
||||
inline void reverse_sparse_jacobian_binary_op(
|
||||
size_t i_z ,
|
||||
const addr_t* arg ,
|
||||
Vector_set& sparsity )
|
||||
{
|
||||
// check assumptions
|
||||
CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < i_z );
|
||||
CPPAD_ASSERT_UNKNOWN( size_t(arg[1]) < i_z );
|
||||
|
||||
sparsity.binary_union(arg[0], arg[0], i_z, sparsity);
|
||||
sparsity.binary_union(arg[1], arg[1], i_z, sparsity);
|
||||
|
||||
return;
|
||||
}
|
||||
// ---------------------------------------------------------------------------
|
||||
/*!
|
||||
Reverse mode Hessian sparsity pattern for add and subtract operators.
|
||||
|
||||
The C++ source code corresponding to a unary operation has the form
|
||||
\verbatim
|
||||
z = x op y
|
||||
\endverbatim
|
||||
where op is + or - and x, y are variables.
|
||||
|
||||
\copydetails CppAD::local::reverse_sparse_hessian_binary_op
|
||||
*/
|
||||
template <class Vector_set>
|
||||
inline void reverse_sparse_hessian_addsub_op(
|
||||
size_t i_z ,
|
||||
const addr_t* arg ,
|
||||
bool* jac_reverse ,
|
||||
const Vector_set& for_jac_sparsity ,
|
||||
Vector_set& rev_hes_sparsity )
|
||||
{
|
||||
// check assumptions
|
||||
CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < i_z );
|
||||
CPPAD_ASSERT_UNKNOWN( size_t(arg[1]) < i_z );
|
||||
|
||||
rev_hes_sparsity.binary_union(arg[0], arg[0], i_z, rev_hes_sparsity);
|
||||
rev_hes_sparsity.binary_union(arg[1], arg[1], i_z, rev_hes_sparsity);
|
||||
|
||||
jac_reverse[arg[0]] |= jac_reverse[i_z];
|
||||
jac_reverse[arg[1]] |= jac_reverse[i_z];
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/*!
|
||||
Reverse mode Hessian sparsity pattern for multiplication operator.
|
||||
|
||||
The C++ source code corresponding to a unary operation has the form
|
||||
\verbatim
|
||||
z = x * y
|
||||
\endverbatim
|
||||
where x and y are variables.
|
||||
|
||||
\copydetails CppAD::local::reverse_sparse_hessian_binary_op
|
||||
*/
|
||||
template <class Vector_set>
|
||||
inline void reverse_sparse_hessian_mul_op(
|
||||
size_t i_z ,
|
||||
const addr_t* arg ,
|
||||
bool* jac_reverse ,
|
||||
const Vector_set& for_jac_sparsity ,
|
||||
Vector_set& rev_hes_sparsity )
|
||||
{
|
||||
// check assumptions
|
||||
CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < i_z );
|
||||
CPPAD_ASSERT_UNKNOWN( size_t(arg[1]) < i_z );
|
||||
|
||||
rev_hes_sparsity.binary_union(arg[0], arg[0], i_z, rev_hes_sparsity);
|
||||
rev_hes_sparsity.binary_union(arg[1], arg[1], i_z, rev_hes_sparsity);
|
||||
|
||||
if( jac_reverse[i_z] )
|
||||
{ rev_hes_sparsity.binary_union(
|
||||
arg[0], arg[0], arg[1], for_jac_sparsity);
|
||||
rev_hes_sparsity.binary_union(
|
||||
arg[1], arg[1], arg[0], for_jac_sparsity);
|
||||
}
|
||||
|
||||
jac_reverse[arg[0]] |= jac_reverse[i_z];
|
||||
jac_reverse[arg[1]] |= jac_reverse[i_z];
|
||||
return;
|
||||
}
|
||||
|
||||
/*!
|
||||
Reverse mode Hessian sparsity pattern for division operator.
|
||||
|
||||
The C++ source code corresponding to a unary operation has the form
|
||||
\verbatim
|
||||
z = x / y
|
||||
\endverbatim
|
||||
where x and y are variables.
|
||||
|
||||
\copydetails CppAD::local::reverse_sparse_hessian_binary_op
|
||||
*/
|
||||
template <class Vector_set>
|
||||
inline void reverse_sparse_hessian_div_op(
|
||||
size_t i_z ,
|
||||
const addr_t* arg ,
|
||||
bool* jac_reverse ,
|
||||
const Vector_set& for_jac_sparsity ,
|
||||
Vector_set& rev_hes_sparsity )
|
||||
{
|
||||
// check assumptions
|
||||
CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < i_z );
|
||||
CPPAD_ASSERT_UNKNOWN( size_t(arg[1]) < i_z );
|
||||
|
||||
rev_hes_sparsity.binary_union(arg[0], arg[0], i_z, rev_hes_sparsity);
|
||||
rev_hes_sparsity.binary_union(arg[1], arg[1], i_z, rev_hes_sparsity);
|
||||
|
||||
if( jac_reverse[i_z] )
|
||||
{ rev_hes_sparsity.binary_union(
|
||||
arg[0], arg[0], arg[1], for_jac_sparsity);
|
||||
rev_hes_sparsity.binary_union(
|
||||
arg[1], arg[1], arg[0], for_jac_sparsity);
|
||||
rev_hes_sparsity.binary_union(
|
||||
arg[1], arg[1], arg[1], for_jac_sparsity);
|
||||
}
|
||||
|
||||
jac_reverse[arg[0]] |= jac_reverse[i_z];
|
||||
jac_reverse[arg[1]] |= jac_reverse[i_z];
|
||||
return;
|
||||
}
|
||||
|
||||
/*!
|
||||
Reverse mode Hessian sparsity pattern for power function.
|
||||
|
||||
The C++ source code corresponding to a unary operation has the form
|
||||
\verbatim
|
||||
z = pow(x, y)
|
||||
\endverbatim
|
||||
where x and y are variables.
|
||||
|
||||
\copydetails CppAD::local::reverse_sparse_hessian_binary_op
|
||||
*/
|
||||
template <class Vector_set>
|
||||
inline void reverse_sparse_hessian_pow_op(
|
||||
size_t i_z ,
|
||||
const addr_t* arg ,
|
||||
bool* jac_reverse ,
|
||||
const Vector_set& for_jac_sparsity ,
|
||||
Vector_set& rev_hes_sparsity )
|
||||
{
|
||||
// check assumptions
|
||||
CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < i_z );
|
||||
CPPAD_ASSERT_UNKNOWN( size_t(arg[1]) < i_z );
|
||||
|
||||
rev_hes_sparsity.binary_union(arg[0], arg[0], i_z, rev_hes_sparsity);
|
||||
rev_hes_sparsity.binary_union(arg[1], arg[1], i_z, rev_hes_sparsity);
|
||||
|
||||
if( jac_reverse[i_z] )
|
||||
{
|
||||
rev_hes_sparsity.binary_union(
|
||||
arg[0], arg[0], arg[0], for_jac_sparsity);
|
||||
rev_hes_sparsity.binary_union(
|
||||
arg[0], arg[0], arg[1], for_jac_sparsity);
|
||||
|
||||
rev_hes_sparsity.binary_union(
|
||||
arg[1], arg[1], arg[0], for_jac_sparsity);
|
||||
rev_hes_sparsity.binary_union(
|
||||
arg[1], arg[1], arg[1], for_jac_sparsity);
|
||||
}
|
||||
|
||||
// I cannot think of a case where this is necessary, but it including
|
||||
// it makes it like the other cases.
|
||||
jac_reverse[arg[0]] |= jac_reverse[i_z];
|
||||
jac_reverse[arg[1]] |= jac_reverse[i_z];
|
||||
return;
|
||||
}
|
||||
// ---------------------------------------------------------------------------
|
||||
/*!
|
||||
Forward mode Hessian sparsity pattern for multiplication operator.
|
||||
|
||||
The C++ source code corresponding to this operation is
|
||||
\verbatim
|
||||
w(x) = v0(x) * v1(x)
|
||||
\endverbatim
|
||||
|
||||
\param arg
|
||||
is the index of the argument vector for the multiplication operation; i.e.,
|
||||
arg[0], arg[1] are the left and right operands.
|
||||
|
||||
\param for_jac_sparsity
|
||||
for_jac_sparsity(arg[0]) constains the Jacobian sparsity for v0(x),
|
||||
for_jac_sparsity(arg[1]) constains the Jacobian sparsity for v1(x).
|
||||
|
||||
\param for_hes_sparsity
|
||||
On input, for_hes_sparsity includes the Hessian sparsity for v0(x)
|
||||
and v1(x); i.e., the sparsity can be a super set.
|
||||
Upon return it includes the Hessian sparsity for w(x)
|
||||
*/
|
||||
template <class Vector_set>
|
||||
inline void forward_sparse_hessian_mul_op(
|
||||
const addr_t* arg ,
|
||||
const Vector_set& for_jac_sparsity ,
|
||||
Vector_set& for_hes_sparsity )
|
||||
{ // --------------------------------------------------
|
||||
// set of independent variables that v0 depends on
|
||||
typename Vector_set::const_iterator itr_0(for_jac_sparsity, arg[0]);
|
||||
|
||||
// loop over dependent variables with non-zero partial
|
||||
size_t i_x = *itr_0;
|
||||
while( i_x < for_jac_sparsity.end() )
|
||||
{ // N(i_x) = N(i_x) union L(v1)
|
||||
for_hes_sparsity.binary_union(i_x, i_x, arg[1], for_jac_sparsity);
|
||||
i_x = *(++itr_0);
|
||||
}
|
||||
// --------------------------------------------------
|
||||
// set of independent variables that v1 depends on
|
||||
typename Vector_set::const_iterator itr_1(for_jac_sparsity, arg[1]);
|
||||
|
||||
// loop over dependent variables with non-zero partial
|
||||
i_x = *itr_1;
|
||||
while( i_x < for_jac_sparsity.end() )
|
||||
{ // N(i_x) = N(i_x) union L(v0)
|
||||
for_hes_sparsity.binary_union(i_x, i_x, arg[0], for_jac_sparsity);
|
||||
i_x = *(++itr_1);
|
||||
}
|
||||
return;
|
||||
}
|
||||
/*!
|
||||
Forward mode Hessian sparsity pattern for division operator.
|
||||
|
||||
The C++ source code corresponding to this operation is
|
||||
\verbatim
|
||||
w(x) = v0(x) / v1(x)
|
||||
\endverbatim
|
||||
|
||||
\param arg
|
||||
is the index of the argument vector for the division operation; i.e.,
|
||||
arg[0], arg[1] are the left and right operands.
|
||||
|
||||
\param for_jac_sparsity
|
||||
for_jac_sparsity(arg[0]) constains the Jacobian sparsity for v0(x),
|
||||
for_jac_sparsity(arg[1]) constains the Jacobian sparsity for v1(x).
|
||||
|
||||
\param for_hes_sparsity
|
||||
On input, for_hes_sparsity includes the Hessian sparsity for v0(x)
|
||||
and v1(x); i.e., the sparsity can be a super set.
|
||||
Upon return it includes the Hessian sparsity for w(x)
|
||||
*/
|
||||
template <class Vector_set>
|
||||
inline void forward_sparse_hessian_div_op(
|
||||
const addr_t* arg ,
|
||||
const Vector_set& for_jac_sparsity ,
|
||||
Vector_set& for_hes_sparsity )
|
||||
{ // --------------------------------------------------
|
||||
// set of independent variables that v0 depends on
|
||||
typename Vector_set::const_iterator itr_0(for_jac_sparsity, arg[0]);
|
||||
|
||||
// loop over dependent variables with non-zero partial
|
||||
size_t i_x = *itr_0;
|
||||
while( i_x < for_jac_sparsity.end() )
|
||||
{ // N(i_x) = N(i_x) union L(v1)
|
||||
for_hes_sparsity.binary_union(i_x, i_x, arg[1], for_jac_sparsity);
|
||||
i_x = *(++itr_0);
|
||||
}
|
||||
// --------------------------------------------------
|
||||
// set of independent variables that v1 depends on
|
||||
typename Vector_set::const_iterator itr_1(for_jac_sparsity, arg[1]);
|
||||
|
||||
// loop over dependent variables with non-zero partial
|
||||
i_x = *itr_1;
|
||||
while( i_x < for_jac_sparsity.end() )
|
||||
{ // N(i_x) = N(i_x) union L(v0)
|
||||
for_hes_sparsity.binary_union(i_x, i_x, arg[0], for_jac_sparsity);
|
||||
// N(i_x) = N(i_x) union L(v1)
|
||||
for_hes_sparsity.binary_union(i_x, i_x, arg[1], for_jac_sparsity);
|
||||
i_x = *(++itr_1);
|
||||
}
|
||||
return;
|
||||
}
|
||||
/*!
|
||||
Forward mode Hessian sparsity pattern for power operator.
|
||||
|
||||
The C++ source code corresponding to this operation is
|
||||
\verbatim
|
||||
w(x) = pow( v0(x) , v1(x) )
|
||||
\endverbatim
|
||||
|
||||
\param arg
|
||||
is the index of the argument vector for the power operation; i.e.,
|
||||
arg[0], arg[1] are the left and right operands.
|
||||
|
||||
\param for_jac_sparsity
|
||||
for_jac_sparsity(arg[0]) constains the Jacobian sparsity for v0(x),
|
||||
for_jac_sparsity(arg[1]) constains the Jacobian sparsity for v1(x).
|
||||
|
||||
\param for_hes_sparsity
|
||||
On input, for_hes_sparsity includes the Hessian sparsity for v0(x)
|
||||
and v1(x); i.e., the sparsity can be a super set.
|
||||
Upon return it includes the Hessian sparsity for w(x)
|
||||
*/
|
||||
template <class Vector_set>
|
||||
inline void forward_sparse_hessian_pow_op(
|
||||
const addr_t* arg ,
|
||||
const Vector_set& for_jac_sparsity ,
|
||||
Vector_set& for_hes_sparsity )
|
||||
{ // --------------------------------------------------
|
||||
// set of independent variables that v0 depends on
|
||||
typename Vector_set::const_iterator itr_0(for_jac_sparsity, arg[0]);
|
||||
|
||||
// loop over dependent variables with non-zero partial
|
||||
size_t i_x = *itr_0;
|
||||
while( i_x < for_jac_sparsity.end() )
|
||||
{ // N(i_x) = N(i_x) union L(v0)
|
||||
for_hes_sparsity.binary_union(i_x, i_x, arg[0], for_jac_sparsity);
|
||||
// N(i_x) = N(i_x) union L(v1)
|
||||
for_hes_sparsity.binary_union(i_x, i_x, arg[1], for_jac_sparsity);
|
||||
i_x = *(++itr_0);
|
||||
}
|
||||
// --------------------------------------------------
|
||||
// set of independent variables that v1 depends on
|
||||
typename Vector_set::const_iterator itr_1(for_jac_sparsity, arg[1]);
|
||||
|
||||
// loop over dependent variables with non-zero partial
|
||||
i_x = *itr_1;
|
||||
while( i_x < for_jac_sparsity.end() )
|
||||
{ // N(i_x) = N(i_x) union L(v0)
|
||||
for_hes_sparsity.binary_union(i_x, i_x, arg[0], for_jac_sparsity);
|
||||
// N(i_x) = N(i_x) union L(v1)
|
||||
for_hes_sparsity.binary_union(i_x, i_x, arg[1], for_jac_sparsity);
|
||||
i_x = *(++itr_1);
|
||||
}
|
||||
return;
|
||||
}
|
||||
// ---------------------------------------------------------------------------
|
||||
} } // END_CPPAD_LOCAL_NAMESPACE
|
||||
# endif
|
||||
@@ -0,0 +1,440 @@
|
||||
# ifndef CPPAD_LOCAL_SPARSE_INTERNAL_HPP
|
||||
# define CPPAD_LOCAL_SPARSE_INTERNAL_HPP
|
||||
|
||||
/* --------------------------------------------------------------------------
|
||||
CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-17 Bradley M. Bell
|
||||
|
||||
CppAD is distributed under multiple licenses. This distribution is under
|
||||
the terms of the
|
||||
Eclipse Public License Version 1.0.
|
||||
|
||||
A copy of this license is included in the COPYING file of this distribution.
|
||||
Please visit http://www.coin-or.org/CppAD/ for information on other licenses.
|
||||
-------------------------------------------------------------------------- */
|
||||
|
||||
// necessary definitions
|
||||
# include <cppad/core/define.hpp>
|
||||
# include <cppad/local/sparse_pack.hpp>
|
||||
# include <cppad/local/sparse_list.hpp>
|
||||
|
||||
namespace CppAD { namespace local { // BEGIN_CPPAD_LOCAL_NAMESPACE
|
||||
/*!
|
||||
\file sparse_internal.hpp
|
||||
Routines that enable code to be independent of which internal spasity pattern
|
||||
is used.
|
||||
*/
|
||||
// ---------------------------------------------------------------------------
|
||||
/*!
|
||||
Template structure used obtain the internal sparsity pattern type
|
||||
form the corresponding element type.
|
||||
The general form is not valid, must use a specialization.
|
||||
|
||||
\tparam Element_type
|
||||
type of an element in the sparsity structrue.
|
||||
|
||||
\par <code>internal_sparsity<Element_type>::pattern_type</code>
|
||||
is the type of the corresponding internal sparsity pattern.
|
||||
*/
|
||||
template <class Element_type> struct internal_sparsity;
|
||||
/// Specilization for \c bool elements.
|
||||
template <>
|
||||
struct internal_sparsity<bool>
|
||||
{
|
||||
typedef sparse_pack pattern_type;
|
||||
};
|
||||
/// Specilization for <code>std::set<size_t></code> elements.
|
||||
template <>
|
||||
struct internal_sparsity< std::set<size_t> >
|
||||
{
|
||||
typedef sparse_list pattern_type;
|
||||
};
|
||||
// ---------------------------------------------------------------------------
|
||||
/*!
|
||||
Update the internal sparsity pattern for a sub-set of rows
|
||||
|
||||
\tparam SizeVector
|
||||
The type used for index sparsity patterns. This is a simple vector
|
||||
with elements of type size_t.
|
||||
|
||||
\tparam InternalSparsitiy
|
||||
The type used for intenal sparsity patterns. This can be either
|
||||
sparse_pack or sparse_list.
|
||||
|
||||
\param zero_empty
|
||||
If this is true, the internal sparstity pattern corresponds to row zero
|
||||
must be empty on input and will be emtpy output; i.e., any corresponding
|
||||
values in pattern_in will be ignored.
|
||||
|
||||
\param input_empty
|
||||
If this is true, the initial sparsity pattern for row
|
||||
internal_index[i] is empty for all i.
|
||||
In this case, one is setting the sparsity patterns; i.e.,
|
||||
the output pattern in row internal_index[i] is the corresponding
|
||||
entries in pattern.
|
||||
|
||||
\param transpose
|
||||
If this is true, pattern_in is transposed.
|
||||
|
||||
\param internal_index
|
||||
This specifies the sub-set of rows in internal_sparsity that we are updating.
|
||||
If traspose is false (true),
|
||||
this is the mapping from row (column) index in pattern_in to the corresponding
|
||||
row index in the internal_pattern.
|
||||
|
||||
\param internal_pattern
|
||||
On input, the number of sets internal_pattern.n_set(),
|
||||
and possible elements internal_pattern.end(), have been set.
|
||||
If input_empty is true, and all of the sets
|
||||
in internal_index are empty on input.
|
||||
On output, the entries in pattern_in are added to internal_pattern.
|
||||
To be specific, suppose transpose is false, and (i, j) is a possibly
|
||||
non-zero entry in pattern_in, the entry (internal_index[i], j) is added
|
||||
to internal_pattern.
|
||||
On the other hand, if transpose is true,
|
||||
the entry (internal_index[j], i) is added to internal_pattern.
|
||||
|
||||
\param pattern_in
|
||||
This is the sparsity pattern for variables,
|
||||
or its transpose, depending on the value of transpose.
|
||||
*/
|
||||
template <class SizeVector, class InternalSparsity>
|
||||
void set_internal_sparsity(
|
||||
bool zero_empty ,
|
||||
bool input_empty ,
|
||||
bool transpose ,
|
||||
const vector<size_t>& internal_index ,
|
||||
InternalSparsity& internal_pattern ,
|
||||
const sparse_rc<SizeVector>& pattern_in )
|
||||
{
|
||||
# ifndef NDEBUG
|
||||
size_t nr = internal_index.size();
|
||||
size_t nc = internal_pattern.end();
|
||||
if( transpose )
|
||||
{ CPPAD_ASSERT_UNKNOWN( pattern_in.nr() == nc );
|
||||
CPPAD_ASSERT_UNKNOWN( pattern_in.nc() == nr );
|
||||
}
|
||||
else
|
||||
{ CPPAD_ASSERT_UNKNOWN( pattern_in.nr() == nr );
|
||||
CPPAD_ASSERT_UNKNOWN( pattern_in.nc() == nc );
|
||||
}
|
||||
if( input_empty ) for(size_t i = 0; i < nr; i++)
|
||||
{ size_t i_var = internal_index[i];
|
||||
CPPAD_ASSERT_UNKNOWN( internal_pattern.number_elements(i_var) == 0 );
|
||||
}
|
||||
# endif
|
||||
const SizeVector& row( pattern_in.row() );
|
||||
const SizeVector& col( pattern_in.col() );
|
||||
size_t nnz = row.size();
|
||||
for(size_t k = 0; k < nnz; k++)
|
||||
{ size_t r = row[k];
|
||||
size_t c = col[k];
|
||||
if( transpose )
|
||||
std::swap(r, c);
|
||||
//
|
||||
size_t i_var = internal_index[r];
|
||||
CPPAD_ASSERT_UNKNOWN( i_var < internal_pattern.n_set() );
|
||||
CPPAD_ASSERT_UNKNOWN( c < nc );
|
||||
bool ignore = zero_empty && i_var == 0;
|
||||
if( ! ignore )
|
||||
internal_pattern.add_element( internal_index[r], c );
|
||||
}
|
||||
}
|
||||
template <class InternalSparsity>
|
||||
void set_internal_sparsity(
|
||||
bool zero_empty ,
|
||||
bool input_empty ,
|
||||
bool transpose ,
|
||||
const vector<size_t>& internal_index ,
|
||||
InternalSparsity& internal_pattern ,
|
||||
const vectorBool& pattern_in )
|
||||
{ size_t nr = internal_index.size();
|
||||
size_t nc = internal_pattern.end();
|
||||
# ifndef NDEBUG
|
||||
CPPAD_ASSERT_UNKNOWN( pattern_in.size() == nr * nc );
|
||||
if( input_empty ) for(size_t i = 0; i < nr; i++)
|
||||
{ size_t i_var = internal_index[i];
|
||||
CPPAD_ASSERT_UNKNOWN( internal_pattern.number_elements(i_var) == 0 );
|
||||
}
|
||||
# endif
|
||||
for(size_t i = 0; i < nr; i++)
|
||||
{ for(size_t j = 0; j < nc; j++)
|
||||
{ bool flag = pattern_in[i * nc + j];
|
||||
if( transpose )
|
||||
flag = pattern_in[j * nr + i];
|
||||
if( flag )
|
||||
{ size_t i_var = internal_index[i];
|
||||
CPPAD_ASSERT_UNKNOWN( i_var < internal_pattern.n_set() );
|
||||
CPPAD_ASSERT_UNKNOWN( j < nc );
|
||||
bool ignore = zero_empty && i_var == 0;
|
||||
if( ! ignore )
|
||||
internal_pattern.add_element( i_var, j);
|
||||
}
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
template <class InternalSparsity>
|
||||
void set_internal_sparsity(
|
||||
bool zero_empty ,
|
||||
bool input_empty ,
|
||||
bool transpose ,
|
||||
const vector<size_t>& internal_index ,
|
||||
InternalSparsity& internal_pattern ,
|
||||
const vector<bool>& pattern_in )
|
||||
{ size_t nr = internal_index.size();
|
||||
size_t nc = internal_pattern.end();
|
||||
# ifndef NDEBUG
|
||||
CPPAD_ASSERT_UNKNOWN( pattern_in.size() == nr * nc );
|
||||
if( input_empty ) for(size_t i = 0; i < nr; i++)
|
||||
{ size_t i_var = internal_index[i];
|
||||
CPPAD_ASSERT_UNKNOWN( internal_pattern.number_elements(i_var) == 0 );
|
||||
}
|
||||
# endif
|
||||
for(size_t i = 0; i < nr; i++)
|
||||
{ for(size_t j = 0; j < nc; j++)
|
||||
{ bool flag = pattern_in[i * nc + j];
|
||||
if( transpose )
|
||||
flag = pattern_in[j * nr + i];
|
||||
if( flag )
|
||||
{ size_t i_var = internal_index[i];
|
||||
CPPAD_ASSERT_UNKNOWN( i_var < internal_pattern.n_set() );
|
||||
CPPAD_ASSERT_UNKNOWN( j < nc );
|
||||
bool ignore = zero_empty && i_var == 0;
|
||||
if( ! ignore )
|
||||
internal_pattern.add_element( i_var, j);
|
||||
}
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
template <class InternalSparsity>
|
||||
void set_internal_sparsity(
|
||||
bool zero_empty ,
|
||||
bool input_empty ,
|
||||
bool transpose ,
|
||||
const vector<size_t>& internal_index ,
|
||||
InternalSparsity& internal_pattern ,
|
||||
const vector< std::set<size_t> >& pattern_in )
|
||||
{ size_t nr = internal_index.size();
|
||||
size_t nc = internal_pattern.end();
|
||||
# ifndef NDEBUG
|
||||
if( input_empty ) for(size_t i = 0; i < nr; i++)
|
||||
{ size_t i_var = internal_index[i];
|
||||
CPPAD_ASSERT_UNKNOWN( internal_pattern.number_elements(i_var) == 0 );
|
||||
}
|
||||
# endif
|
||||
if( transpose )
|
||||
{ CPPAD_ASSERT_UNKNOWN( pattern_in.size() == nc );
|
||||
for(size_t j = 0; j < nc; j++)
|
||||
{ std::set<size_t>::const_iterator itr( pattern_in[j].begin() );
|
||||
while( itr != pattern_in[j].end() )
|
||||
{ size_t i = *itr;
|
||||
size_t i_var = internal_index[i];
|
||||
CPPAD_ASSERT_UNKNOWN( i_var < internal_pattern.n_set() );
|
||||
CPPAD_ASSERT_UNKNOWN( j < nc );
|
||||
bool ignore = zero_empty && i_var == 0;
|
||||
if( ! ignore )
|
||||
internal_pattern.add_element( i_var, j);
|
||||
++itr;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{ CPPAD_ASSERT_UNKNOWN( pattern_in.size() == nr );
|
||||
for(size_t i = 0; i < nr; i++)
|
||||
{ std::set<size_t>::const_iterator itr( pattern_in[i].begin() );
|
||||
while( itr != pattern_in[i].end() )
|
||||
{ size_t j = *itr;
|
||||
size_t i_var = internal_index[i];
|
||||
CPPAD_ASSERT_UNKNOWN( i_var < internal_pattern.n_set() );
|
||||
CPPAD_ASSERT_UNKNOWN( j < nc );
|
||||
bool ignore = zero_empty && i_var == 0;
|
||||
if( ! ignore )
|
||||
internal_pattern.add_element( i_var, j);
|
||||
++itr;
|
||||
}
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
// ---------------------------------------------------------------------------
|
||||
/*!
|
||||
Get sparsity pattern for a sub-set of variables
|
||||
|
||||
\tparam SizeVector
|
||||
The type used for index sparsity patterns. This is a simple vector
|
||||
with elements of type size_t.
|
||||
|
||||
\tparam InternalSparsitiy
|
||||
The type used for intenal sparsity patterns. This can be either
|
||||
sparse_pack or sparse_list.
|
||||
|
||||
\param transpose
|
||||
If this is true, pattern_out is transposed.
|
||||
|
||||
\param internal_index
|
||||
If transpose is false (true)
|
||||
this is the mapping from row (column) an index in pattern_out
|
||||
to the corresponding row index in internal_pattern.
|
||||
|
||||
\param internal_pattern
|
||||
This is the internal sparsity pattern.
|
||||
|
||||
\param pattern_out
|
||||
The input value of pattern_out does not matter.
|
||||
Upon return it is an index sparsity pattern for each of the variables
|
||||
in internal_index, or its transpose, depending on the value of transpose.
|
||||
*/
|
||||
template <class SizeVector, class InternalSparsity>
|
||||
void get_internal_sparsity(
|
||||
bool transpose ,
|
||||
const vector<size_t>& internal_index ,
|
||||
const InternalSparsity& internal_pattern ,
|
||||
sparse_rc<SizeVector>& pattern_out )
|
||||
{ typedef typename InternalSparsity::const_iterator iterator;
|
||||
// number variables
|
||||
size_t nr = internal_index.size();
|
||||
// column size of interanl sparstiy pattern
|
||||
size_t nc = internal_pattern.end();
|
||||
// determine nnz, the number of possibly non-zero index pairs
|
||||
size_t nnz = 0;
|
||||
for(size_t i = 0; i < nr; i++)
|
||||
{ CPPAD_ASSERT_UNKNOWN( internal_index[i] < internal_pattern.n_set() );
|
||||
iterator itr(internal_pattern, internal_index[i]);
|
||||
size_t j = *itr;
|
||||
while( j < nc )
|
||||
{ ++nnz;
|
||||
j = *(++itr);
|
||||
}
|
||||
}
|
||||
// transposed
|
||||
if( transpose )
|
||||
{ pattern_out.resize(nc, nr, nnz);
|
||||
//
|
||||
size_t k = 0;
|
||||
for(size_t i = 0; i < nr; i++)
|
||||
{ iterator itr(internal_pattern, internal_index[i]);
|
||||
size_t j = *itr;
|
||||
while( j < nc )
|
||||
{ pattern_out.set(k++, j, i);
|
||||
j = *(++itr);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
// not transposed
|
||||
pattern_out.resize(nr, nc, nnz);
|
||||
//
|
||||
size_t k = 0;
|
||||
for(size_t i = 0; i < nr; i++)
|
||||
{ iterator itr(internal_pattern, internal_index[i]);
|
||||
size_t j = *itr;
|
||||
while( j < nc )
|
||||
{ pattern_out.set(k++, i, j);
|
||||
j = *(++itr);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
template <class InternalSparsity>
|
||||
void get_internal_sparsity(
|
||||
bool transpose ,
|
||||
const vector<size_t>& internal_index ,
|
||||
const InternalSparsity& internal_pattern ,
|
||||
vectorBool& pattern_out )
|
||||
{ typedef typename InternalSparsity::const_iterator iterator;
|
||||
// number variables
|
||||
size_t nr = internal_index.size();
|
||||
//
|
||||
// column size of interanl sparstiy pattern
|
||||
size_t nc = internal_pattern.end();
|
||||
//
|
||||
pattern_out.resize(nr * nc);
|
||||
for(size_t ij = 0; ij < nr * nc; ij++)
|
||||
pattern_out[ij] = false;
|
||||
//
|
||||
for(size_t i = 0; i < nr; i++)
|
||||
{ CPPAD_ASSERT_UNKNOWN( internal_index[i] < internal_pattern.n_set() );
|
||||
iterator itr(internal_pattern, internal_index[i]);
|
||||
size_t j = *itr;
|
||||
while( j < nc )
|
||||
{ if( transpose )
|
||||
pattern_out[j * nr + i] = true;
|
||||
else
|
||||
pattern_out[i * nc + j] = true;
|
||||
j = *(++itr);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
template <class InternalSparsity>
|
||||
void get_internal_sparsity(
|
||||
bool transpose ,
|
||||
const vector<size_t>& internal_index ,
|
||||
const InternalSparsity& internal_pattern ,
|
||||
vector<bool>& pattern_out )
|
||||
{ typedef typename InternalSparsity::const_iterator iterator;
|
||||
// number variables
|
||||
size_t nr = internal_index.size();
|
||||
//
|
||||
// column size of interanl sparstiy pattern
|
||||
size_t nc = internal_pattern.end();
|
||||
//
|
||||
pattern_out.resize(nr * nc);
|
||||
for(size_t ij = 0; ij < nr * nc; ij++)
|
||||
pattern_out[ij] = false;
|
||||
//
|
||||
for(size_t i = 0; i < nr; i++)
|
||||
{ CPPAD_ASSERT_UNKNOWN( internal_index[i] < internal_pattern.n_set() );
|
||||
iterator itr(internal_pattern, internal_index[i]);
|
||||
size_t j = *itr;
|
||||
while( j < nc )
|
||||
{ if( transpose )
|
||||
pattern_out[j * nr + i] = true;
|
||||
else
|
||||
pattern_out[i * nc + j] = true;
|
||||
j = *(++itr);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
template <class InternalSparsity>
|
||||
void get_internal_sparsity(
|
||||
bool transpose ,
|
||||
const vector<size_t>& internal_index ,
|
||||
const InternalSparsity& internal_pattern ,
|
||||
vector< std::set<size_t> >& pattern_out )
|
||||
{ typedef typename InternalSparsity::const_iterator iterator;
|
||||
// number variables
|
||||
size_t nr = internal_index.size();
|
||||
//
|
||||
// column size of interanl sparstiy pattern
|
||||
size_t nc = internal_pattern.end();
|
||||
//
|
||||
if( transpose )
|
||||
pattern_out.resize(nc);
|
||||
else
|
||||
pattern_out.resize(nr);
|
||||
for(size_t k = 0; k < pattern_out.size(); k++)
|
||||
pattern_out[k].clear();
|
||||
//
|
||||
for(size_t i = 0; i < nr; i++)
|
||||
{ CPPAD_ASSERT_UNKNOWN( internal_index[i] < internal_pattern.n_set() );
|
||||
iterator itr(internal_pattern, internal_index[i]);
|
||||
size_t j = *itr;
|
||||
while( j < nc )
|
||||
{ if( transpose )
|
||||
pattern_out[j].insert(i);
|
||||
else
|
||||
pattern_out[i].insert(j);
|
||||
j = *(++itr);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
} } // END_CPPAD_LOCAL_NAMESPACE
|
||||
|
||||
# endif
|
||||
+1102
File diff suppressed because it is too large
Load Diff
+544
@@ -0,0 +1,544 @@
|
||||
# ifndef CPPAD_LOCAL_SPARSE_PACK_HPP
|
||||
# define CPPAD_LOCAL_SPARSE_PACK_HPP
|
||||
|
||||
/* --------------------------------------------------------------------------
|
||||
CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-17 Bradley M. Bell
|
||||
|
||||
CppAD is distributed under multiple licenses. This distribution is under
|
||||
the terms of the
|
||||
Eclipse Public License Version 1.0.
|
||||
|
||||
A copy of this license is included in the COPYING file of this distribution.
|
||||
Please visit http://www.coin-or.org/CppAD/ for information on other licenses.
|
||||
-------------------------------------------------------------------------- */
|
||||
# include <cppad/core/cppad_assert.hpp>
|
||||
# include <cppad/local/pod_vector.hpp>
|
||||
|
||||
namespace CppAD { namespace local { // BEGIN_CPPAD_LOCAL_NAMESPACE
|
||||
/*!
|
||||
\file sparse_pack.hpp
|
||||
Vector of sets of positive integers stored as a packed array of bools.
|
||||
*/
|
||||
|
||||
// ==========================================================================
|
||||
/*!
|
||||
Vector of sets of postivie integers, each set stored as a packed boolean array.
|
||||
*/
|
||||
|
||||
class sparse_pack_const_iterator;
|
||||
class sparse_pack {
|
||||
friend class sparse_pack_const_iterator;
|
||||
private:
|
||||
/// Type used to pack elements (should be the same as corresponding
|
||||
/// typedef in multiple_n_bit() in test_more/sparse_hacobian.cpp)
|
||||
typedef size_t Pack;
|
||||
/// Number of bits per Pack value
|
||||
const size_t n_bit_;
|
||||
/// Number of sets that we are representing
|
||||
/// (set by constructor and resize).
|
||||
size_t n_set_;
|
||||
/// Possible elements in each set are 0, 1, ..., end_ - 1
|
||||
/// (set by constructor and resize).
|
||||
size_t end_;
|
||||
/// Number of \c Pack values necessary to represent \c end_ bits.
|
||||
/// (set by constructor and resize).
|
||||
size_t n_pack_;
|
||||
/// Data for all the sets.
|
||||
pod_vector<Pack> data_;
|
||||
public:
|
||||
/// declare a const iterator
|
||||
typedef sparse_pack_const_iterator const_iterator;
|
||||
|
||||
// -----------------------------------------------------------------
|
||||
/*! Default constructor (no sets)
|
||||
*/
|
||||
sparse_pack(void) :
|
||||
n_bit_( std::numeric_limits<Pack>::digits ),
|
||||
n_set_(0) ,
|
||||
end_(0) ,
|
||||
n_pack_(0)
|
||||
{ }
|
||||
// -----------------------------------------------------------------
|
||||
/*! Make use of copy constructor an error
|
||||
|
||||
\param v
|
||||
vector that we are attempting to make a copy of.
|
||||
*/
|
||||
sparse_pack(const sparse_pack& v) :
|
||||
n_bit_( std::numeric_limits<Pack>::digits )
|
||||
{ // Error:
|
||||
// Probably a sparse_pack argument has been passed by value
|
||||
CPPAD_ASSERT_UNKNOWN(0);
|
||||
}
|
||||
// -----------------------------------------------------------------
|
||||
/*! Destructor
|
||||
*/
|
||||
~sparse_pack(void)
|
||||
{ }
|
||||
// -----------------------------------------------------------------
|
||||
/*! Change number of sets, set end, and initialize all sets as empty
|
||||
|
||||
If \c n_set_in is zero, any memory currently allocated for this object
|
||||
is freed. Otherwise, new memory may be allocated for the sets (if needed).
|
||||
|
||||
\param n_set_in
|
||||
is the number of sets in this vector of sets.
|
||||
|
||||
\param end_in
|
||||
is the maximum element plus one. The minimum element is 0 and
|
||||
end must be greater than zero (unless n_set is also zero).
|
||||
*/
|
||||
void resize(size_t n_set_in, size_t end_in)
|
||||
{ CPPAD_ASSERT_UNKNOWN( n_set_in == 0 || 0 < end_in );
|
||||
n_set_ = n_set_in;
|
||||
end_ = end_in;
|
||||
if( n_set_ == 0 )
|
||||
{ data_.free();
|
||||
return;
|
||||
}
|
||||
// now start a new vector with empty sets
|
||||
Pack zero(0);
|
||||
data_.erase();
|
||||
|
||||
n_pack_ = ( 1 + (end_ - 1) / n_bit_ );
|
||||
size_t i = n_set_ * n_pack_;
|
||||
|
||||
if( i > 0 )
|
||||
{ data_.extend(i);
|
||||
while(i--)
|
||||
data_[i] = zero;
|
||||
}
|
||||
}
|
||||
// -----------------------------------------------------------------
|
||||
/*!
|
||||
Count number of elements in a set.
|
||||
|
||||
\param index
|
||||
is the index in of the set we are counting the elements of.
|
||||
*/
|
||||
size_t number_elements(size_t index) const
|
||||
{ static Pack one(1);
|
||||
CPPAD_ASSERT_UNKNOWN( index < n_set_ );
|
||||
size_t count = 0;
|
||||
for(size_t k = 0; k < n_pack_; k++)
|
||||
{ Pack unit = data_[ index * n_pack_ + k ];
|
||||
Pack mask = one;
|
||||
size_t n = std::min(n_bit_, end_ - n_bit_ * k);
|
||||
for(size_t bit = 0; bit < n; bit++)
|
||||
{ CPPAD_ASSERT_UNKNOWN( mask > one || bit == 0);
|
||||
if( mask & unit )
|
||||
++count;
|
||||
mask = mask << 1;
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
// -----------------------------------------------------------------
|
||||
/*! Add one element to a set.
|
||||
|
||||
\param index
|
||||
is the index for this set in the vector of sets.
|
||||
|
||||
\param element
|
||||
is the element we are adding to the set.
|
||||
|
||||
\par Checked Assertions
|
||||
\li index < n_set_
|
||||
\li element < end_
|
||||
*/
|
||||
void add_element(size_t index, size_t element)
|
||||
{ static Pack one(1);
|
||||
CPPAD_ASSERT_UNKNOWN( index < n_set_ );
|
||||
CPPAD_ASSERT_UNKNOWN( element < end_ );
|
||||
size_t j = element / n_bit_;
|
||||
size_t k = element - j * n_bit_;
|
||||
Pack mask = one << k;
|
||||
data_[ index * n_pack_ + j] |= mask;
|
||||
}
|
||||
// -----------------------------------------------------------------
|
||||
/*! Is an element of a set.
|
||||
|
||||
\param index
|
||||
is the index for this set in the vector of sets.
|
||||
|
||||
\param element
|
||||
is the element we are checking to see if it is in the set.
|
||||
|
||||
\par Checked Assertions
|
||||
\li index < n_set_
|
||||
\li element < end_
|
||||
*/
|
||||
bool is_element(size_t index, size_t element) const
|
||||
{ static Pack one(1);
|
||||
static Pack zero(0);
|
||||
CPPAD_ASSERT_UNKNOWN( index < n_set_ );
|
||||
CPPAD_ASSERT_UNKNOWN( element < end_ );
|
||||
size_t j = element / n_bit_;
|
||||
size_t k = element - j * n_bit_;
|
||||
Pack mask = one << k;
|
||||
return (data_[ index * n_pack_ + j] & mask) != zero;
|
||||
}
|
||||
// -----------------------------------------------------------------
|
||||
/*! Assign the empty set to one of the sets.
|
||||
|
||||
\param target
|
||||
is the index of the set we are setting to the empty set.
|
||||
|
||||
\par Checked Assertions
|
||||
\li target < n_set_
|
||||
*/
|
||||
void clear(size_t target)
|
||||
{ // value with all its bits set to false
|
||||
static Pack zero(0);
|
||||
CPPAD_ASSERT_UNKNOWN( target < n_set_ );
|
||||
size_t t = target * n_pack_;
|
||||
|
||||
size_t j = n_pack_;
|
||||
while(j--)
|
||||
data_[t++] = zero;
|
||||
}
|
||||
// -----------------------------------------------------------------
|
||||
/*! Assign one set equal to another set.
|
||||
|
||||
\param this_target
|
||||
is the index (in this \c sparse_pack object) of the set being assinged.
|
||||
|
||||
\param other_value
|
||||
is the index (in the other \c sparse_pack object) of the
|
||||
that we are using as the value to assign to the target set.
|
||||
|
||||
\param other
|
||||
is the other \c sparse_pack object (which may be the same as this
|
||||
\c sparse_pack object).
|
||||
|
||||
\par Checked Assertions
|
||||
\li this_target < n_set_
|
||||
\li other_value < other.n_set_
|
||||
\li n_pack_ == other.n_pack_
|
||||
*/
|
||||
void assignment(
|
||||
size_t this_target ,
|
||||
size_t other_value ,
|
||||
const sparse_pack& other )
|
||||
{ CPPAD_ASSERT_UNKNOWN( this_target < n_set_ );
|
||||
CPPAD_ASSERT_UNKNOWN( other_value < other.n_set_ );
|
||||
CPPAD_ASSERT_UNKNOWN( n_pack_ == other.n_pack_ );
|
||||
size_t t = this_target * n_pack_;
|
||||
size_t v = other_value * n_pack_;
|
||||
|
||||
size_t j = n_pack_;
|
||||
while(j--)
|
||||
data_[t++] = other.data_[v++];
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------
|
||||
/*! Assing a set equal to the union of two other sets.
|
||||
|
||||
\param this_target
|
||||
is the index (in this \c sparse_pack object) of the set being assinged.
|
||||
|
||||
\param this_left
|
||||
is the index (in this \c sparse_pack object) of the
|
||||
left operand for the union operation.
|
||||
It is OK for \a this_target and \a this_left to be the same value.
|
||||
|
||||
\param other_right
|
||||
is the index (in the other \c sparse_pack object) of the
|
||||
right operand for the union operation.
|
||||
It is OK for \a this_target and \a other_right to be the same value.
|
||||
|
||||
\param other
|
||||
is the other \c sparse_pack object (which may be the same as this
|
||||
\c sparse_pack object).
|
||||
|
||||
\par Checked Assertions
|
||||
\li this_target < n_set_
|
||||
\li this_left < n_set_
|
||||
\li other_right < other.n_set_
|
||||
\li n_pack_ == other.n_pack_
|
||||
*/
|
||||
void binary_union(
|
||||
size_t this_target ,
|
||||
size_t this_left ,
|
||||
size_t other_right ,
|
||||
const sparse_pack& other )
|
||||
{ CPPAD_ASSERT_UNKNOWN( this_target < n_set_ );
|
||||
CPPAD_ASSERT_UNKNOWN( this_left < n_set_ );
|
||||
CPPAD_ASSERT_UNKNOWN( other_right < other.n_set_ );
|
||||
CPPAD_ASSERT_UNKNOWN( n_pack_ == other.n_pack_ );
|
||||
|
||||
size_t t = this_target * n_pack_;
|
||||
size_t l = this_left * n_pack_;
|
||||
size_t r = other_right * n_pack_;
|
||||
|
||||
size_t j = n_pack_;
|
||||
while(j--)
|
||||
data_[t++] = ( data_[l++] | other.data_[r++] );
|
||||
}
|
||||
// -----------------------------------------------------------------
|
||||
/*! Assing a set equal to the intersection of two other sets.
|
||||
|
||||
\param this_target
|
||||
is the index (in this \c sparse_pack object) of the set being assinged.
|
||||
|
||||
\param this_left
|
||||
is the index (in this \c sparse_pack object) of the
|
||||
left operand for the intersection operation.
|
||||
It is OK for \a this_target and \a this_left to be the same value.
|
||||
|
||||
\param other_right
|
||||
is the index (in the other \c sparse_pack object) of the
|
||||
right operand for the intersection operation.
|
||||
It is OK for \a this_target and \a other_right to be the same value.
|
||||
|
||||
\param other
|
||||
is the other \c sparse_pack object (which may be the same as this
|
||||
\c sparse_pack object).
|
||||
|
||||
\par Checked Assertions
|
||||
\li this_target < n_set_
|
||||
\li this_left < n_set_
|
||||
\li other_right < other.n_set_
|
||||
\li n_pack_ == other.n_pack_
|
||||
*/
|
||||
void binary_intersection(
|
||||
size_t this_target ,
|
||||
size_t this_left ,
|
||||
size_t other_right ,
|
||||
const sparse_pack& other )
|
||||
{ CPPAD_ASSERT_UNKNOWN( this_target < n_set_ );
|
||||
CPPAD_ASSERT_UNKNOWN( this_left < n_set_ );
|
||||
CPPAD_ASSERT_UNKNOWN( other_right < other.n_set_ );
|
||||
CPPAD_ASSERT_UNKNOWN( n_pack_ == other.n_pack_ );
|
||||
|
||||
size_t t = this_target * n_pack_;
|
||||
size_t l = this_left * n_pack_;
|
||||
size_t r = other_right * n_pack_;
|
||||
|
||||
size_t j = n_pack_;
|
||||
while(j--)
|
||||
data_[t++] = ( data_[l++] & other.data_[r++] );
|
||||
}
|
||||
// -----------------------------------------------------------------
|
||||
/*! Fetch n_set for vector of sets object.
|
||||
|
||||
\return
|
||||
Number of from sets for this vector of sets object
|
||||
*/
|
||||
size_t n_set(void) const
|
||||
{ return n_set_; }
|
||||
// -----------------------------------------------------------------
|
||||
/*! Fetch end for this vector of sets object.
|
||||
|
||||
\return
|
||||
is the maximum element value plus one (the minimum element value is 0).
|
||||
*/
|
||||
size_t end(void) const
|
||||
{ return end_; }
|
||||
// -----------------------------------------------------------------
|
||||
/*! Amount of memory used by this vector of sets
|
||||
|
||||
\return
|
||||
The amount of memory in units of type unsigned char memory.
|
||||
*/
|
||||
size_t memory(void) const
|
||||
{ return data_.capacity() * sizeof(Pack);
|
||||
}
|
||||
/*!
|
||||
Print the vector of sets (used for debugging)
|
||||
*/
|
||||
void print(void) const;
|
||||
};
|
||||
// ==========================================================================
|
||||
/*!
|
||||
cons_iterator for one set of positive integers in a sparse_pack object.
|
||||
*/
|
||||
class sparse_pack_const_iterator {
|
||||
private:
|
||||
/// Type used to pack elements in sparse_pack
|
||||
typedef sparse_pack::Pack Pack;
|
||||
|
||||
/// data for the entire vector of sets
|
||||
const pod_vector<Pack>& data_;
|
||||
|
||||
/// Number of bits per Pack value
|
||||
const size_t n_bit_;
|
||||
|
||||
/// Number of Pack values necessary to represent end_ bits.
|
||||
const size_t n_pack_;
|
||||
|
||||
/// Possible elements in each set are 0, 1, ..., end_ - 1;
|
||||
const size_t end_;
|
||||
|
||||
/// index of this set in the vector of sets;
|
||||
const size_t index_;
|
||||
|
||||
/// value of the next element in this set
|
||||
/// (use end_ for no such element exists; i.e., past end of the set).
|
||||
size_t next_element_;
|
||||
public:
|
||||
/// construct a const_iterator for a set in a sparse_pack object
|
||||
sparse_pack_const_iterator (const sparse_pack& pack, size_t index)
|
||||
:
|
||||
data_ ( pack.data_ ) ,
|
||||
n_bit_ ( pack.n_bit_ ) ,
|
||||
n_pack_ ( pack.n_pack_ ) ,
|
||||
end_ ( pack.end_ ) ,
|
||||
index_ ( index )
|
||||
{ static Pack one(1);
|
||||
CPPAD_ASSERT_UNKNOWN( index < pack.n_set_ );
|
||||
//
|
||||
next_element_ = 0;
|
||||
if( next_element_ < end_ )
|
||||
{ Pack check = data_[ index_ * n_pack_ + 0 ];
|
||||
if( check & one )
|
||||
return;
|
||||
}
|
||||
// element with index zero is not in this set of integers,
|
||||
// advance to first element or end
|
||||
++(*this);
|
||||
}
|
||||
|
||||
/// advance to next element in this set
|
||||
sparse_pack_const_iterator& operator++(void)
|
||||
{ static Pack one(1);
|
||||
CPPAD_ASSERT_UNKNOWN( next_element_ <= end_ );
|
||||
if( next_element_ == end_ )
|
||||
return *this;
|
||||
//
|
||||
++next_element_;
|
||||
if( next_element_ == end_ )
|
||||
return *this;
|
||||
//
|
||||
// initialize packed data index
|
||||
size_t j = next_element_ / n_bit_;
|
||||
|
||||
// initialize bit index
|
||||
size_t k = next_element_ - j * n_bit_;
|
||||
|
||||
// initialize mask
|
||||
size_t mask = one << k;
|
||||
|
||||
// start search at this packed value
|
||||
Pack check = data_[ index_ * n_pack_ + j ];
|
||||
//
|
||||
while( true )
|
||||
{ // check if this element is in the set
|
||||
if( check & mask )
|
||||
return *this;
|
||||
|
||||
// increment next element before checking this one
|
||||
next_element_++;
|
||||
if( next_element_ == end_ )
|
||||
return *this;
|
||||
|
||||
// shift mask to left one bit so corresponds to next_element_
|
||||
// (use mask <<= 1. not one << k, so compiler knows value)
|
||||
k++;
|
||||
mask <<= 1;
|
||||
CPPAD_ASSERT_UNKNOWN( k <= n_bit_ );
|
||||
|
||||
// check if we must go to next packed data index
|
||||
if( k == n_bit_ )
|
||||
{ // get next packed value
|
||||
k = 0;
|
||||
mask = one;
|
||||
j++;
|
||||
CPPAD_ASSERT_UNKNOWN( j < n_pack_ );
|
||||
check = data_[ index_ * n_pack_ + j ];
|
||||
}
|
||||
}
|
||||
// should never get here
|
||||
CPPAD_ASSERT_UNKNOWN(false);
|
||||
return *this;
|
||||
}
|
||||
|
||||
/// obtain value of this element of the set of positive integers
|
||||
/// (end_ for no such element)
|
||||
size_t operator*(void) const
|
||||
{ return next_element_; }
|
||||
};
|
||||
// =========================================================================
|
||||
/*!
|
||||
Print the vector of sets (used for debugging)
|
||||
*/
|
||||
inline void sparse_pack::print(void) const
|
||||
{ std::cout << "sparse_pack:\n";
|
||||
for(size_t i = 0; i < n_set(); i++)
|
||||
{ std::cout << "set[" << i << "] = {";
|
||||
const_iterator itr(*this, i);
|
||||
while( *itr != end() )
|
||||
{ std::cout << *itr;
|
||||
if( *(++itr) != end() )
|
||||
std::cout << ",";
|
||||
}
|
||||
std::cout << "}\n";
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// ==========================================================================
|
||||
|
||||
/*!
|
||||
Copy a user vector of sets sparsity pattern to an internal sparse_pack object.
|
||||
|
||||
\tparam VectorSet
|
||||
is a simple vector with elements of type std::set<size_t>.
|
||||
|
||||
\param internal
|
||||
The input value of sparisty does not matter.
|
||||
Upon return it contains the same sparsity pattern as \c user
|
||||
(or the transposed sparsity pattern).
|
||||
|
||||
\param user
|
||||
sparsity pattern that we are placing internal.
|
||||
|
||||
\param n_set
|
||||
number of sets (rows) in the internal sparsity pattern.
|
||||
|
||||
\param end
|
||||
end of set value (number of columns) in the interanl sparsity pattern.
|
||||
|
||||
\param transpose
|
||||
if true, the user sparsity patter is the transposed.
|
||||
|
||||
\param error_msg
|
||||
is the error message to display if some values in the user sparstiy
|
||||
pattern are not valid.
|
||||
*/
|
||||
template<class VectorSet>
|
||||
void sparsity_user2internal(
|
||||
sparse_pack& internal ,
|
||||
const VectorSet& user ,
|
||||
size_t n_set ,
|
||||
size_t end ,
|
||||
bool transpose ,
|
||||
const char* error_msg )
|
||||
{ CPPAD_ASSERT_KNOWN(size_t( user.size() ) == n_set * end, error_msg );
|
||||
|
||||
// size of internal sparsity pattern
|
||||
internal.resize(n_set, end);
|
||||
|
||||
if( transpose )
|
||||
{ // transposed pattern case
|
||||
for(size_t j = 0; j < end; j++)
|
||||
{ for(size_t i = 0; i < n_set; i++)
|
||||
{ if( user[ j * n_set + i ] )
|
||||
internal.add_element(i, j);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
else
|
||||
{ for(size_t i = 0; i < n_set; i++)
|
||||
{ for(size_t j = 0; j < end; j++)
|
||||
{ if( user[ i * end + j ] )
|
||||
internal.add_element(i, j);
|
||||
}
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
} } // END_CPPAD_LOCAL_NAMESPACE
|
||||
# endif
|
||||
@@ -0,0 +1,250 @@
|
||||
// $Id: sparse_unary_op.hpp 3865 2017-01-19 01:57:55Z bradbell $
|
||||
# ifndef CPPAD_LOCAL_SPARSE_UNARY_OP_HPP
|
||||
# define CPPAD_LOCAL_SPARSE_UNARY_OP_HPP
|
||||
/* --------------------------------------------------------------------------
|
||||
CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-17 Bradley M. Bell
|
||||
|
||||
CppAD is distributed under multiple licenses. This distribution is under
|
||||
the terms of the
|
||||
Eclipse Public License Version 1.0.
|
||||
|
||||
A copy of this license is included in the COPYING file of this distribution.
|
||||
Please visit http://www.coin-or.org/CppAD/ for information on other licenses.
|
||||
-------------------------------------------------------------------------- */
|
||||
|
||||
namespace CppAD { namespace local { // BEGIN_CPPAD_LOCAL_NAMESPACE
|
||||
/*!
|
||||
\file sparse_unary_op.hpp
|
||||
Forward and reverse mode sparsity patterns for unary operators.
|
||||
*/
|
||||
|
||||
|
||||
/*!
|
||||
Forward mode Jacobian sparsity pattern for all unary operators.
|
||||
|
||||
The C++ source code corresponding to a unary operation has the form
|
||||
\verbatim
|
||||
z = fun(x)
|
||||
\endverbatim
|
||||
where fun is a C++ unary function, or it has the form
|
||||
\verbatim
|
||||
z = x op q
|
||||
\endverbatim
|
||||
where op is a C++ binary unary operator and q is a parameter.
|
||||
|
||||
\tparam Vector_set
|
||||
is the type used for vectors of sets. It can be either
|
||||
sparse_pack or sparse_list.
|
||||
|
||||
\param i_z
|
||||
variable index corresponding to the result for this operation;
|
||||
i.e., z.
|
||||
|
||||
\param i_x
|
||||
variable index corresponding to the argument for this operator;
|
||||
i.e., x.
|
||||
|
||||
|
||||
\param sparsity
|
||||
\b Input: The set with index \a arg[0] in \a sparsity
|
||||
is the sparsity bit pattern for x.
|
||||
This identifies which of the independent variables the variable x
|
||||
depends on.
|
||||
\n
|
||||
\n
|
||||
\b Output: The set with index \a i_z in \a sparsity
|
||||
is the sparsity bit pattern for z.
|
||||
This identifies which of the independent variables the variable z
|
||||
depends on.
|
||||
\n
|
||||
|
||||
\par Checked Assertions:
|
||||
\li \a i_x < \a i_z
|
||||
*/
|
||||
|
||||
template <class Vector_set>
|
||||
inline void forward_sparse_jacobian_unary_op(
|
||||
size_t i_z ,
|
||||
size_t i_x ,
|
||||
Vector_set& sparsity )
|
||||
{
|
||||
// check assumptions
|
||||
CPPAD_ASSERT_UNKNOWN( i_x < i_z );
|
||||
|
||||
sparsity.assignment(i_z, i_x, sparsity);
|
||||
}
|
||||
/*!
|
||||
Reverse mode Jacobian sparsity pattern for all unary operators.
|
||||
|
||||
The C++ source code corresponding to a unary operation has the form
|
||||
\verbatim
|
||||
z = fun(x)
|
||||
\endverbatim
|
||||
where fun is a C++ unary function, or it has the form
|
||||
\verbatim
|
||||
z = x op q
|
||||
\endverbatim
|
||||
where op is a C++ bianry operator and q is a parameter.
|
||||
|
||||
This routine is given the sparsity patterns
|
||||
for a function G(z, y, ... )
|
||||
and it uses them to compute the sparsity patterns for
|
||||
\verbatim
|
||||
H( x , w , u , ... ) = G[ z(x) , x , w , u , ... ]
|
||||
\endverbatim
|
||||
|
||||
\tparam Vector_set
|
||||
is the type used for vectors of sets. It can be either
|
||||
sparse_pack or sparse_list.
|
||||
|
||||
|
||||
\param i_z
|
||||
variable index corresponding to the result for this operation;
|
||||
i.e. the row index in sparsity corresponding to z.
|
||||
|
||||
\param i_x
|
||||
variable index corresponding to the argument for this operator;
|
||||
i.e. the row index in sparsity corresponding to x.
|
||||
|
||||
\param sparsity
|
||||
\b Input:
|
||||
The set with index \a i_z in \a sparsity
|
||||
is the sparsity bit pattern for G with respect to the variable z.
|
||||
\n
|
||||
\b Input:
|
||||
The set with index \a i_x in \a sparsity
|
||||
is the sparsity bit pattern for G with respect to the variable x.
|
||||
\n
|
||||
\b Output:
|
||||
The set with index \a i_x in \a sparsity
|
||||
is the sparsity bit pattern for H with respect to the variable x.
|
||||
|
||||
\par Checked Assertions:
|
||||
\li \a i_x < \a i_z
|
||||
*/
|
||||
|
||||
template <class Vector_set>
|
||||
inline void reverse_sparse_jacobian_unary_op(
|
||||
size_t i_z ,
|
||||
size_t i_x ,
|
||||
Vector_set& sparsity )
|
||||
{
|
||||
// check assumptions
|
||||
CPPAD_ASSERT_UNKNOWN( i_x < i_z );
|
||||
|
||||
sparsity.binary_union(i_x, i_x, i_z, sparsity);
|
||||
|
||||
return;
|
||||
}
|
||||
// ---------------------------------------------------------------------------
|
||||
/*!
|
||||
Reverse mode Hessian sparsity pattern for linear unary operators.
|
||||
|
||||
The C++ source code corresponding to this operation is
|
||||
\verbatim
|
||||
z = fun(x)
|
||||
\endverbatim
|
||||
where fun is a linear functions; e.g. abs, or
|
||||
\verbatim
|
||||
z = x op q
|
||||
\endverbatim
|
||||
where op is a C++ binary operator and q is a parameter.
|
||||
|
||||
\copydetails CppAD::local::reverse_sparse_hessian_unary_op
|
||||
*/
|
||||
template <class Vector_set>
|
||||
inline void reverse_sparse_hessian_linear_unary_op(
|
||||
size_t i_z ,
|
||||
size_t i_x ,
|
||||
bool* rev_jacobian ,
|
||||
const Vector_set& for_jac_sparsity ,
|
||||
Vector_set& rev_hes_sparsity )
|
||||
{
|
||||
// check assumptions
|
||||
CPPAD_ASSERT_UNKNOWN( i_x < i_z );
|
||||
|
||||
rev_hes_sparsity.binary_union(i_x, i_x, i_z, rev_hes_sparsity);
|
||||
|
||||
rev_jacobian[i_x] |= rev_jacobian[i_z];
|
||||
return;
|
||||
}
|
||||
|
||||
/*!
|
||||
Reverse mode Hessian sparsity pattern for non-linear unary operators.
|
||||
|
||||
The C++ source code corresponding to this operation is
|
||||
\verbatim
|
||||
z = fun(x)
|
||||
\endverbatim
|
||||
where fun is a non-linear functions; e.g. sin. or
|
||||
\verbatim
|
||||
z = q / x
|
||||
\endverbatim
|
||||
where q is a parameter.
|
||||
|
||||
|
||||
\copydetails CppAD::local::reverse_sparse_hessian_unary_op
|
||||
*/
|
||||
template <class Vector_set>
|
||||
inline void reverse_sparse_hessian_nonlinear_unary_op(
|
||||
size_t i_z ,
|
||||
size_t i_x ,
|
||||
bool* rev_jacobian ,
|
||||
const Vector_set& for_jac_sparsity ,
|
||||
Vector_set& rev_hes_sparsity )
|
||||
{
|
||||
// check assumptions
|
||||
CPPAD_ASSERT_UNKNOWN( i_x < i_z );
|
||||
|
||||
rev_hes_sparsity.binary_union(i_x, i_x, i_z, rev_hes_sparsity);
|
||||
if( rev_jacobian[i_z] )
|
||||
rev_hes_sparsity.binary_union(i_x, i_x, i_x, for_jac_sparsity);
|
||||
|
||||
rev_jacobian[i_x] |= rev_jacobian[i_z];
|
||||
return;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
/*!
|
||||
Forward mode Hessian sparsity pattern for non-linear unary operators.
|
||||
|
||||
The C++ source code corresponding to this operation is
|
||||
\verbatim
|
||||
w(x) = fun( v(x) )
|
||||
\endverbatim
|
||||
where fun is a non-linear function.
|
||||
|
||||
\param i_v
|
||||
is the index of the argument variable v
|
||||
|
||||
\param for_jac_sparsity
|
||||
for_jac_sparsity(i_v) constains the Jacobian sparsity for v(x).
|
||||
|
||||
\param for_hes_sparsity
|
||||
On input, for_hes_sparsity includes the Hessian sparsity for v(x); i.e.,
|
||||
the sparsity can be a super set.
|
||||
Upon return it includes the Hessian sparsity for w(x)
|
||||
*/
|
||||
template <class Vector_set>
|
||||
inline void forward_sparse_hessian_nonlinear_unary_op(
|
||||
size_t i_v ,
|
||||
const Vector_set& for_jac_sparsity ,
|
||||
Vector_set& for_hes_sparsity )
|
||||
{
|
||||
// set of independent variables that v depends on
|
||||
typename Vector_set::const_iterator itr(for_jac_sparsity, i_v);
|
||||
|
||||
// next independent variables that v depends on
|
||||
size_t i_x = *itr;
|
||||
|
||||
// loop over dependent variables with non-zero partial
|
||||
while( i_x < for_jac_sparsity.end() )
|
||||
{ // N(i_x) = N(i_x) union L(i_v)
|
||||
for_hes_sparsity.binary_union(i_x, i_x, i_v, for_jac_sparsity);
|
||||
i_x = *(++itr);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
} } // END_CPPAD_LOCAL_NAMESPACE
|
||||
# endif
|
||||
+193
@@ -0,0 +1,193 @@
|
||||
# ifndef CPPAD_LOCAL_SQRT_OP_HPP
|
||||
# define CPPAD_LOCAL_SQRT_OP_HPP
|
||||
|
||||
/* --------------------------------------------------------------------------
|
||||
CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-17 Bradley M. Bell
|
||||
|
||||
CppAD is distributed under multiple licenses. This distribution is under
|
||||
the terms of the
|
||||
Eclipse Public License Version 1.0.
|
||||
|
||||
A copy of this license is included in the COPYING file of this distribution.
|
||||
Please visit http://www.coin-or.org/CppAD/ for information on other licenses.
|
||||
-------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
namespace CppAD { namespace local { // BEGIN_CPPAD_LOCAL_NAMESPACE
|
||||
/*!
|
||||
\file sqrt_op.hpp
|
||||
Forward and reverse mode calculations for z = sqrt(x).
|
||||
*/
|
||||
|
||||
|
||||
/*!
|
||||
Compute forward mode Taylor coefficient for result of op = SqrtOp.
|
||||
|
||||
The C++ source code corresponding to this operation is
|
||||
\verbatim
|
||||
z = sqrt(x)
|
||||
\endverbatim
|
||||
|
||||
\copydetails CppAD::local::forward_unary1_op
|
||||
*/
|
||||
template <class Base>
|
||||
inline void forward_sqrt_op(
|
||||
size_t p ,
|
||||
size_t q ,
|
||||
size_t i_z ,
|
||||
size_t i_x ,
|
||||
size_t cap_order ,
|
||||
Base* taylor )
|
||||
{
|
||||
// check assumptions
|
||||
CPPAD_ASSERT_UNKNOWN( NumArg(SqrtOp) == 1 );
|
||||
CPPAD_ASSERT_UNKNOWN( NumRes(SqrtOp) == 1 );
|
||||
CPPAD_ASSERT_UNKNOWN( q < cap_order );
|
||||
CPPAD_ASSERT_UNKNOWN( p <= q );
|
||||
|
||||
// Taylor coefficients corresponding to argument and result
|
||||
Base* x = taylor + i_x * cap_order;
|
||||
Base* z = taylor + i_z * cap_order;
|
||||
|
||||
size_t k;
|
||||
if( p == 0 )
|
||||
{ z[0] = sqrt( x[0] );
|
||||
p++;
|
||||
}
|
||||
for(size_t j = p; j <= q; j++)
|
||||
{
|
||||
z[j] = Base(0.0);
|
||||
for(k = 1; k < j; k++)
|
||||
z[j] -= Base(double(k)) * z[k] * z[j-k];
|
||||
z[j] /= Base(double(j));
|
||||
z[j] += x[j] / Base(2.0);
|
||||
z[j] /= z[0];
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
Multiple direction forward mode Taylor coefficient for op = SqrtOp.
|
||||
|
||||
The C++ source code corresponding to this operation is
|
||||
\verbatim
|
||||
z = sqrt(x)
|
||||
\endverbatim
|
||||
|
||||
\copydetails CppAD::local::forward_unary1_op_dir
|
||||
*/
|
||||
template <class Base>
|
||||
inline void forward_sqrt_op_dir(
|
||||
size_t q ,
|
||||
size_t r ,
|
||||
size_t i_z ,
|
||||
size_t i_x ,
|
||||
size_t cap_order ,
|
||||
Base* taylor )
|
||||
{
|
||||
// check assumptions
|
||||
CPPAD_ASSERT_UNKNOWN( NumArg(SqrtOp) == 1 );
|
||||
CPPAD_ASSERT_UNKNOWN( NumRes(SqrtOp) == 1 );
|
||||
CPPAD_ASSERT_UNKNOWN( 0 < q );
|
||||
CPPAD_ASSERT_UNKNOWN( q < cap_order );
|
||||
|
||||
// Taylor coefficients corresponding to argument and result
|
||||
size_t num_taylor_per_var = (cap_order-1) * r + 1;
|
||||
Base* z = taylor + i_z * num_taylor_per_var;
|
||||
Base* x = taylor + i_x * num_taylor_per_var;
|
||||
|
||||
size_t m = (q-1) * r + 1;
|
||||
for(size_t ell = 0; ell < r; ell++)
|
||||
{ z[m+ell] = Base(0.0);
|
||||
for(size_t k = 1; k < q; k++)
|
||||
z[m+ell] -= Base(double(k)) * z[(k-1)*r+1+ell] * z[(q-k-1)*r+1+ell];
|
||||
z[m+ell] /= Base(double(q));
|
||||
z[m+ell] += x[m+ell] / Base(2.0);
|
||||
z[m+ell] /= z[0];
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
Compute zero order forward mode Taylor coefficient for result of op = SqrtOp.
|
||||
|
||||
The C++ source code corresponding to this operation is
|
||||
\verbatim
|
||||
z = sqrt(x)
|
||||
\endverbatim
|
||||
|
||||
\copydetails CppAD::local::forward_unary1_op_0
|
||||
*/
|
||||
template <class Base>
|
||||
inline void forward_sqrt_op_0(
|
||||
size_t i_z ,
|
||||
size_t i_x ,
|
||||
size_t cap_order ,
|
||||
Base* taylor )
|
||||
{
|
||||
// check assumptions
|
||||
CPPAD_ASSERT_UNKNOWN( NumArg(SqrtOp) == 1 );
|
||||
CPPAD_ASSERT_UNKNOWN( NumRes(SqrtOp) == 1 );
|
||||
CPPAD_ASSERT_UNKNOWN( 0 < cap_order );
|
||||
|
||||
// Taylor coefficients corresponding to argument and result
|
||||
Base* x = taylor + i_x * cap_order;
|
||||
Base* z = taylor + i_z * cap_order;
|
||||
|
||||
z[0] = sqrt( x[0] );
|
||||
}
|
||||
/*!
|
||||
Compute reverse mode partial derivatives for result of op = SqrtOp.
|
||||
|
||||
The C++ source code corresponding to this operation is
|
||||
\verbatim
|
||||
z = sqrt(x)
|
||||
\endverbatim
|
||||
|
||||
\copydetails CppAD::local::reverse_unary1_op
|
||||
*/
|
||||
|
||||
template <class Base>
|
||||
inline void reverse_sqrt_op(
|
||||
size_t d ,
|
||||
size_t i_z ,
|
||||
size_t i_x ,
|
||||
size_t cap_order ,
|
||||
const Base* taylor ,
|
||||
size_t nc_partial ,
|
||||
Base* partial )
|
||||
{
|
||||
// check assumptions
|
||||
CPPAD_ASSERT_UNKNOWN( NumArg(SqrtOp) == 1 );
|
||||
CPPAD_ASSERT_UNKNOWN( NumRes(SqrtOp) == 1 );
|
||||
CPPAD_ASSERT_UNKNOWN( d < cap_order );
|
||||
CPPAD_ASSERT_UNKNOWN( d < nc_partial );
|
||||
|
||||
// Taylor coefficients and partials corresponding to argument
|
||||
Base* px = partial + i_x * nc_partial;
|
||||
|
||||
// Taylor coefficients and partials corresponding to result
|
||||
const Base* z = taylor + i_z * cap_order;
|
||||
Base* pz = partial + i_z * nc_partial;
|
||||
|
||||
|
||||
Base inv_z0 = Base(1.0) / z[0];
|
||||
|
||||
// number of indices to access
|
||||
size_t j = d;
|
||||
size_t k;
|
||||
while(j)
|
||||
{
|
||||
|
||||
// scale partial w.r.t. z[j]
|
||||
pz[j] = azmul(pz[j], inv_z0);
|
||||
|
||||
pz[0] -= azmul(pz[j], z[j]);
|
||||
px[j] += pz[j] / Base(2.0);
|
||||
for(k = 1; k < j; k++)
|
||||
pz[k] -= azmul(pz[j], z[j-k]);
|
||||
--j;
|
||||
}
|
||||
px[0] += azmul(pz[0], inv_z0) / Base(2.0);
|
||||
}
|
||||
|
||||
} } // END_CPPAD_LOCAL_NAMESPACE
|
||||
# endif
|
||||
+53
@@ -0,0 +1,53 @@
|
||||
// $Id: std_set.hpp 3845 2016-11-19 01:50:47Z bradbell $
|
||||
# ifndef CPPAD_LOCAL_STD_SET_HPP
|
||||
# define CPPAD_LOCAL_STD_SET_HPP
|
||||
|
||||
/* --------------------------------------------------------------------------
|
||||
CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-16 Bradley M. Bell
|
||||
|
||||
CppAD is distributed under multiple licenses. This distribution is under
|
||||
the terms of the
|
||||
Eclipse Public License Version 1.0.
|
||||
|
||||
A copy of this license is included in the COPYING file of this distribution.
|
||||
Please visit http://www.coin-or.org/CppAD/ for information on other licenses.
|
||||
-------------------------------------------------------------------------- */
|
||||
|
||||
# include <cppad/core/define.hpp>
|
||||
|
||||
// needed before one can use CPPAD_ASSERT_FIRST_CALL_NOT_PARALLEL
|
||||
# include <cppad/utility/thread_alloc.hpp>
|
||||
|
||||
namespace CppAD { namespace local { // BEGIN_CPPAD_LOCAL_NAMESPACE
|
||||
/*!
|
||||
\file std_set.hpp
|
||||
Two constant standard sets (currently used for concept checking).
|
||||
*/
|
||||
|
||||
/*!
|
||||
A standard set with one element.
|
||||
*/
|
||||
template <class Scalar>
|
||||
const std::set<Scalar>& one_element_std_set(void)
|
||||
{ CPPAD_ASSERT_FIRST_CALL_NOT_PARALLEL;
|
||||
static std::set<Scalar> one;
|
||||
if( one.empty() )
|
||||
one.insert(1);
|
||||
return one;
|
||||
}
|
||||
/*!
|
||||
A standard set with a two elements.
|
||||
*/
|
||||
template <class Scalar>
|
||||
const std::set<Scalar>& two_element_std_set(void)
|
||||
{ CPPAD_ASSERT_FIRST_CALL_NOT_PARALLEL;
|
||||
static std::set<Scalar> two;
|
||||
if( two.empty() )
|
||||
{ two.insert(1);
|
||||
two.insert(2);
|
||||
}
|
||||
return two;
|
||||
}
|
||||
|
||||
} } // END_CPPAD_LOCAL_NAMESPACE
|
||||
# endif
|
||||
+498
@@ -0,0 +1,498 @@
|
||||
// $Id: store_op.hpp 3865 2017-01-19 01:57:55Z bradbell $
|
||||
# ifndef CPPAD_LOCAL_STORE_OP_HPP
|
||||
# define CPPAD_LOCAL_STORE_OP_HPP
|
||||
|
||||
/* --------------------------------------------------------------------------
|
||||
CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-17 Bradley M. Bell
|
||||
|
||||
CppAD is distributed under multiple licenses. This distribution is under
|
||||
the terms of the
|
||||
Eclipse Public License Version 1.0.
|
||||
|
||||
A copy of this license is included in the COPYING file of this distribution.
|
||||
Please visit http://www.coin-or.org/CppAD/ for information on other licenses.
|
||||
-------------------------------------------------------------------------- */
|
||||
|
||||
namespace CppAD { namespace local { // BEGIN_CPPAD_LOCAL_NAMESPACE
|
||||
/*!
|
||||
\file store_op.hpp
|
||||
Changing the current value of a VecAD element.
|
||||
*/
|
||||
/*
|
||||
==============================================================================
|
||||
<!-- define preamble -->
|
||||
The C++ source code corresponding to this operation is
|
||||
\verbatim
|
||||
v[x] = y
|
||||
\endverbatim
|
||||
where v is a VecAD<Base> vector, x is an AD<Base> object,
|
||||
and y is AD<Base> or Base objects.
|
||||
We define the index corresponding to v[x] by
|
||||
\verbatim
|
||||
i_v_x = index_by_ind[ arg[0] + i_vec ]
|
||||
\endverbatim
|
||||
where i_vec is defined under the heading arg[1] below:
|
||||
<!-- end preamble -->
|
||||
==============================================================================
|
||||
*/
|
||||
/*!
|
||||
Shared documentation for zero order forward implementation of
|
||||
op = StppOp, StpvOp, StvpOp, or StvvOp (not called).
|
||||
|
||||
<!-- replace preamble -->
|
||||
The C++ source code corresponding to this operation is
|
||||
\verbatim
|
||||
v[x] = y
|
||||
\endverbatim
|
||||
where v is a VecAD<Base> vector, x is an AD<Base> object,
|
||||
and y is AD<Base> or Base objects.
|
||||
We define the index corresponding to v[x] by
|
||||
\verbatim
|
||||
i_v_x = index_by_ind[ arg[0] + i_vec ]
|
||||
\endverbatim
|
||||
where i_vec is defined under the heading arg[1] below:
|
||||
<!-- end preamble -->
|
||||
|
||||
\tparam Base
|
||||
base type for the operator; i.e., this operation was recorded
|
||||
using AD<Base> and computations by this routine are done using type Base.
|
||||
|
||||
\param i_z
|
||||
is the index corresponding to the previous variable on the tape
|
||||
(only used for error checking).
|
||||
|
||||
\param arg
|
||||
\n
|
||||
arg[0]
|
||||
\n
|
||||
is the offset of this VecAD vector relative to the beginning
|
||||
of the isvar_by_ind and index_by_ind arrays.
|
||||
\n
|
||||
\n
|
||||
arg[1]
|
||||
\n
|
||||
If this is a StppOp or StpvOp operation (if x is a parameter),
|
||||
i_vec is defined by
|
||||
\verbatim
|
||||
i_vec = arg[1]
|
||||
\endverbatim
|
||||
If this is a StvpOp or StvvOp operation (if x is a variable),
|
||||
i_vec is defined by
|
||||
\verbatim
|
||||
i_vec = floor( taylor[ arg[1] * cap_order + 0 ] )
|
||||
\endverbatim
|
||||
where floor(c) is the greatest integer less that or equal c.
|
||||
\n
|
||||
\n
|
||||
arg[2]
|
||||
\n
|
||||
index corresponding to the third operand for this operator;
|
||||
i.e. the index corresponding to y.
|
||||
|
||||
\param num_par
|
||||
is the total number of parameters on the tape
|
||||
(only used for error checking).
|
||||
|
||||
\param cap_order
|
||||
number of columns in the matrix containing the Taylor coefficients.
|
||||
|
||||
\param taylor
|
||||
In StvpOp and StvvOp cases, <code><taylor[ arg[1] * cap_order + 0 ]</code>
|
||||
is used to compute the index in the definition of i_vec above.
|
||||
|
||||
\param isvar_by_ind
|
||||
If y is a varable (StpvOp and StvvOp cases),
|
||||
<code>isvar_by_ind[ arg[0] + i_vec ] </code> is set to true.
|
||||
Otherwise y is a paraemter (StppOp and StvpOp cases) and
|
||||
<code>isvar_by_ind[ arg[0] + i_vec ] </code> is set to false.
|
||||
|
||||
\param index_by_ind
|
||||
<code>index_by_ind[ arg[0] - 1 ]</code>
|
||||
is the number of elements in the user vector containing this element.
|
||||
The value <code>index_by_ind[ arg[0] + i_vec]</code>
|
||||
is set equal to arg[2].
|
||||
|
||||
\par Check User Errors
|
||||
\li Check that the index is with in range; i.e.
|
||||
<code>i_vec < index_by_ind[ arg[0] - 1 ]</code>
|
||||
Note that, if x is a parameter,
|
||||
the corresponding vector index and it does not change.
|
||||
In this case, the error above should be detected during tape recording.
|
||||
|
||||
\par Checked Assertions
|
||||
\li NumArg(op) == 3
|
||||
\li NumRes(op) == 0
|
||||
\li 0 < arg[0]
|
||||
\li if y is a parameter, arg[2] < num_par
|
||||
*/
|
||||
template <class Base>
|
||||
inline void forward_store_op_0(
|
||||
size_t i_z ,
|
||||
const addr_t* arg ,
|
||||
size_t num_par ,
|
||||
size_t cap_order ,
|
||||
Base* taylor ,
|
||||
bool* isvar_by_ind ,
|
||||
size_t* index_by_ind )
|
||||
{
|
||||
// This routine is only for documentaiton, it should not be used
|
||||
CPPAD_ASSERT_UNKNOWN( false );
|
||||
}
|
||||
/*!
|
||||
Shared documnetation for sparsity operations corresponding to
|
||||
op = StpvOp or StvvOp (not called).
|
||||
|
||||
\tparam Vector_set
|
||||
is the type used for vectors of sets. It can be either
|
||||
sparse_pack or sparse_list.
|
||||
|
||||
\param op
|
||||
is the code corresponding to this operator;
|
||||
i.e., StpvOp, StvpOp, or StvvOp.
|
||||
|
||||
\param arg
|
||||
\n
|
||||
\a arg[0]
|
||||
is the offset corresponding to this VecAD vector in the combined array.
|
||||
\n
|
||||
\n
|
||||
\a arg[2]
|
||||
\n
|
||||
The set with index \a arg[2] in \a var_sparsity
|
||||
is the sparsity pattern corresponding to y.
|
||||
(Note that \a arg[2] > 0 because y is a variable.)
|
||||
|
||||
\param num_combined
|
||||
is the total number of elements in the VecAD address array.
|
||||
|
||||
\param combined
|
||||
\a combined [ arg[0] - 1 ]
|
||||
is the index of the set in \a vecad_sparsity corresponding
|
||||
to the sparsity pattern for the vector v.
|
||||
We use the notation i_v below which is defined by
|
||||
\verbatim
|
||||
i_v = combined[ \a arg[0] - 1 ]
|
||||
\endverbatim
|
||||
|
||||
\param var_sparsity
|
||||
The set with index \a arg[2] in \a var_sparsity
|
||||
is the sparsity pattern for y.
|
||||
This is an input for forward mode operations.
|
||||
For reverse mode operations:
|
||||
The sparsity pattern for v is added to the spartisy pattern for y.
|
||||
|
||||
\param vecad_sparsity
|
||||
The set with index \a i_v in \a vecad_sparsity
|
||||
is the sparsity pattern for v.
|
||||
This is an input for reverse mode operations.
|
||||
For forward mode operations, the sparsity pattern for y is added
|
||||
to the sparsity pattern for the vector v.
|
||||
|
||||
\par Checked Assertions
|
||||
\li NumArg(op) == 3
|
||||
\li NumRes(op) == 0
|
||||
\li 0 < \a arg[0]
|
||||
\li \a arg[0] < \a num_combined
|
||||
\li \a arg[2] < \a var_sparsity.n_set()
|
||||
\li i_v < \a vecad_sparsity.n_set()
|
||||
*/
|
||||
template <class Vector_set>
|
||||
inline void sparse_store_op(
|
||||
OpCode op ,
|
||||
const addr_t* arg ,
|
||||
size_t num_combined ,
|
||||
const size_t* combined ,
|
||||
Vector_set& var_sparsity ,
|
||||
Vector_set& vecad_sparsity )
|
||||
{
|
||||
// This routine is only for documentaiton, it should not be used
|
||||
CPPAD_ASSERT_UNKNOWN( false );
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
Zero order forward mode implementation of op = StppOp.
|
||||
|
||||
\copydetails CppAD::local::forward_store_op_0
|
||||
*/
|
||||
template <class Base>
|
||||
inline void forward_store_pp_op_0(
|
||||
size_t i_z ,
|
||||
const addr_t* arg ,
|
||||
size_t num_par ,
|
||||
size_t cap_order ,
|
||||
Base* taylor ,
|
||||
bool* isvar_by_ind ,
|
||||
size_t* index_by_ind )
|
||||
{ size_t i_vec = arg[1];
|
||||
|
||||
// Because the index is a parameter, this indexing error should be
|
||||
// caught and reported to the user when the tape is recording.
|
||||
CPPAD_ASSERT_UNKNOWN( i_vec < index_by_ind[ arg[0] - 1 ] );
|
||||
|
||||
CPPAD_ASSERT_UNKNOWN( NumArg(StppOp) == 3 );
|
||||
CPPAD_ASSERT_UNKNOWN( NumRes(StppOp) == 0 );
|
||||
CPPAD_ASSERT_UNKNOWN( 0 < arg[0] );
|
||||
CPPAD_ASSERT_UNKNOWN( size_t(arg[2]) < num_par );
|
||||
|
||||
isvar_by_ind[ arg[0] + i_vec ] = false;
|
||||
index_by_ind[ arg[0] + i_vec ] = arg[2];
|
||||
}
|
||||
|
||||
/*!
|
||||
Zero order forward mode implementation of op = StpvOp.
|
||||
|
||||
\copydetails CppAD::local::forward_store_op_0
|
||||
*/
|
||||
template <class Base>
|
||||
inline void forward_store_pv_op_0(
|
||||
size_t i_z ,
|
||||
const addr_t* arg ,
|
||||
size_t num_par ,
|
||||
size_t cap_order ,
|
||||
Base* taylor ,
|
||||
bool* isvar_by_ind ,
|
||||
size_t* index_by_ind )
|
||||
{ size_t i_vec = arg[1];
|
||||
|
||||
// Because the index is a parameter, this indexing error should be
|
||||
// caught and reported to the user when the tape is recording.
|
||||
CPPAD_ASSERT_UNKNOWN( i_vec < index_by_ind[ arg[0] - 1 ] );
|
||||
|
||||
CPPAD_ASSERT_UNKNOWN( NumArg(StpvOp) == 3 );
|
||||
CPPAD_ASSERT_UNKNOWN( NumRes(StpvOp) == 0 );
|
||||
CPPAD_ASSERT_UNKNOWN( 0 < arg[0] );
|
||||
|
||||
isvar_by_ind[ arg[0] + i_vec ] = true;
|
||||
index_by_ind[ arg[0] + i_vec ] = arg[2];
|
||||
}
|
||||
|
||||
/*!
|
||||
Zero order forward mode implementation of op = StvpOp.
|
||||
|
||||
\copydetails CppAD::local::forward_store_op_0
|
||||
*/
|
||||
template <class Base>
|
||||
inline void forward_store_vp_op_0(
|
||||
size_t i_z ,
|
||||
const addr_t* arg ,
|
||||
size_t num_par ,
|
||||
size_t cap_order ,
|
||||
Base* taylor ,
|
||||
bool* isvar_by_ind ,
|
||||
size_t* index_by_ind )
|
||||
{
|
||||
size_t i_vec = Integer( taylor[ arg[1] * cap_order + 0 ] );
|
||||
CPPAD_ASSERT_KNOWN(
|
||||
i_vec < index_by_ind[ arg[0] - 1 ] ,
|
||||
"VecAD: index during zero order forward sweep is out of range"
|
||||
);
|
||||
|
||||
CPPAD_ASSERT_UNKNOWN( NumArg(StvpOp) == 3 );
|
||||
CPPAD_ASSERT_UNKNOWN( NumRes(StvpOp) == 0 );
|
||||
CPPAD_ASSERT_UNKNOWN( 0 < arg[0] );
|
||||
CPPAD_ASSERT_UNKNOWN( size_t(arg[2]) < num_par );
|
||||
|
||||
isvar_by_ind[ arg[0] + i_vec ] = false;
|
||||
index_by_ind[ arg[0] + i_vec ] = arg[2];
|
||||
}
|
||||
|
||||
/*!
|
||||
Zero order forward mode implementation of op = StvvOp.
|
||||
|
||||
\copydetails CppAD::local::forward_store_op_0
|
||||
*/
|
||||
template <class Base>
|
||||
inline void forward_store_vv_op_0(
|
||||
size_t i_z ,
|
||||
const addr_t* arg ,
|
||||
size_t num_par ,
|
||||
size_t cap_order ,
|
||||
Base* taylor ,
|
||||
bool* isvar_by_ind ,
|
||||
size_t* index_by_ind )
|
||||
{
|
||||
size_t i_vec = Integer( taylor[ arg[1] * cap_order + 0 ] );
|
||||
CPPAD_ASSERT_KNOWN(
|
||||
i_vec < index_by_ind[ arg[0] - 1 ] ,
|
||||
"VecAD: index during zero order forward sweep is out of range"
|
||||
);
|
||||
|
||||
CPPAD_ASSERT_UNKNOWN( NumArg(StvpOp) == 3 );
|
||||
CPPAD_ASSERT_UNKNOWN( NumRes(StvpOp) == 0 );
|
||||
CPPAD_ASSERT_UNKNOWN( 0 < arg[0] );
|
||||
|
||||
isvar_by_ind[ arg[0] + i_vec ] = true;
|
||||
index_by_ind[ arg[0] + i_vec ] = arg[2];
|
||||
}
|
||||
|
||||
/*!
|
||||
Forward mode sparsity operations for StpvOp and StvvOp
|
||||
|
||||
<!-- replace preamble -->
|
||||
The C++ source code corresponding to this operation is
|
||||
\verbatim
|
||||
v[x] = y
|
||||
\endverbatim
|
||||
where v is a VecAD<Base> vector, x is an AD<Base> object,
|
||||
and y is AD<Base> or Base objects.
|
||||
We define the index corresponding to v[x] by
|
||||
\verbatim
|
||||
i_v_x = index_by_ind[ arg[0] + i_vec ]
|
||||
\endverbatim
|
||||
where i_vec is defined under the heading arg[1] below:
|
||||
<!-- end preamble -->
|
||||
|
||||
\param dependency
|
||||
is this a dependency (or sparsity) calculation.
|
||||
|
||||
\copydetails CppAD::local::sparse_store_op
|
||||
*/
|
||||
template <class Vector_set>
|
||||
inline void forward_sparse_store_op(
|
||||
bool dependency ,
|
||||
OpCode op ,
|
||||
const addr_t* arg ,
|
||||
size_t num_combined ,
|
||||
const size_t* combined ,
|
||||
Vector_set& var_sparsity ,
|
||||
Vector_set& vecad_sparsity )
|
||||
{
|
||||
CPPAD_ASSERT_UNKNOWN( NumArg(op) == 3 );
|
||||
CPPAD_ASSERT_UNKNOWN( NumRes(op) == 0 );
|
||||
CPPAD_ASSERT_UNKNOWN( 0 < arg[0] );
|
||||
CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < num_combined );
|
||||
size_t i_v = combined[ arg[0] - 1 ];
|
||||
CPPAD_ASSERT_UNKNOWN( i_v < vecad_sparsity.n_set() );
|
||||
CPPAD_ASSERT_UNKNOWN( size_t(arg[2]) < var_sparsity.n_set() );
|
||||
|
||||
if( dependency & ( (op == StvvOp) | (op == StvpOp) ) )
|
||||
vecad_sparsity.binary_union(i_v, i_v, arg[1], var_sparsity);
|
||||
|
||||
if( (op == StpvOp) | (op == StvvOp ) )
|
||||
vecad_sparsity.binary_union(i_v, i_v, arg[2], var_sparsity);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/*!
|
||||
Reverse mode sparsity operations for StpvOp, StvpOp, and StvvOp
|
||||
|
||||
<!-- replace preamble -->
|
||||
The C++ source code corresponding to this operation is
|
||||
\verbatim
|
||||
v[x] = y
|
||||
\endverbatim
|
||||
where v is a VecAD<Base> vector, x is an AD<Base> object,
|
||||
and y is AD<Base> or Base objects.
|
||||
We define the index corresponding to v[x] by
|
||||
\verbatim
|
||||
i_v_x = index_by_ind[ arg[0] + i_vec ]
|
||||
\endverbatim
|
||||
where i_vec is defined under the heading arg[1] below:
|
||||
<!-- end preamble -->
|
||||
|
||||
This routine is given the sparsity patterns for
|
||||
G(v[x], y , w , u ... ) and it uses them to compute the
|
||||
sparsity patterns for
|
||||
\verbatim
|
||||
H(y , w , u , ... ) = G[ v[x], y , w , u , ... ]
|
||||
\endverbatim
|
||||
|
||||
\param dependency
|
||||
is this a dependency (or sparsity) calculation.
|
||||
|
||||
\copydetails CppAD::local::sparse_store_op
|
||||
*/
|
||||
template <class Vector_set>
|
||||
inline void reverse_sparse_jacobian_store_op(
|
||||
bool dependency ,
|
||||
OpCode op ,
|
||||
const addr_t* arg ,
|
||||
size_t num_combined ,
|
||||
const size_t* combined ,
|
||||
Vector_set& var_sparsity ,
|
||||
Vector_set& vecad_sparsity )
|
||||
{
|
||||
CPPAD_ASSERT_UNKNOWN( NumArg(op) == 3 );
|
||||
CPPAD_ASSERT_UNKNOWN( NumRes(op) == 0 );
|
||||
CPPAD_ASSERT_UNKNOWN( 0 < arg[0] );
|
||||
CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < num_combined );
|
||||
size_t i_v = combined[ arg[0] - 1 ];
|
||||
CPPAD_ASSERT_UNKNOWN( i_v < vecad_sparsity.n_set() );
|
||||
CPPAD_ASSERT_UNKNOWN( size_t(arg[2]) < var_sparsity.n_set() );
|
||||
|
||||
if( dependency & ( (op == StvpOp) | (op == StvvOp) ) )
|
||||
var_sparsity.binary_union(arg[1], arg[1], i_v, vecad_sparsity);
|
||||
if( (op == StpvOp) | (op == StvvOp) )
|
||||
var_sparsity.binary_union(arg[2], arg[2], i_v, vecad_sparsity);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/*!
|
||||
Reverse mode sparsity operations for StpvOp and StvvOp
|
||||
|
||||
<!-- replace preamble -->
|
||||
The C++ source code corresponding to this operation is
|
||||
\verbatim
|
||||
v[x] = y
|
||||
\endverbatim
|
||||
where v is a VecAD<Base> vector, x is an AD<Base> object,
|
||||
and y is AD<Base> or Base objects.
|
||||
We define the index corresponding to v[x] by
|
||||
\verbatim
|
||||
i_v_x = index_by_ind[ arg[0] + i_vec ]
|
||||
\endverbatim
|
||||
where i_vec is defined under the heading arg[1] below:
|
||||
<!-- end preamble -->
|
||||
|
||||
This routine is given the sparsity patterns for
|
||||
G(v[x], y , w , u ... )
|
||||
and it uses them to compute the sparsity patterns for
|
||||
\verbatim
|
||||
H(y , w , u , ... ) = G[ v[x], y , w , u , ... ]
|
||||
\endverbatim
|
||||
|
||||
\copydetails CppAD::local::sparse_store_op
|
||||
|
||||
\param var_jacobian
|
||||
\a var_jacobian[ \a arg[2] ]
|
||||
is false (true) if the Jacobian of G with respect to y is always zero
|
||||
(may be non-zero).
|
||||
|
||||
\param vecad_jacobian
|
||||
\a vecad_jacobian[i_v]
|
||||
is false (true) if the Jacobian with respect to x is always zero
|
||||
(may be non-zero).
|
||||
On input, it corresponds to the function G,
|
||||
and on output it corresponds to the function H.
|
||||
*/
|
||||
template <class Vector_set>
|
||||
inline void reverse_sparse_hessian_store_op(
|
||||
OpCode op ,
|
||||
const addr_t* arg ,
|
||||
size_t num_combined ,
|
||||
const size_t* combined ,
|
||||
Vector_set& var_sparsity ,
|
||||
Vector_set& vecad_sparsity ,
|
||||
bool* var_jacobian ,
|
||||
bool* vecad_jacobian )
|
||||
{
|
||||
CPPAD_ASSERT_UNKNOWN( NumArg(op) == 3 );
|
||||
CPPAD_ASSERT_UNKNOWN( NumRes(op) == 0 );
|
||||
CPPAD_ASSERT_UNKNOWN( 0 < arg[0] );
|
||||
CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < num_combined );
|
||||
size_t i_v = combined[ arg[0] - 1 ];
|
||||
CPPAD_ASSERT_UNKNOWN( i_v < vecad_sparsity.n_set() );
|
||||
CPPAD_ASSERT_UNKNOWN( size_t(arg[2]) < var_sparsity.n_set() );
|
||||
|
||||
var_sparsity.binary_union(arg[2], arg[2], i_v, vecad_sparsity);
|
||||
|
||||
var_jacobian[ arg[2] ] |= vecad_jacobian[i_v];
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
} } // END_CPPAD_LOCAL_NAMESPACE
|
||||
# endif
|
||||
+501
@@ -0,0 +1,501 @@
|
||||
// $Id: sub_op.hpp 3865 2017-01-19 01:57:55Z bradbell $
|
||||
# ifndef CPPAD_LOCAL_SUB_OP_HPP
|
||||
# define CPPAD_LOCAL_SUB_OP_HPP
|
||||
|
||||
/* --------------------------------------------------------------------------
|
||||
CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-17 Bradley M. Bell
|
||||
|
||||
CppAD is distributed under multiple licenses. This distribution is under
|
||||
the terms of the
|
||||
Eclipse Public License Version 1.0.
|
||||
|
||||
A copy of this license is included in the COPYING file of this distribution.
|
||||
Please visit http://www.coin-or.org/CppAD/ for information on other licenses.
|
||||
-------------------------------------------------------------------------- */
|
||||
|
||||
namespace CppAD { namespace local { // BEGIN_CPPAD_LOCAL_NAMESPACE
|
||||
/*!
|
||||
\file sub_op.hpp
|
||||
Forward and reverse mode calculations for z = x - y.
|
||||
*/
|
||||
|
||||
// --------------------------- Subvv -----------------------------------------
|
||||
/*!
|
||||
Compute forward mode Taylor coefficients for result of op = SubvvOp.
|
||||
|
||||
The C++ source code corresponding to this operation is
|
||||
\verbatim
|
||||
z = x - y
|
||||
\endverbatim
|
||||
In the documentation below,
|
||||
this operations is for the case where both x and y are variables
|
||||
and the argument \a parameter is not used.
|
||||
|
||||
\copydetails CppAD::local::forward_binary_op
|
||||
*/
|
||||
|
||||
template <class Base>
|
||||
inline void forward_subvv_op(
|
||||
size_t p ,
|
||||
size_t q ,
|
||||
size_t i_z ,
|
||||
const addr_t* arg ,
|
||||
const Base* parameter ,
|
||||
size_t cap_order ,
|
||||
Base* taylor )
|
||||
{
|
||||
// check assumptions
|
||||
CPPAD_ASSERT_UNKNOWN( NumArg(SubvvOp) == 2 );
|
||||
CPPAD_ASSERT_UNKNOWN( NumRes(SubvvOp) == 1 );
|
||||
CPPAD_ASSERT_UNKNOWN( q < cap_order );
|
||||
CPPAD_ASSERT_UNKNOWN( p <= q );
|
||||
|
||||
// Taylor coefficients corresponding to arguments and result
|
||||
Base* x = taylor + arg[0] * cap_order;
|
||||
Base* y = taylor + arg[1] * cap_order;
|
||||
Base* z = taylor + i_z * cap_order;
|
||||
|
||||
for(size_t d = p; d <= q; d++)
|
||||
z[d] = x[d] - y[d];
|
||||
}
|
||||
/*!
|
||||
Multiple directions forward mode Taylor coefficients for op = SubvvOp.
|
||||
|
||||
The C++ source code corresponding to this operation is
|
||||
\verbatim
|
||||
z = x - y
|
||||
\endverbatim
|
||||
In the documentation below,
|
||||
this operations is for the case where both x and y are variables
|
||||
and the argument \a parameter is not used.
|
||||
|
||||
\copydetails CppAD::local::forward_binary_op_dir
|
||||
*/
|
||||
|
||||
template <class Base>
|
||||
inline void forward_subvv_op_dir(
|
||||
size_t q ,
|
||||
size_t r ,
|
||||
size_t i_z ,
|
||||
const addr_t* arg ,
|
||||
const Base* parameter ,
|
||||
size_t cap_order ,
|
||||
Base* taylor )
|
||||
{
|
||||
// check assumptions
|
||||
CPPAD_ASSERT_UNKNOWN( NumArg(SubvvOp) == 2 );
|
||||
CPPAD_ASSERT_UNKNOWN( NumRes(SubvvOp) == 1 );
|
||||
CPPAD_ASSERT_UNKNOWN( 0 < q );
|
||||
CPPAD_ASSERT_UNKNOWN( q < cap_order );
|
||||
|
||||
// Taylor coefficients corresponding to arguments and result
|
||||
size_t num_taylor_per_var = (cap_order-1) * r + 1;
|
||||
size_t m = (q-1) * r + 1;
|
||||
Base* x = taylor + arg[0] * num_taylor_per_var + m;
|
||||
Base* y = taylor + arg[1] * num_taylor_per_var + m;
|
||||
Base* z = taylor + i_z * num_taylor_per_var + m;
|
||||
|
||||
for(size_t ell = 0; ell < r; ell++)
|
||||
z[ell] = x[ell] - y[ell];
|
||||
}
|
||||
|
||||
/*!
|
||||
Compute zero order forward mode Taylor coefficients for result of op = SubvvOp.
|
||||
|
||||
The C++ source code corresponding to this operation is
|
||||
\verbatim
|
||||
z = x - y
|
||||
\endverbatim
|
||||
In the documentation below,
|
||||
this operations is for the case where both x and y are variables
|
||||
and the argument \a parameter is not used.
|
||||
|
||||
\copydetails CppAD::local::forward_binary_op_0
|
||||
*/
|
||||
|
||||
template <class Base>
|
||||
inline void forward_subvv_op_0(
|
||||
size_t i_z ,
|
||||
const addr_t* arg ,
|
||||
const Base* parameter ,
|
||||
size_t cap_order ,
|
||||
Base* taylor )
|
||||
{
|
||||
// check assumptions
|
||||
CPPAD_ASSERT_UNKNOWN( NumArg(SubvvOp) == 2 );
|
||||
CPPAD_ASSERT_UNKNOWN( NumRes(SubvvOp) == 1 );
|
||||
|
||||
// Taylor coefficients corresponding to arguments and result
|
||||
Base* x = taylor + arg[0] * cap_order;
|
||||
Base* y = taylor + arg[1] * cap_order;
|
||||
Base* z = taylor + i_z * cap_order;
|
||||
|
||||
z[0] = x[0] - y[0];
|
||||
}
|
||||
|
||||
/*!
|
||||
Compute reverse mode partial derivatives for result of op = SubvvOp.
|
||||
|
||||
The C++ source code corresponding to this operation is
|
||||
\verbatim
|
||||
z = x - y
|
||||
\endverbatim
|
||||
In the documentation below,
|
||||
this operations is for the case where both x and y are variables
|
||||
and the argument \a parameter is not used.
|
||||
|
||||
\copydetails CppAD::local::reverse_binary_op
|
||||
*/
|
||||
|
||||
template <class Base>
|
||||
inline void reverse_subvv_op(
|
||||
size_t d ,
|
||||
size_t i_z ,
|
||||
const addr_t* arg ,
|
||||
const Base* parameter ,
|
||||
size_t cap_order ,
|
||||
const Base* taylor ,
|
||||
size_t nc_partial ,
|
||||
Base* partial )
|
||||
{
|
||||
// check assumptions
|
||||
CPPAD_ASSERT_UNKNOWN( NumArg(SubvvOp) == 2 );
|
||||
CPPAD_ASSERT_UNKNOWN( NumRes(SubvvOp) == 1 );
|
||||
CPPAD_ASSERT_UNKNOWN( d < cap_order );
|
||||
CPPAD_ASSERT_UNKNOWN( d < nc_partial );
|
||||
|
||||
// Partial derivatives corresponding to arguments and result
|
||||
Base* px = partial + arg[0] * nc_partial;
|
||||
Base* py = partial + arg[1] * nc_partial;
|
||||
Base* pz = partial + i_z * nc_partial;
|
||||
|
||||
// number of indices to access
|
||||
size_t i = d + 1;
|
||||
while(i)
|
||||
{ --i;
|
||||
px[i] += pz[i];
|
||||
py[i] -= pz[i];
|
||||
}
|
||||
}
|
||||
|
||||
// --------------------------- Subpv -----------------------------------------
|
||||
/*!
|
||||
Compute forward mode Taylor coefficients for result of op = SubpvOp.
|
||||
|
||||
The C++ source code corresponding to this operation is
|
||||
\verbatim
|
||||
z = x - y
|
||||
\endverbatim
|
||||
In the documentation below,
|
||||
this operations is for the case where x is a parameter and y is a variable.
|
||||
|
||||
\copydetails CppAD::local::forward_binary_op
|
||||
*/
|
||||
|
||||
template <class Base>
|
||||
inline void forward_subpv_op(
|
||||
size_t p ,
|
||||
size_t q ,
|
||||
size_t i_z ,
|
||||
const addr_t* arg ,
|
||||
const Base* parameter ,
|
||||
size_t cap_order ,
|
||||
Base* taylor )
|
||||
{
|
||||
// check assumptions
|
||||
CPPAD_ASSERT_UNKNOWN( NumArg(SubpvOp) == 2 );
|
||||
CPPAD_ASSERT_UNKNOWN( NumRes(SubpvOp) == 1 );
|
||||
CPPAD_ASSERT_UNKNOWN( q < cap_order );
|
||||
CPPAD_ASSERT_UNKNOWN( p <= q );
|
||||
|
||||
// Taylor coefficients corresponding to arguments and result
|
||||
Base* y = taylor + arg[1] * cap_order;
|
||||
Base* z = taylor + i_z * cap_order;
|
||||
|
||||
// Paraemter value
|
||||
Base x = parameter[ arg[0] ];
|
||||
if( p == 0 )
|
||||
{ z[0] = x - y[0];
|
||||
p++;
|
||||
}
|
||||
for(size_t d = p; d <= q; d++)
|
||||
z[d] = - y[d];
|
||||
}
|
||||
/*!
|
||||
Multiple directions forward mode Taylor coefficients for op = SubpvOp.
|
||||
|
||||
The C++ source code corresponding to this operation is
|
||||
\verbatim
|
||||
z = x - y
|
||||
\endverbatim
|
||||
In the documentation below,
|
||||
this operations is for the case where x is a parameter and y is a variable.
|
||||
|
||||
\copydetails CppAD::local::forward_binary_op_dir
|
||||
*/
|
||||
|
||||
template <class Base>
|
||||
inline void forward_subpv_op_dir(
|
||||
size_t q ,
|
||||
size_t r ,
|
||||
size_t i_z ,
|
||||
const addr_t* arg ,
|
||||
const Base* parameter ,
|
||||
size_t cap_order ,
|
||||
Base* taylor )
|
||||
{
|
||||
// check assumptions
|
||||
CPPAD_ASSERT_UNKNOWN( NumArg(SubpvOp) == 2 );
|
||||
CPPAD_ASSERT_UNKNOWN( NumRes(SubpvOp) == 1 );
|
||||
CPPAD_ASSERT_UNKNOWN( 0 < q );
|
||||
CPPAD_ASSERT_UNKNOWN( q < cap_order );
|
||||
|
||||
// Taylor coefficients corresponding to arguments and result
|
||||
size_t num_taylor_per_var = (cap_order-1) * r + 1;
|
||||
size_t m = (q-1) * r + 1;
|
||||
Base* y = taylor + arg[1] * num_taylor_per_var + m;
|
||||
Base* z = taylor + i_z * num_taylor_per_var + m;
|
||||
|
||||
// Paraemter value
|
||||
for(size_t ell = 0; ell < r; ell++)
|
||||
z[ell] = - y[ell];
|
||||
}
|
||||
/*!
|
||||
Compute zero order forward mode Taylor coefficient for result of op = SubpvOp.
|
||||
|
||||
The C++ source code corresponding to this operation is
|
||||
\verbatim
|
||||
z = x - y
|
||||
\endverbatim
|
||||
In the documentation below,
|
||||
this operations is for the case where x is a parameter and y is a variable.
|
||||
|
||||
\copydetails CppAD::local::forward_binary_op_0
|
||||
*/
|
||||
|
||||
template <class Base>
|
||||
inline void forward_subpv_op_0(
|
||||
size_t i_z ,
|
||||
const addr_t* arg ,
|
||||
const Base* parameter ,
|
||||
size_t cap_order ,
|
||||
Base* taylor )
|
||||
{
|
||||
// check assumptions
|
||||
CPPAD_ASSERT_UNKNOWN( NumArg(SubpvOp) == 2 );
|
||||
CPPAD_ASSERT_UNKNOWN( NumRes(SubpvOp) == 1 );
|
||||
|
||||
// Paraemter value
|
||||
Base x = parameter[ arg[0] ];
|
||||
|
||||
// Taylor coefficients corresponding to arguments and result
|
||||
Base* y = taylor + arg[1] * cap_order;
|
||||
Base* z = taylor + i_z * cap_order;
|
||||
|
||||
z[0] = x - y[0];
|
||||
}
|
||||
|
||||
/*!
|
||||
Compute reverse mode partial derivative for result of op = SubpvOp.
|
||||
|
||||
The C++ source code corresponding to this operation is
|
||||
\verbatim
|
||||
z = x - y
|
||||
\endverbatim
|
||||
In the documentation below,
|
||||
this operations is for the case where x is a parameter and y is a variable.
|
||||
|
||||
\copydetails CppAD::local::reverse_binary_op
|
||||
*/
|
||||
|
||||
template <class Base>
|
||||
inline void reverse_subpv_op(
|
||||
size_t d ,
|
||||
size_t i_z ,
|
||||
const addr_t* arg ,
|
||||
const Base* parameter ,
|
||||
size_t cap_order ,
|
||||
const Base* taylor ,
|
||||
size_t nc_partial ,
|
||||
Base* partial )
|
||||
{
|
||||
// check assumptions
|
||||
CPPAD_ASSERT_UNKNOWN( NumArg(SubvvOp) == 2 );
|
||||
CPPAD_ASSERT_UNKNOWN( NumRes(SubvvOp) == 1 );
|
||||
CPPAD_ASSERT_UNKNOWN( d < cap_order );
|
||||
CPPAD_ASSERT_UNKNOWN( d < nc_partial );
|
||||
|
||||
// Partial derivatives corresponding to arguments and result
|
||||
Base* py = partial + arg[1] * nc_partial;
|
||||
Base* pz = partial + i_z * nc_partial;
|
||||
|
||||
// number of indices to access
|
||||
size_t i = d + 1;
|
||||
while(i)
|
||||
{ --i;
|
||||
py[i] -= pz[i];
|
||||
}
|
||||
}
|
||||
|
||||
// --------------------------- Subvp -----------------------------------------
|
||||
/*!
|
||||
Compute forward mode Taylor coefficients for result of op = SubvvOp.
|
||||
|
||||
The C++ source code corresponding to this operation is
|
||||
\verbatim
|
||||
z = x - y
|
||||
\endverbatim
|
||||
In the documentation below,
|
||||
this operations is for the case where x is a variable and y is a parameter.
|
||||
|
||||
\copydetails CppAD::local::forward_binary_op
|
||||
*/
|
||||
|
||||
template <class Base>
|
||||
inline void forward_subvp_op(
|
||||
size_t p ,
|
||||
size_t q ,
|
||||
size_t i_z ,
|
||||
const addr_t* arg ,
|
||||
const Base* parameter ,
|
||||
size_t cap_order ,
|
||||
Base* taylor )
|
||||
{
|
||||
// check assumptions
|
||||
CPPAD_ASSERT_UNKNOWN( NumArg(SubvpOp) == 2 );
|
||||
CPPAD_ASSERT_UNKNOWN( NumRes(SubvpOp) == 1 );
|
||||
CPPAD_ASSERT_UNKNOWN( q < cap_order );
|
||||
CPPAD_ASSERT_UNKNOWN( p <= q );
|
||||
|
||||
// Taylor coefficients corresponding to arguments and result
|
||||
Base* x = taylor + arg[0] * cap_order;
|
||||
Base* z = taylor + i_z * cap_order;
|
||||
|
||||
// Parameter value
|
||||
Base y = parameter[ arg[1] ];
|
||||
if( p == 0 )
|
||||
{ z[0] = x[0] - y;
|
||||
p++;
|
||||
}
|
||||
for(size_t d = p; d <= q; d++)
|
||||
z[d] = x[d];
|
||||
}
|
||||
/*!
|
||||
Multiple directions forward mode Taylor coefficients for op = SubvvOp.
|
||||
|
||||
The C++ source code corresponding to this operation is
|
||||
\verbatim
|
||||
z = x - y
|
||||
\endverbatim
|
||||
In the documentation below,
|
||||
this operations is for the case where x is a variable and y is a parameter.
|
||||
|
||||
\copydetails CppAD::local::forward_binary_op_dir
|
||||
*/
|
||||
|
||||
template <class Base>
|
||||
inline void forward_subvp_op_dir(
|
||||
size_t q ,
|
||||
size_t r ,
|
||||
size_t i_z ,
|
||||
const addr_t* arg ,
|
||||
const Base* parameter ,
|
||||
size_t cap_order ,
|
||||
Base* taylor )
|
||||
{
|
||||
// check assumptions
|
||||
CPPAD_ASSERT_UNKNOWN( NumArg(SubvpOp) == 2 );
|
||||
CPPAD_ASSERT_UNKNOWN( NumRes(SubvpOp) == 1 );
|
||||
CPPAD_ASSERT_UNKNOWN( 0 < q );
|
||||
CPPAD_ASSERT_UNKNOWN( q < cap_order );
|
||||
|
||||
// Taylor coefficients corresponding to arguments and result
|
||||
size_t num_taylor_per_var = (cap_order-1) * r + 1;
|
||||
Base* x = taylor + arg[0] * num_taylor_per_var;
|
||||
Base* z = taylor + i_z * num_taylor_per_var;
|
||||
|
||||
// Parameter value
|
||||
size_t m = (q-1) * r + 1;
|
||||
for(size_t ell = 0; ell < r; ell++)
|
||||
z[m+ell] = x[m+ell];
|
||||
}
|
||||
|
||||
/*!
|
||||
Compute zero order forward mode Taylor coefficients for result of op = SubvvOp.
|
||||
|
||||
The C++ source code corresponding to this operation is
|
||||
\verbatim
|
||||
z = x - y
|
||||
\endverbatim
|
||||
In the documentation below,
|
||||
this operations is for the case where x is a variable and y is a parameter.
|
||||
|
||||
\copydetails CppAD::local::forward_binary_op_0
|
||||
*/
|
||||
|
||||
template <class Base>
|
||||
inline void forward_subvp_op_0(
|
||||
size_t i_z ,
|
||||
const addr_t* arg ,
|
||||
const Base* parameter ,
|
||||
size_t cap_order ,
|
||||
Base* taylor )
|
||||
{
|
||||
// check assumptions
|
||||
CPPAD_ASSERT_UNKNOWN( NumArg(SubvpOp) == 2 );
|
||||
CPPAD_ASSERT_UNKNOWN( NumRes(SubvpOp) == 1 );
|
||||
|
||||
// Parameter value
|
||||
Base y = parameter[ arg[1] ];
|
||||
|
||||
// Taylor coefficients corresponding to arguments and result
|
||||
Base* x = taylor + arg[0] * cap_order;
|
||||
Base* z = taylor + i_z * cap_order;
|
||||
|
||||
z[0] = x[0] - y;
|
||||
}
|
||||
|
||||
/*!
|
||||
Compute reverse mode partial derivative for result of op = SubvpOp.
|
||||
|
||||
The C++ source code corresponding to this operation is
|
||||
\verbatim
|
||||
z = x - y
|
||||
\endverbatim
|
||||
In the documentation below,
|
||||
this operations is for the case where x is a variable and y is a parameter.
|
||||
|
||||
\copydetails CppAD::local::reverse_binary_op
|
||||
*/
|
||||
|
||||
template <class Base>
|
||||
inline void reverse_subvp_op(
|
||||
size_t d ,
|
||||
size_t i_z ,
|
||||
const addr_t* arg ,
|
||||
const Base* parameter ,
|
||||
size_t cap_order ,
|
||||
const Base* taylor ,
|
||||
size_t nc_partial ,
|
||||
Base* partial )
|
||||
{
|
||||
// check assumptions
|
||||
CPPAD_ASSERT_UNKNOWN( NumArg(SubvpOp) == 2 );
|
||||
CPPAD_ASSERT_UNKNOWN( NumRes(SubvpOp) == 1 );
|
||||
CPPAD_ASSERT_UNKNOWN( d < cap_order );
|
||||
CPPAD_ASSERT_UNKNOWN( d < nc_partial );
|
||||
|
||||
// Partial derivatives corresponding to arguments and result
|
||||
Base* px = partial + arg[0] * nc_partial;
|
||||
Base* pz = partial + i_z * nc_partial;
|
||||
|
||||
// number of indices to access
|
||||
size_t i = d + 1;
|
||||
while(i)
|
||||
{ --i;
|
||||
px[i] += pz[i];
|
||||
}
|
||||
}
|
||||
|
||||
} } // END_CPPAD_LOCAL_NAMESPACE
|
||||
# endif
|
||||
+231
@@ -0,0 +1,231 @@
|
||||
# ifndef CPPAD_LOCAL_TAN_OP_HPP
|
||||
# define CPPAD_LOCAL_TAN_OP_HPP
|
||||
|
||||
/* --------------------------------------------------------------------------
|
||||
CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-17 Bradley M. Bell
|
||||
|
||||
CppAD is distributed under multiple licenses. This distribution is under
|
||||
the terms of the
|
||||
Eclipse Public License Version 1.0.
|
||||
|
||||
A copy of this license is included in the COPYING file of this distribution.
|
||||
Please visit http://www.coin-or.org/CppAD/ for information on other licenses.
|
||||
-------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
namespace CppAD { namespace local { // BEGIN_CPPAD_LOCAL_NAMESPACE
|
||||
/*!
|
||||
\file tan_op.hpp
|
||||
Forward and reverse mode calculations for z = tan(x).
|
||||
*/
|
||||
|
||||
|
||||
/*!
|
||||
Compute forward mode Taylor coefficient for result of op = TanOp.
|
||||
|
||||
The C++ source code corresponding to this operation is
|
||||
\verbatim
|
||||
z = tan(x)
|
||||
\endverbatim
|
||||
The auxillary result is
|
||||
\verbatim
|
||||
y = tan(x)^2
|
||||
\endverbatim
|
||||
The value of y, and its derivatives, are computed along with the value
|
||||
and derivatives of z.
|
||||
|
||||
\copydetails CppAD::local::forward_unary2_op
|
||||
*/
|
||||
template <class Base>
|
||||
inline void forward_tan_op(
|
||||
size_t p ,
|
||||
size_t q ,
|
||||
size_t i_z ,
|
||||
size_t i_x ,
|
||||
size_t cap_order ,
|
||||
Base* taylor )
|
||||
{
|
||||
// check assumptions
|
||||
CPPAD_ASSERT_UNKNOWN( NumArg(TanOp) == 1 );
|
||||
CPPAD_ASSERT_UNKNOWN( NumRes(TanOp) == 2 );
|
||||
CPPAD_ASSERT_UNKNOWN( q < cap_order );
|
||||
CPPAD_ASSERT_UNKNOWN( p <= q );
|
||||
|
||||
// Taylor coefficients corresponding to argument and result
|
||||
Base* x = taylor + i_x * cap_order;
|
||||
Base* z = taylor + i_z * cap_order;
|
||||
Base* y = z - cap_order;
|
||||
|
||||
size_t k;
|
||||
if( p == 0 )
|
||||
{ z[0] = tan( x[0] );
|
||||
y[0] = z[0] * z[0];
|
||||
p++;
|
||||
}
|
||||
for(size_t j = p; j <= q; j++)
|
||||
{ Base base_j = static_cast<Base>(double(j));
|
||||
|
||||
z[j] = x[j];
|
||||
for(k = 1; k <= j; k++)
|
||||
z[j] += Base(double(k)) * x[k] * y[j-k] / base_j;
|
||||
|
||||
y[j] = z[0] * z[j];
|
||||
for(k = 1; k <= j; k++)
|
||||
y[j] += z[k] * z[j-k];
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
Multiple directions forward mode Taylor coefficient for op = TanOp.
|
||||
|
||||
The C++ source code corresponding to this operation is
|
||||
\verbatim
|
||||
z = tan(x)
|
||||
\endverbatim
|
||||
The auxillary result is
|
||||
\verbatim
|
||||
y = tan(x)^2
|
||||
\endverbatim
|
||||
The value of y, and its derivatives, are computed along with the value
|
||||
and derivatives of z.
|
||||
|
||||
\copydetails CppAD::local::forward_unary2_op_dir
|
||||
*/
|
||||
template <class Base>
|
||||
inline void forward_tan_op_dir(
|
||||
size_t q ,
|
||||
size_t r ,
|
||||
size_t i_z ,
|
||||
size_t i_x ,
|
||||
size_t cap_order ,
|
||||
Base* taylor )
|
||||
{
|
||||
// check assumptions
|
||||
CPPAD_ASSERT_UNKNOWN( NumArg(TanOp) == 1 );
|
||||
CPPAD_ASSERT_UNKNOWN( NumRes(TanOp) == 2 );
|
||||
CPPAD_ASSERT_UNKNOWN( 0 < q );
|
||||
CPPAD_ASSERT_UNKNOWN( q < cap_order );
|
||||
|
||||
// Taylor coefficients corresponding to argument and result
|
||||
size_t num_taylor_per_var = (cap_order-1) * r + 1;
|
||||
Base* x = taylor + i_x * num_taylor_per_var;
|
||||
Base* z = taylor + i_z * num_taylor_per_var;
|
||||
Base* y = z - num_taylor_per_var;
|
||||
|
||||
size_t k;
|
||||
size_t m = (q-1) * r + 1;
|
||||
for(size_t ell = 0; ell < r; ell++)
|
||||
{ z[m+ell] = Base(double(q)) * ( x[m+ell] + x[m+ell] * y[0]);
|
||||
for(k = 1; k < q; k++)
|
||||
z[m+ell] += Base(double(k)) * x[(k-1)*r+1+ell] * y[(q-k-1)*r+1+ell];
|
||||
z[m+ell] /= Base(double(q));
|
||||
//
|
||||
y[m+ell] = Base(2.0) * z[m+ell] * z[0];
|
||||
for(k = 1; k < q; k++)
|
||||
y[m+ell] += z[(k-1)*r+1+ell] * z[(q-k-1)*r+1+ell];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
Compute zero order forward mode Taylor coefficient for result of op = TanOp.
|
||||
|
||||
The C++ source code corresponding to this operation is
|
||||
\verbatim
|
||||
z = tan(x)
|
||||
\endverbatim
|
||||
The auxillary result is
|
||||
\verbatim
|
||||
y = cos(x)
|
||||
\endverbatim
|
||||
The value of y is computed along with the value of z.
|
||||
|
||||
\copydetails CppAD::local::forward_unary2_op_0
|
||||
*/
|
||||
template <class Base>
|
||||
inline void forward_tan_op_0(
|
||||
size_t i_z ,
|
||||
size_t i_x ,
|
||||
size_t cap_order ,
|
||||
Base* taylor )
|
||||
{
|
||||
// check assumptions
|
||||
CPPAD_ASSERT_UNKNOWN( NumArg(TanOp) == 1 );
|
||||
CPPAD_ASSERT_UNKNOWN( NumRes(TanOp) == 2 );
|
||||
CPPAD_ASSERT_UNKNOWN( 0 < cap_order );
|
||||
|
||||
// Taylor coefficients corresponding to argument and result
|
||||
Base* x = taylor + i_x * cap_order;
|
||||
Base* z = taylor + i_z * cap_order; // called z in documentation
|
||||
Base* y = z - cap_order; // called y in documentation
|
||||
|
||||
z[0] = tan( x[0] );
|
||||
y[0] = z[0] * z[0];
|
||||
}
|
||||
|
||||
/*!
|
||||
Compute reverse mode partial derivatives for result of op = TanOp.
|
||||
|
||||
The C++ source code corresponding to this operation is
|
||||
\verbatim
|
||||
z = tan(x)
|
||||
\endverbatim
|
||||
The auxillary result is
|
||||
\verbatim
|
||||
y = cos(x)
|
||||
\endverbatim
|
||||
The value of y is computed along with the value of z.
|
||||
|
||||
\copydetails CppAD::local::reverse_unary2_op
|
||||
*/
|
||||
|
||||
template <class Base>
|
||||
inline void reverse_tan_op(
|
||||
size_t d ,
|
||||
size_t i_z ,
|
||||
size_t i_x ,
|
||||
size_t cap_order ,
|
||||
const Base* taylor ,
|
||||
size_t nc_partial ,
|
||||
Base* partial )
|
||||
{
|
||||
// check assumptions
|
||||
CPPAD_ASSERT_UNKNOWN( NumArg(TanOp) == 1 );
|
||||
CPPAD_ASSERT_UNKNOWN( NumRes(TanOp) == 2 );
|
||||
CPPAD_ASSERT_UNKNOWN( d < cap_order );
|
||||
CPPAD_ASSERT_UNKNOWN( d < nc_partial );
|
||||
|
||||
// Taylor coefficients and partials corresponding to argument
|
||||
const Base* x = taylor + i_x * cap_order;
|
||||
Base* px = partial + i_x * nc_partial;
|
||||
|
||||
// Taylor coefficients and partials corresponding to first result
|
||||
const Base* z = taylor + i_z * cap_order; // called z in doc
|
||||
Base* pz = partial + i_z * nc_partial;
|
||||
|
||||
// Taylor coefficients and partials corresponding to auxillary result
|
||||
const Base* y = z - cap_order; // called y in documentation
|
||||
Base* py = pz - nc_partial;
|
||||
|
||||
|
||||
size_t j = d;
|
||||
size_t k;
|
||||
Base base_two(2);
|
||||
while(j)
|
||||
{
|
||||
px[j] += pz[j];
|
||||
pz[j] /= Base(double(j));
|
||||
for(k = 1; k <= j; k++)
|
||||
{ px[k] += azmul(pz[j], y[j-k]) * Base(double(k));
|
||||
py[j-k] += azmul(pz[j], x[k]) * Base(double(k));
|
||||
}
|
||||
for(k = 0; k < j; k++)
|
||||
pz[k] += azmul(py[j-1], z[j-k-1]) * base_two;
|
||||
|
||||
--j;
|
||||
}
|
||||
px[0] += azmul(pz[0], Base(1.0) + y[0]);
|
||||
}
|
||||
|
||||
} } // END_CPPAD_LOCAL_NAMESPACE
|
||||
# endif
|
||||
+230
@@ -0,0 +1,230 @@
|
||||
# ifndef CPPAD_LOCAL_TANH_OP_HPP
|
||||
# define CPPAD_LOCAL_TANH_OP_HPP
|
||||
|
||||
/* --------------------------------------------------------------------------
|
||||
CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-17 Bradley M. Bell
|
||||
|
||||
CppAD is distributed under multiple licenses. This distribution is under
|
||||
the terms of the
|
||||
Eclipse Public License Version 1.0.
|
||||
|
||||
A copy of this license is included in the COPYING file of this distribution.
|
||||
Please visit http://www.coin-or.org/CppAD/ for information on other licenses.
|
||||
-------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
namespace CppAD { namespace local { // BEGIN_CPPAD_LOCAL_NAMESPACE
|
||||
/*!
|
||||
\file tanh_op.hpp
|
||||
Forward and reverse mode calculations for z = tanh(x).
|
||||
*/
|
||||
|
||||
|
||||
/*!
|
||||
Compute forward mode Taylor coefficient for result of op = TanOp.
|
||||
|
||||
The C++ source code corresponding to this operation is
|
||||
\verbatim
|
||||
z = tanh(x)
|
||||
\endverbatim
|
||||
The auxillary result is
|
||||
\verbatim
|
||||
y = tanh(x)^2
|
||||
\endverbatim
|
||||
The value of y, and its derivatives, are computed along with the value
|
||||
and derivatives of z.
|
||||
|
||||
\copydetails CppAD::local::forward_unary2_op
|
||||
*/
|
||||
template <class Base>
|
||||
inline void forward_tanh_op(
|
||||
size_t p ,
|
||||
size_t q ,
|
||||
size_t i_z ,
|
||||
size_t i_x ,
|
||||
size_t cap_order ,
|
||||
Base* taylor )
|
||||
{
|
||||
// check assumptions
|
||||
CPPAD_ASSERT_UNKNOWN( NumArg(TanOp) == 1 );
|
||||
CPPAD_ASSERT_UNKNOWN( NumRes(TanOp) == 2 );
|
||||
CPPAD_ASSERT_UNKNOWN( q < cap_order );
|
||||
CPPAD_ASSERT_UNKNOWN( p <= q );
|
||||
|
||||
// Taylor coefficients corresponding to argument and result
|
||||
Base* x = taylor + i_x * cap_order;
|
||||
Base* z = taylor + i_z * cap_order;
|
||||
Base* y = z - cap_order;
|
||||
|
||||
size_t k;
|
||||
if( p == 0 )
|
||||
{ z[0] = tanh( x[0] );
|
||||
y[0] = z[0] * z[0];
|
||||
p++;
|
||||
}
|
||||
for(size_t j = p; j <= q; j++)
|
||||
{ Base base_j = static_cast<Base>(double(j));
|
||||
|
||||
z[j] = x[j];
|
||||
for(k = 1; k <= j; k++)
|
||||
z[j] -= Base(double(k)) * x[k] * y[j-k] / base_j;
|
||||
|
||||
y[j] = z[0] * z[j];
|
||||
for(k = 1; k <= j; k++)
|
||||
y[j] += z[k] * z[j-k];
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
Multiple directions forward mode Taylor coefficient for op = TanOp.
|
||||
|
||||
The C++ source code corresponding to this operation is
|
||||
\verbatim
|
||||
z = tanh(x)
|
||||
\endverbatim
|
||||
The auxillary result is
|
||||
\verbatim
|
||||
y = tanh(x)^2
|
||||
\endverbatim
|
||||
The value of y, and its derivatives, are computed along with the value
|
||||
and derivatives of z.
|
||||
|
||||
\copydetails CppAD::local::forward_unary2_op_dir
|
||||
*/
|
||||
template <class Base>
|
||||
inline void forward_tanh_op_dir(
|
||||
size_t q ,
|
||||
size_t r ,
|
||||
size_t i_z ,
|
||||
size_t i_x ,
|
||||
size_t cap_order ,
|
||||
Base* taylor )
|
||||
{
|
||||
// check assumptions
|
||||
CPPAD_ASSERT_UNKNOWN( NumArg(TanOp) == 1 );
|
||||
CPPAD_ASSERT_UNKNOWN( NumRes(TanOp) == 2 );
|
||||
CPPAD_ASSERT_UNKNOWN( 0 < q );
|
||||
CPPAD_ASSERT_UNKNOWN( q < cap_order );
|
||||
|
||||
// Taylor coefficients corresponding to argument and result
|
||||
size_t num_taylor_per_var = (cap_order-1) * r + 1;
|
||||
Base* x = taylor + i_x * num_taylor_per_var;
|
||||
Base* z = taylor + i_z * num_taylor_per_var;
|
||||
Base* y = z - num_taylor_per_var;
|
||||
|
||||
size_t k;
|
||||
size_t m = (q-1) * r + 1;
|
||||
for(size_t ell = 0; ell < r; ell++)
|
||||
{ z[m+ell] = Base(double(q)) * ( x[m+ell] - x[m+ell] * y[0] );
|
||||
for(k = 1; k < q; k++)
|
||||
z[m+ell] -= Base(double(k)) * x[(k-1)*r+1+ell] * y[(q-k-1)*r+1+ell];
|
||||
z[m+ell] /= Base(double(q));
|
||||
//
|
||||
y[m+ell] = Base(2.0) * z[m+ell] * z[0];
|
||||
for(k = 1; k < q; k++)
|
||||
y[m+ell] += z[(k-1)*r+1+ell] * z[(q-k-1)*r+1+ell];
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
Compute zero order forward mode Taylor coefficient for result of op = TanOp.
|
||||
|
||||
The C++ source code corresponding to this operation is
|
||||
\verbatim
|
||||
z = tanh(x)
|
||||
\endverbatim
|
||||
The auxillary result is
|
||||
\verbatim
|
||||
y = cos(x)
|
||||
\endverbatim
|
||||
The value of y is computed along with the value of z.
|
||||
|
||||
\copydetails CppAD::local::forward_unary2_op_0
|
||||
*/
|
||||
template <class Base>
|
||||
inline void forward_tanh_op_0(
|
||||
size_t i_z ,
|
||||
size_t i_x ,
|
||||
size_t cap_order ,
|
||||
Base* taylor )
|
||||
{
|
||||
// check assumptions
|
||||
CPPAD_ASSERT_UNKNOWN( NumArg(TanOp) == 1 );
|
||||
CPPAD_ASSERT_UNKNOWN( NumRes(TanOp) == 2 );
|
||||
CPPAD_ASSERT_UNKNOWN( 0 < cap_order );
|
||||
|
||||
// Taylor coefficients corresponding to argument and result
|
||||
Base* x = taylor + i_x * cap_order;
|
||||
Base* z = taylor + i_z * cap_order; // called z in documentation
|
||||
Base* y = z - cap_order; // called y in documentation
|
||||
|
||||
z[0] = tanh( x[0] );
|
||||
y[0] = z[0] * z[0];
|
||||
}
|
||||
|
||||
/*!
|
||||
Compute reverse mode partial derivatives for result of op = TanOp.
|
||||
|
||||
The C++ source code corresponding to this operation is
|
||||
\verbatim
|
||||
z = tanh(x)
|
||||
\endverbatim
|
||||
The auxillary result is
|
||||
\verbatim
|
||||
y = cos(x)
|
||||
\endverbatim
|
||||
The value of y is computed along with the value of z.
|
||||
|
||||
\copydetails CppAD::local::reverse_unary2_op
|
||||
*/
|
||||
|
||||
template <class Base>
|
||||
inline void reverse_tanh_op(
|
||||
size_t d ,
|
||||
size_t i_z ,
|
||||
size_t i_x ,
|
||||
size_t cap_order ,
|
||||
const Base* taylor ,
|
||||
size_t nc_partial ,
|
||||
Base* partial )
|
||||
{
|
||||
// check assumptions
|
||||
CPPAD_ASSERT_UNKNOWN( NumArg(TanOp) == 1 );
|
||||
CPPAD_ASSERT_UNKNOWN( NumRes(TanOp) == 2 );
|
||||
CPPAD_ASSERT_UNKNOWN( d < cap_order );
|
||||
CPPAD_ASSERT_UNKNOWN( d < nc_partial );
|
||||
|
||||
// Taylor coefficients and partials corresponding to argument
|
||||
const Base* x = taylor + i_x * cap_order;
|
||||
Base* px = partial + i_x * nc_partial;
|
||||
|
||||
// Taylor coefficients and partials corresponding to first result
|
||||
const Base* z = taylor + i_z * cap_order; // called z in doc
|
||||
Base* pz = partial + i_z * nc_partial;
|
||||
|
||||
// Taylor coefficients and partials corresponding to auxillary result
|
||||
const Base* y = z - cap_order; // called y in documentation
|
||||
Base* py = pz - nc_partial;
|
||||
|
||||
|
||||
size_t j = d;
|
||||
size_t k;
|
||||
Base base_two(2);
|
||||
while(j)
|
||||
{
|
||||
px[j] += pz[j];
|
||||
pz[j] /= Base(double(j));
|
||||
for(k = 1; k <= j; k++)
|
||||
{ px[k] -= azmul(pz[j], y[j-k]) * Base(double(k));
|
||||
py[j-k] -= azmul(pz[j], x[k]) * Base(double(k));
|
||||
}
|
||||
for(k = 0; k < j; k++)
|
||||
pz[k] += azmul(py[j-1], z[j-k-1]) * base_two;
|
||||
|
||||
--j;
|
||||
}
|
||||
px[0] += azmul(pz[0], Base(1.0) - y[0]);
|
||||
}
|
||||
|
||||
} } // END_CPPAD_LOCAL_NAMESPACE
|
||||
# endif
|
||||
@@ -0,0 +1,32 @@
|
||||
// $Id$
|
||||
# ifndef CPPAD_LOCAL_USER_STATE_HPP
|
||||
# define CPPAD_LOCAL_USER_STATE_HPP
|
||||
/* --------------------------------------------------------------------------
|
||||
CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-16 Bradley M. Bell
|
||||
|
||||
CppAD is distributed under multiple licenses. This distribution is under
|
||||
the terms of the
|
||||
Eclipse Public License Version 1.0.
|
||||
|
||||
A copy of this license is included in the COPYING file of this distribution.
|
||||
Please visit http://www.coin-or.org/CppAD/ for information on other licenses.
|
||||
-------------------------------------------------------------------------- */
|
||||
|
||||
namespace CppAD { namespace local { // BEGIN_CPPAD_LOCAL_NAMESPACE
|
||||
|
||||
enum enum_user_state {
|
||||
/// next UserOp marks beginning of a user atomic call
|
||||
start_user,
|
||||
|
||||
/// next UsrapOp (UsravOp) is a parameter (variable) argument
|
||||
arg_user,
|
||||
|
||||
/// next UsrrpOp (UsrrvOp) is a parameter (variable) result
|
||||
ret_user,
|
||||
|
||||
/// next UserOp marks end of a user atomic call
|
||||
end_user
|
||||
};
|
||||
|
||||
} } // END_CPPAD_LOCAL_NAMESPACE
|
||||
# endif
|
||||
+517
@@ -0,0 +1,517 @@
|
||||
# ifndef CPPAD_LOCAL_ZMUL_OP_HPP
|
||||
# define CPPAD_LOCAL_ZMUL_OP_HPP
|
||||
|
||||
/* --------------------------------------------------------------------------
|
||||
CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-17 Bradley M. Bell
|
||||
|
||||
CppAD is distributed under multiple licenses. This distribution is under
|
||||
the terms of the
|
||||
Eclipse Public License Version 1.0.
|
||||
|
||||
A copy of this license is included in the COPYING file of this distribution.
|
||||
Please visit http://www.coin-or.org/CppAD/ for information on other licenses.
|
||||
-------------------------------------------------------------------------- */
|
||||
|
||||
namespace CppAD { namespace local { // BEGIN_CPPAD_LOCAL_NAMESPACE
|
||||
/*!
|
||||
\file mul_op.hpp
|
||||
Forward and reverse mode calculations for z = azmul(x, y).
|
||||
*/
|
||||
|
||||
// --------------------------- Zmulvv -----------------------------------------
|
||||
/*!
|
||||
Compute forward mode Taylor coefficients for result of op = ZmulvvOp.
|
||||
|
||||
The C++ source code corresponding to this operation is
|
||||
\verbatim
|
||||
z = azmul(x, y)
|
||||
\endverbatim
|
||||
In the documentation below,
|
||||
this operations is for the case where both x and y are variables
|
||||
and the argument \a parameter is not used.
|
||||
|
||||
\copydetails CppAD::local::forward_binary_op
|
||||
*/
|
||||
|
||||
template <class Base>
|
||||
inline void forward_zmulvv_op(
|
||||
size_t p ,
|
||||
size_t q ,
|
||||
size_t i_z ,
|
||||
const addr_t* arg ,
|
||||
const Base* parameter ,
|
||||
size_t cap_order ,
|
||||
Base* taylor )
|
||||
{
|
||||
// check assumptions
|
||||
CPPAD_ASSERT_UNKNOWN( NumArg(ZmulvvOp) == 2 );
|
||||
CPPAD_ASSERT_UNKNOWN( NumRes(ZmulvvOp) == 1 );
|
||||
CPPAD_ASSERT_UNKNOWN( q < cap_order );
|
||||
CPPAD_ASSERT_UNKNOWN( p <= q );
|
||||
|
||||
// Taylor coefficients corresponding to arguments and result
|
||||
Base* x = taylor + arg[0] * cap_order;
|
||||
Base* y = taylor + arg[1] * cap_order;
|
||||
Base* z = taylor + i_z * cap_order;
|
||||
|
||||
size_t k;
|
||||
for(size_t d = p; d <= q; d++)
|
||||
{ z[d] = Base(0.0);
|
||||
for(k = 0; k <= d; k++)
|
||||
z[d] += azmul(x[d-k], y[k]);
|
||||
}
|
||||
}
|
||||
/*!
|
||||
Multiple directions forward mode Taylor coefficients for op = ZmulvvOp.
|
||||
|
||||
The C++ source code corresponding to this operation is
|
||||
\verbatim
|
||||
z = azmul(x, y)
|
||||
\endverbatim
|
||||
In the documentation below,
|
||||
this operations is for the case where both x and y are variables
|
||||
and the argument \a parameter is not used.
|
||||
|
||||
\copydetails CppAD::local::forward_binary_op_dir
|
||||
*/
|
||||
|
||||
template <class Base>
|
||||
inline void forward_zmulvv_op_dir(
|
||||
size_t q ,
|
||||
size_t r ,
|
||||
size_t i_z ,
|
||||
const addr_t* arg ,
|
||||
const Base* parameter ,
|
||||
size_t cap_order ,
|
||||
Base* taylor )
|
||||
{
|
||||
// check assumptions
|
||||
CPPAD_ASSERT_UNKNOWN( NumArg(ZmulvvOp) == 2 );
|
||||
CPPAD_ASSERT_UNKNOWN( NumRes(ZmulvvOp) == 1 );
|
||||
CPPAD_ASSERT_UNKNOWN( 0 < q );
|
||||
CPPAD_ASSERT_UNKNOWN( q < cap_order );
|
||||
|
||||
// Taylor coefficients corresponding to arguments and result
|
||||
size_t num_taylor_per_var = (cap_order-1) * r + 1;
|
||||
Base* x = taylor + arg[0] * num_taylor_per_var;
|
||||
Base* y = taylor + arg[1] * num_taylor_per_var;
|
||||
Base* z = taylor + i_z * num_taylor_per_var;
|
||||
|
||||
size_t k, ell, m;
|
||||
for(ell = 0; ell < r; ell++)
|
||||
{ m = (q-1)*r + ell + 1;
|
||||
z[m] = azmul(x[0], y[m]) + azmul(x[m], y[0]);
|
||||
for(k = 1; k < q; k++)
|
||||
z[m] += azmul(x[(q-k-1)*r + ell + 1], y[(k-1)*r + ell + 1]);
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
Compute zero order forward mode Taylor coefficients for result of op = ZmulvvOp.
|
||||
|
||||
The C++ source code corresponding to this operation is
|
||||
\verbatim
|
||||
z = azmul(x, y)
|
||||
\endverbatim
|
||||
In the documentation below,
|
||||
this operations is for the case where both x and y are variables
|
||||
and the argument \a parameter is not used.
|
||||
|
||||
\copydetails CppAD::local::forward_binary_op_0
|
||||
*/
|
||||
|
||||
template <class Base>
|
||||
inline void forward_zmulvv_op_0(
|
||||
size_t i_z ,
|
||||
const addr_t* arg ,
|
||||
const Base* parameter ,
|
||||
size_t cap_order ,
|
||||
Base* taylor )
|
||||
{
|
||||
// check assumptions
|
||||
CPPAD_ASSERT_UNKNOWN( NumArg(ZmulvvOp) == 2 );
|
||||
CPPAD_ASSERT_UNKNOWN( NumRes(ZmulvvOp) == 1 );
|
||||
|
||||
// Taylor coefficients corresponding to arguments and result
|
||||
Base* x = taylor + arg[0] * cap_order;
|
||||
Base* y = taylor + arg[1] * cap_order;
|
||||
Base* z = taylor + i_z * cap_order;
|
||||
|
||||
z[0] = azmul(x[0], y[0]);
|
||||
}
|
||||
|
||||
/*!
|
||||
Compute reverse mode partial derivatives for result of op = ZmulvvOp.
|
||||
|
||||
The C++ source code corresponding to this operation is
|
||||
\verbatim
|
||||
z = azmul(x, y)
|
||||
\endverbatim
|
||||
In the documentation below,
|
||||
this operations is for the case where both x and y are variables
|
||||
and the argument \a parameter is not used.
|
||||
|
||||
\copydetails CppAD::local::reverse_binary_op
|
||||
*/
|
||||
|
||||
template <class Base>
|
||||
inline void reverse_zmulvv_op(
|
||||
size_t d ,
|
||||
size_t i_z ,
|
||||
const addr_t* arg ,
|
||||
const Base* parameter ,
|
||||
size_t cap_order ,
|
||||
const Base* taylor ,
|
||||
size_t nc_partial ,
|
||||
Base* partial )
|
||||
{
|
||||
// check assumptions
|
||||
CPPAD_ASSERT_UNKNOWN( NumArg(ZmulvvOp) == 2 );
|
||||
CPPAD_ASSERT_UNKNOWN( NumRes(ZmulvvOp) == 1 );
|
||||
CPPAD_ASSERT_UNKNOWN( d < cap_order );
|
||||
CPPAD_ASSERT_UNKNOWN( d < nc_partial );
|
||||
|
||||
// Arguments
|
||||
const Base* x = taylor + arg[0] * cap_order;
|
||||
const Base* y = taylor + arg[1] * cap_order;
|
||||
|
||||
// Partial derivatives corresponding to arguments and result
|
||||
Base* px = partial + arg[0] * nc_partial;
|
||||
Base* py = partial + arg[1] * nc_partial;
|
||||
Base* pz = partial + i_z * nc_partial;
|
||||
|
||||
// number of indices to access
|
||||
size_t j = d + 1;
|
||||
size_t k;
|
||||
while(j)
|
||||
{ --j;
|
||||
for(k = 0; k <= j; k++)
|
||||
{
|
||||
px[j-k] += azmul(pz[j], y[k]);
|
||||
py[k] += azmul(pz[j], x[j-k]);
|
||||
}
|
||||
}
|
||||
}
|
||||
// --------------------------- Zmulpv -----------------------------------------
|
||||
/*!
|
||||
Compute forward mode Taylor coefficients for result of op = ZmulpvOp.
|
||||
|
||||
The C++ source code corresponding to this operation is
|
||||
\verbatim
|
||||
z = azmul(x, y)
|
||||
\endverbatim
|
||||
In the documentation below,
|
||||
this operations is for the case where x is a parameter and y is a variable.
|
||||
|
||||
\copydetails CppAD::local::forward_binary_op
|
||||
*/
|
||||
|
||||
template <class Base>
|
||||
inline void forward_zmulpv_op(
|
||||
size_t p ,
|
||||
size_t q ,
|
||||
size_t i_z ,
|
||||
const addr_t* arg ,
|
||||
const Base* parameter ,
|
||||
size_t cap_order ,
|
||||
Base* taylor )
|
||||
{
|
||||
// check assumptions
|
||||
CPPAD_ASSERT_UNKNOWN( NumArg(ZmulpvOp) == 2 );
|
||||
CPPAD_ASSERT_UNKNOWN( NumRes(ZmulpvOp) == 1 );
|
||||
CPPAD_ASSERT_UNKNOWN( q < cap_order );
|
||||
CPPAD_ASSERT_UNKNOWN( p <= q );
|
||||
|
||||
// Taylor coefficients corresponding to arguments and result
|
||||
Base* y = taylor + arg[1] * cap_order;
|
||||
Base* z = taylor + i_z * cap_order;
|
||||
|
||||
// Paraemter value
|
||||
Base x = parameter[ arg[0] ];
|
||||
|
||||
for(size_t d = p; d <= q; d++)
|
||||
z[d] = azmul(x, y[d]);
|
||||
}
|
||||
/*!
|
||||
Multiple directions forward mode Taylor coefficients for op = ZmulpvOp.
|
||||
|
||||
The C++ source code corresponding to this operation is
|
||||
\verbatim
|
||||
z = azmul(x, y)
|
||||
\endverbatim
|
||||
In the documentation below,
|
||||
this operations is for the case where x is a parameter and y is a variable.
|
||||
|
||||
\copydetails CppAD::local::forward_binary_op_dir
|
||||
*/
|
||||
|
||||
template <class Base>
|
||||
inline void forward_zmulpv_op_dir(
|
||||
size_t q ,
|
||||
size_t r ,
|
||||
size_t i_z ,
|
||||
const addr_t* arg ,
|
||||
const Base* parameter ,
|
||||
size_t cap_order ,
|
||||
Base* taylor )
|
||||
{
|
||||
// check assumptions
|
||||
CPPAD_ASSERT_UNKNOWN( NumArg(ZmulpvOp) == 2 );
|
||||
CPPAD_ASSERT_UNKNOWN( NumRes(ZmulpvOp) == 1 );
|
||||
CPPAD_ASSERT_UNKNOWN( 0 < q );
|
||||
CPPAD_ASSERT_UNKNOWN( q < cap_order );
|
||||
|
||||
// Taylor coefficients corresponding to arguments and result
|
||||
size_t num_taylor_per_var = (cap_order-1) * r + 1;
|
||||
size_t m = (q-1) * r + 1;
|
||||
Base* y = taylor + arg[1] * num_taylor_per_var + m;
|
||||
Base* z = taylor + i_z * num_taylor_per_var + m;
|
||||
|
||||
// Paraemter value
|
||||
Base x = parameter[ arg[0] ];
|
||||
|
||||
for(size_t ell = 0; ell < r; ell++)
|
||||
z[ell] = azmul(x, y[ell]);
|
||||
}
|
||||
/*!
|
||||
Compute zero order forward mode Taylor coefficient for result of op = ZmulpvOp.
|
||||
|
||||
The C++ source code corresponding to this operation is
|
||||
\verbatim
|
||||
z = azmul(x, y)
|
||||
\endverbatim
|
||||
In the documentation below,
|
||||
this operations is for the case where x is a parameter and y is a variable.
|
||||
|
||||
\copydetails CppAD::local::forward_binary_op_0
|
||||
*/
|
||||
|
||||
template <class Base>
|
||||
inline void forward_zmulpv_op_0(
|
||||
size_t i_z ,
|
||||
const addr_t* arg ,
|
||||
const Base* parameter ,
|
||||
size_t cap_order ,
|
||||
Base* taylor )
|
||||
{
|
||||
// check assumptions
|
||||
CPPAD_ASSERT_UNKNOWN( NumArg(ZmulpvOp) == 2 );
|
||||
CPPAD_ASSERT_UNKNOWN( NumRes(ZmulpvOp) == 1 );
|
||||
|
||||
// Paraemter value
|
||||
Base x = parameter[ arg[0] ];
|
||||
|
||||
// Taylor coefficients corresponding to arguments and result
|
||||
Base* y = taylor + arg[1] * cap_order;
|
||||
Base* z = taylor + i_z * cap_order;
|
||||
|
||||
z[0] = azmul(x, y[0]);
|
||||
}
|
||||
|
||||
/*!
|
||||
Compute reverse mode partial derivative for result of op = ZmulpvOp.
|
||||
|
||||
The C++ source code corresponding to this operation is
|
||||
\verbatim
|
||||
z = azmul(x, y)
|
||||
\endverbatim
|
||||
In the documentation below,
|
||||
this operations is for the case where x is a parameter and y is a variable.
|
||||
|
||||
\copydetails CppAD::local::reverse_binary_op
|
||||
*/
|
||||
|
||||
template <class Base>
|
||||
inline void reverse_zmulpv_op(
|
||||
size_t d ,
|
||||
size_t i_z ,
|
||||
const addr_t* arg ,
|
||||
const Base* parameter ,
|
||||
size_t cap_order ,
|
||||
const Base* taylor ,
|
||||
size_t nc_partial ,
|
||||
Base* partial )
|
||||
{
|
||||
// check assumptions
|
||||
CPPAD_ASSERT_UNKNOWN( NumArg(ZmulpvOp) == 2 );
|
||||
CPPAD_ASSERT_UNKNOWN( NumRes(ZmulpvOp) == 1 );
|
||||
CPPAD_ASSERT_UNKNOWN( d < cap_order );
|
||||
CPPAD_ASSERT_UNKNOWN( d < nc_partial );
|
||||
|
||||
// Arguments
|
||||
Base x = parameter[ arg[0] ];
|
||||
|
||||
// Partial derivatives corresponding to arguments and result
|
||||
Base* py = partial + arg[1] * nc_partial;
|
||||
Base* pz = partial + i_z * nc_partial;
|
||||
|
||||
// number of indices to access
|
||||
size_t j = d + 1;
|
||||
while(j)
|
||||
{ --j;
|
||||
py[j] += azmul(pz[j], x);
|
||||
}
|
||||
}
|
||||
// --------------------------- Zmulvp -----------------------------------------
|
||||
/*!
|
||||
Compute forward mode Taylor coefficients for result of op = ZmulvpOp.
|
||||
|
||||
The C++ source code corresponding to this operation is
|
||||
\verbatim
|
||||
z = azmul(x, y)
|
||||
\endverbatim
|
||||
In the documentation below,
|
||||
this operations is for the case where x is a parameter and y is a variable.
|
||||
|
||||
\copydetails CppAD::local::forward_binary_op
|
||||
*/
|
||||
|
||||
template <class Base>
|
||||
inline void forward_zmulvp_op(
|
||||
size_t p ,
|
||||
size_t q ,
|
||||
size_t i_z ,
|
||||
const addr_t* arg ,
|
||||
const Base* parameter ,
|
||||
size_t cap_order ,
|
||||
Base* taylor )
|
||||
{
|
||||
// check assumptions
|
||||
CPPAD_ASSERT_UNKNOWN( NumArg(ZmulvpOp) == 2 );
|
||||
CPPAD_ASSERT_UNKNOWN( NumRes(ZmulvpOp) == 1 );
|
||||
CPPAD_ASSERT_UNKNOWN( q < cap_order );
|
||||
CPPAD_ASSERT_UNKNOWN( p <= q );
|
||||
|
||||
// Taylor coefficients corresponding to arguments and result
|
||||
Base* x = taylor + arg[0] * cap_order;
|
||||
Base* z = taylor + i_z * cap_order;
|
||||
|
||||
// Paraemter value
|
||||
Base y = parameter[ arg[1] ];
|
||||
|
||||
for(size_t d = p; d <= q; d++)
|
||||
z[d] = azmul(x[d], y);
|
||||
}
|
||||
/*!
|
||||
Multiple directions forward mode Taylor coefficients for op = ZmulvpOp.
|
||||
|
||||
The C++ source code corresponding to this operation is
|
||||
\verbatim
|
||||
z = azmul(x, y)
|
||||
\endverbatim
|
||||
In the documentation below,
|
||||
this operations is for the case where x is a parameter and y is a variable.
|
||||
|
||||
\copydetails CppAD::local::forward_binary_op_dir
|
||||
*/
|
||||
|
||||
template <class Base>
|
||||
inline void forward_zmulvp_op_dir(
|
||||
size_t q ,
|
||||
size_t r ,
|
||||
size_t i_z ,
|
||||
const addr_t* arg ,
|
||||
const Base* parameter ,
|
||||
size_t cap_order ,
|
||||
Base* taylor )
|
||||
{
|
||||
// check assumptions
|
||||
CPPAD_ASSERT_UNKNOWN( NumArg(ZmulvpOp) == 2 );
|
||||
CPPAD_ASSERT_UNKNOWN( NumRes(ZmulvpOp) == 1 );
|
||||
CPPAD_ASSERT_UNKNOWN( 0 < q );
|
||||
CPPAD_ASSERT_UNKNOWN( q < cap_order );
|
||||
|
||||
// Taylor coefficients corresponding to arguments and result
|
||||
size_t num_taylor_per_var = (cap_order-1) * r + 1;
|
||||
size_t m = (q-1) * r + 1;
|
||||
Base* x = taylor + arg[0] * num_taylor_per_var + m;
|
||||
Base* z = taylor + i_z * num_taylor_per_var + m;
|
||||
|
||||
// Paraemter value
|
||||
Base y = parameter[ arg[1] ];
|
||||
|
||||
for(size_t ell = 0; ell < r; ell++)
|
||||
z[ell] = azmul(x[ell], y);
|
||||
}
|
||||
/*!
|
||||
Compute zero order forward mode Taylor coefficient for result of op = ZmulvpOp.
|
||||
|
||||
The C++ source code corresponding to this operation is
|
||||
\verbatim
|
||||
z = azmul(x, y)
|
||||
\endverbatim
|
||||
In the documentation below,
|
||||
this operations is for the case where x is a parameter and y is a variable.
|
||||
|
||||
\copydetails CppAD::local::forward_binary_op_0
|
||||
*/
|
||||
|
||||
template <class Base>
|
||||
inline void forward_zmulvp_op_0(
|
||||
size_t i_z ,
|
||||
const addr_t* arg ,
|
||||
const Base* parameter ,
|
||||
size_t cap_order ,
|
||||
Base* taylor )
|
||||
{
|
||||
// check assumptions
|
||||
CPPAD_ASSERT_UNKNOWN( NumArg(ZmulvpOp) == 2 );
|
||||
CPPAD_ASSERT_UNKNOWN( NumRes(ZmulvpOp) == 1 );
|
||||
|
||||
// Paraemter value
|
||||
Base y = parameter[ arg[1] ];
|
||||
|
||||
// Taylor coefficients corresponding to arguments and result
|
||||
Base* x = taylor + arg[0] * cap_order;
|
||||
Base* z = taylor + i_z * cap_order;
|
||||
|
||||
z[0] = azmul(x[0], y);
|
||||
}
|
||||
|
||||
/*!
|
||||
Compute reverse mode partial derivative for result of op = ZmulvpOp.
|
||||
|
||||
The C++ source code corresponding to this operation is
|
||||
\verbatim
|
||||
z = azmul(x, y)
|
||||
\endverbatim
|
||||
In the documentation below,
|
||||
this operations is for the case where x is a parameter and y is a variable.
|
||||
|
||||
\copydetails CppAD::local::reverse_binary_op
|
||||
*/
|
||||
|
||||
template <class Base>
|
||||
inline void reverse_zmulvp_op(
|
||||
size_t d ,
|
||||
size_t i_z ,
|
||||
const addr_t* arg ,
|
||||
const Base* parameter ,
|
||||
size_t cap_order ,
|
||||
const Base* taylor ,
|
||||
size_t nc_partial ,
|
||||
Base* partial )
|
||||
{
|
||||
// check assumptions
|
||||
CPPAD_ASSERT_UNKNOWN( NumArg(ZmulvpOp) == 2 );
|
||||
CPPAD_ASSERT_UNKNOWN( NumRes(ZmulvpOp) == 1 );
|
||||
CPPAD_ASSERT_UNKNOWN( d < cap_order );
|
||||
CPPAD_ASSERT_UNKNOWN( d < nc_partial );
|
||||
|
||||
// Arguments
|
||||
Base y = parameter[ arg[1] ];
|
||||
|
||||
// Partial derivatives corresponding to arguments and result
|
||||
Base* px = partial + arg[0] * nc_partial;
|
||||
Base* pz = partial + i_z * nc_partial;
|
||||
|
||||
// number of indices to access
|
||||
size_t j = d + 1;
|
||||
while(j)
|
||||
{ --j;
|
||||
px[j] += azmul(pz[j], y);
|
||||
}
|
||||
}
|
||||
|
||||
} } // END_CPPAD_LOCAL_NAMESPACE
|
||||
# endif
|
||||
Reference in New Issue
Block a user