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