1 /* --------------------------------------------------------------------------
2 CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-18 Bradley M. Bell
3 
4 CppAD is distributed under the terms of the
5              Eclipse Public License Version 2.0.
6 
7 This Source Code may also be made available under the following
8 Secondary License when the conditions for such availability set forth
9 in the Eclipse Public License, Version 2.0 are satisfied:
10       GNU General Public License, Version 2.0 or later.
11 ---------------------------------------------------------------------------- */
12 
13 /*
14 $begin atomic_two_get_started.cpp$$
15 
16 $section Getting Started with Atomic Operations: Example and Test$$
17 
18 $head Purpose$$
19 This example demonstrates the minimal amount of information
20 necessary for a $cref atomic_two$$ operation.
21 
22 $nospell
23 
24 $head Start Class Definition$$
25 $srccode%cpp% */
26 # include <cppad/cppad.hpp>
27 namespace {          // isolate items below to this file
28 using CppAD::vector; // abbreviate as vector
29 class atomic_get_started : public CppAD::atomic_base<double> {
30 /* %$$
31 
32 $head Constructor$$
33 $srccode%cpp% */
34 public:
35     // constructor (could use const char* for name)
atomic_get_started(const std::string & name)36     atomic_get_started(const std::string& name) :
37     // this example does not use any sparsity patterns
38     CppAD::atomic_base<double>(name)
39     { }
40 private:
41 /* %$$
42 $head forward$$
43 $srccode%cpp% */
44     // forward mode routine called by CppAD
forward(size_t p,size_t q,const vector<bool> & vx,vector<bool> & vy,const vector<double> & tx,vector<double> & ty)45     virtual bool forward(
46         size_t                    p ,
47         size_t                    q ,
48         const vector<bool>&      vx ,
49               vector<bool>&      vy ,
50         const vector<double>&    tx ,
51               vector<double>&    ty
52     )
53     {
54 # ifndef NDEBUG
55         size_t n = tx.size() / (q + 1);
56         size_t m = ty.size() / (q + 1);
57 # endif
58         assert( n == 1 );
59         assert( m == 1 );
60 
61         // return flag
62         bool ok = q == 0;
63         if( ! ok )
64             return ok;
65 
66         // check for defining variable information
67         // This case must always be implemented
68         if( vx.size() > 0 )
69             vy[0] = vx[0];
70 
71         // Order zero forward mode.
72         // This case must always be implemented
73         // y^0 = f( x^0 ) = 1 / x^0
74         double f = 1. / tx[0];
75         if( p <= 0 )
76             ty[0] = f;
77         return ok;
78     }
79 /* %$$
80 $head End Class Definition$$
81 $srccode%cpp% */
82 }; // End of atomic_get_started class
83 }  // End empty namespace
84 
85 /* %$$
86 $head Use Atomic Function$$
87 $srccode%cpp% */
get_started(void)88 bool get_started(void)
89 {   bool ok = true;
90     using CppAD::AD;
91     using CppAD::NearEqual;
92     double eps = 10. * CppAD::numeric_limits<double>::epsilon();
93 /* %$$
94 $subhead Constructor$$
95 $srccode%cpp% */
96     // Create the atomic get_started object
97     atomic_get_started afun("atomic_get_started");
98 /* %$$
99 $subhead Recording$$
100 $srccode%cpp% */
101     // Create the function f(x)
102     //
103     // domain space vector
104     size_t n  = 1;
105     double  x0 = 0.5;
106     vector< AD<double> > ax(n);
107     ax[0]     = x0;
108 
109     // declare independent variables and start tape recording
110     CppAD::Independent(ax);
111 
112     // range space vector
113     size_t m = 1;
114     vector< AD<double> > ay(m);
115 
116     // call atomic function and store get_started(x) in au[0]
117     vector< AD<double> > au(m);
118     afun(ax, au);        // u = 1 / x
119 
120     // now use AD division to invert to invert the operation
121     ay[0] = 1.0 / au[0]; // y = 1 / u = x
122 
123     // create f: x -> y and stop tape recording
124     CppAD::ADFun<double> f;
125     f.Dependent (ax, ay);  // f(x) = x
126 /* %$$
127 $subhead forward$$
128 $srccode%cpp% */
129     // check function value
130     double check = x0;
131     ok &= NearEqual( Value(ay[0]) , check,  eps, eps);
132 
133     // check zero order forward mode
134     size_t q;
135     vector<double> x_q(n), y_q(m);
136     q      = 0;
137     x_q[0] = x0;
138     y_q    = f.Forward(q, x_q);
139     ok &= NearEqual(y_q[0] , check,  eps, eps);
140 
141     return ok;
142 }
143 /* %$$
144 $$ $comment end nospell$$
145 $end
146 */
147