|
Prev
| Next
|
|
|
|
|
|
atomic_four_get_started.cpp |
|
@(@\newcommand{\W}[1]{ \; #1 \; }
\newcommand{\R}[1]{ {\rm #1} }
\newcommand{\B}[1]{ {\bf #1} }
\newcommand{\D}[2]{ \frac{\partial #1}{\partial #2} }
\newcommand{\DD}[3]{ \frac{\partial^2 #1}{\partial #2 \partial #3} }
\newcommand{\Dpow}[2]{ \frac{\partial^{#1}}{\partial {#2}^{#1}} }
\newcommand{\dpow}[2]{ \frac{ {\rm d}^{#1}}{{\rm d}\, {#2}^{#1}} }@)@This is cppad-20221105 documentation. Here is a link to its
current documentation
.
Getting Started with Atomic Functions: Example and Test
Purpose
This example demonstrates the minimal amount of information
necessary for a atomic_four
function.
Define Atomic Function
// empty namespace
namespace {
// atomic_get_started
class atomic_get_started : public CppAD::atomic_four<double> {
public:
// can use const char* name when calling this constructor
atomic_get_started(const std::string& name) :
CppAD::atomic_four<double>(name) // inform base class of name
{ }
private:
// for_type
bool for_type(
size_t call_id ,
const CppAD::vector<CppAD::ad_type_enum>& type_x ,
CppAD::vector<CppAD::ad_type_enum>& type_y ) override
{
assert( call_id == 0 ); // default value
assert( type_x.size() == 1 ); // n
assert( type_y.size() == 1 ); // m
//
type_y[0] = type_x[0];
return true;
}
// forward
bool forward(
size_t call_id ,
const CppAD::vector<bool>& select_y ,
size_t order_low ,
size_t order_up ,
const CppAD::vector<double>& taylor_x ,
CppAD::vector<double>& taylor_y ) override
{
# ifndef NDEBUG
size_t q = order_up + 1;
size_t n = taylor_x.size() / q;
size_t m = taylor_y.size() / q;
assert( call_id == 0 );
assert( order_low == 0);
assert( order_up == 0);
assert( n == 1 );
assert( m == 1 );
assert( m == select_y.size() );
# endif
// return flag
bool ok = order_up == 0;
if( ! ok )
return ok;
// taylor_y
// Order zero forward mode: y^0 = g( x^0 ) = 1 / x^0
taylor_y[0] = 1.0 / taylor_x[0];
//
return ok;
}
};
}
Use Atomic Function
bool get_started(void)
{
// ok, eps
bool ok = true;
double eps = 10. * CppAD::numeric_limits<double>::epsilon();
//
// afun
atomic_get_started afun("atomic_get_started");
//
// n, m
size_t n = 1;
size_t m = 1;
//
// x0
double x0 = 0.5;
//
// ax
CPPAD_TESTVECTOR( CppAD::AD<double> ) ax(n);
ax[0] = x0;
CppAD::Independent(ax);
//
// au
// call atomic function and store result in au
CPPAD_TESTVECTOR( CppAD::AD<double> ) au(m);
afun(ax, au);
//
// ay
CPPAD_TESTVECTOR( CppAD::AD<double> ) ay(m);
ay[0] = 1.0 + au[0];
//
// f
// create f: x -> y and stop tape recording
CppAD::ADFun<double> f(ax, ay);
//
// check
double check = 1.0 + 1.0 / x0;
//
// ok
// check ay[0]
ok &= CppAD::NearEqual( Value(ay[0]) , check, eps, eps);
//
// ok
// check zero order forward mode
CPPAD_TESTVECTOR( double ) x(n), y(m);
x[0] = x0;
y = f.Forward(0, x);
ok &= CppAD::NearEqual(y[0] , check, eps, eps);
//
return ok;
}
Input File: example/atomic_four/get_started.cpp