# include <cppad/cppad.hpp>
namespace {
// f(x) = |x|^2 / 2 = .5 * ( x[0]^2 + ... + x[n-1]^2 )
template <class Type>
Type f(CPPAD_TEST_VECTOR<Type> &x)
{ Type sum;
sum = 0.;
size_t i = x.size();
for(i = 0; i < x.size(); i++)
sum += x[i] * x[i];
return .5 * sum;
}
}
bool mul_level(void)
{ bool ok = true; // initialize test result
typedef CppAD::AD<double> A1_double; // for one level of taping
typedef CppAD::AD<A1_double> A2_double; // for two levels of taping
size_t n = 5; // dimension for example
size_t j; // a temporary index variable
CPPAD_TEST_VECTOR<double> x(n);
CPPAD_TEST_VECTOR<A1_double> a1_x(n), a1_v(n), a1_dy(1) ;
CPPAD_TEST_VECTOR<A2_double> a2_x(n), a2_y(1);
// Values for the independent variables while taping the function f(x)
for(j = 0; j < n; j++)
a2_x[j] = a1_x[j] = x[j] = double(j);
// Declare the independent variable for taping f(x)
CppAD::Independent(a2_x);
// Use AD< AD<double> > to tape the evaluation of f(x)
a2_y[0] = f(a2_x);
// Declare a1_F as the corresponding ADFun< AD<double> > value a2_y
// (make sure we do not run zero order forward during constructor)
CppAD::ADFun<A1_double> a1_F;
a1_F.Dependent(a2_x, a2_y);
// Values for the independent variables while taping f'(x) * v
// Declare the independent variable for taping f'(x) * v
CppAD::Independent(a1_x);
// set the argument value x for computing f'(x) * v
a1_F.Forward(0, a1_x);
// compute f'(x) * v
for(j = 0; j < n; j++)
a1_v[j] = double(n - j);
a1_dy = a1_F.Forward(1, a1_v);
// declare dF as ADFun<double> function corresponding to f'(x) * v
CppAD::ADFun<double> dF;
dF.Dependent(a1_x, a1_dy);
// optimize out operations not necessary for function f'(x) * v
dF.optimize();
// Evaluate f'(x) * v
dF.Forward(0, x);
// compute the d/dx of f'(x) * v = f''(x) * v = v
CPPAD_TEST_VECTOR<double> w(1);
CPPAD_TEST_VECTOR<double> dw(n);
w[0] = 1.;
dw = dF.Reverse(1, w);
for(j = 0; j < n; j++)
ok &= CppAD::NearEqual(dw[j], a1_v[j], 1e-10, 1e-10);
return ok;
}