Prev Next atomic_three_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_three function.

Start Class Definition
# include <cppad/cppad.hpp>  // CppAD include file
namespace {                  // start empty namespace
using CppAD::vector;         // abbreviate CppAD::vector using vector
// start definition of atomic derived class using atomic_three interface
class atomic_get_started : public CppAD::atomic_three<double> {

Constructor
public:
    // can use const char* name when calling this constructor
    atomic_get_started(const std::string& name) : // can have more arguments
    CppAD::atomic_three<double>(name)             // inform base class of name
    { }

private:

for_type
    // calculate type_y
    bool for_type(
        const vector<double>&               parameter_x ,
        const vector<CppAD::ad_type_enum>&  type_x      ,
        vector<CppAD::ad_type_enum>&        type_y      ) override
    {   assert( parameter_x.size() == type_x.size() );
        bool ok = type_x.size() == 1; // n
        ok     &= type_y.size() == 1; // m
        if( ! ok )
            return false;
        type_y[0] = type_x[0];
        return true;
    }

forward
    // forward mode routine called by CppAD
    bool forward(
        const vector<double>&               parameter_x  ,
        const vector<CppAD::ad_type_enum>&  type_x       ,
        size_t                              need_y       ,
        size_t                              order_low    ,
        size_t                              order_up     ,
        const vector<double>&               taylor_x     ,
        vector<double>&                     taylor_y     ) override
    {
# ifndef NDEBUG
        size_t n = taylor_x.size() / (order_up + 1);
        size_t m = taylor_y.size() / (order_up + 1);
# endif
        assert( n == 1 );
        assert( m == 1 );
        assert( order_low <= order_up );

        // return flag
        bool ok = order_up == 0;
        if( ! ok )
            return ok;

        // Order zero forward mode.
        // This case must always be implemented
        // y^0 = g( x^0 ) = 1 / x^0
        taylor_y[0] = 1. / taylor_x[0];
        //
        return ok;
    }

End Class Definition

}; // End of atomic_get_started class
}  // End empty namespace

Use Atomic Function
bool get_started(void)
{   bool ok = true;
    using CppAD::AD;
    using CppAD::NearEqual;
    double eps = 10. * CppAD::numeric_limits<double>::epsilon();

Constructor

    // Create the atomic get_started object corresponding to g(x)
    atomic_get_started afun("atomic_get_started");

Recording
    // Create the function f(x) which is eqaul to g(x) for this example.
    //
    // domain space vector
    size_t  n  = 1;
    double  x0 = 0.5;
    CPPAD_TESTVECTOR( AD<double> ) ax(n);
    ax[0]     = x0;

    // declare independent variables and start tape recording
    CppAD::Independent(ax);

    // range space vector
    size_t m = 1;
    CPPAD_TESTVECTOR( AD<double> ) ay(m);

    // call atomic function and store result in au[0]
    // u = 1 / x
    CPPAD_TESTVECTOR( AD<double> ) au(m);
    afun(ax, au);

    // now use AD division to invert to invert the operation
    ay[0] = 1.0 / au[0]; // y = 1 / u = x

    // create f: x -> y and stop tape recording
    CppAD::ADFun<double> f;
    f.Dependent (ax, ay);  // f(x) = x

forward
    // check function value
    double check = x0;
    ok &= NearEqual( Value(ay[0]) , check,  eps, eps);

    // check zero order forward mode
    size_t q;
    CPPAD_TESTVECTOR( double ) x_q(n), y_q(m);
    q      = 0;
    x_q[0] = x0;
    y_q    = f.Forward(q, x_q);
    ok    &= NearEqual(y_q[0] , check,  eps, eps);
Return Test Result

    return ok;
}

Input File: example/atomic_three/get_started.cpp