NAG Library Manual, Mark 27.2
Interfaces:  FL   CL   CPP   AD 

NAG AD Library Introduction
Example description
/* nag::ad::c05ay Tangent over Tangent Example Program.
 */

#include <dco.hpp>
#include <nagad.h>
#include <iostream>

// Function which calls NAG AD Library routines.
template<typename T>
void func(T r, T &x);

// Driver with the tangent calls.
// Finds the zero point f(xv) = 0 for the function
// f(x) =  exp(-x) - r*x.
// Also, computes the Hessian d2x_dr2 = d2xv/dr2.
void driver(const double &rv, double &xv, double &d2x_dr2);

// The function f
template<typename T>
void (NAG_CALL f)(void* &ad_handle, const T &x, T &z, Integer iuser[], T ruser[]);

int main()
{
  std::cout << " nag::ad::c05ay Tangent over Tangent Example Program Results\n";

  // Set problem parameters
  double rv = 2.0;
  // Solution x
  double xv;
  // Derivative of x
  double d2x_dr2;

  // Call driver
  driver(rv,xv,d2x_dr2);

  // Print outputs
  std::cout << "\n Derivatives calculated: Second order tangents\n";

  // Print derivatives
  std::cout.setf(std::ios::scientific,std::ios::floatfield);
  std::cout.precision(12);
  std::cout << "\n Solution:\n";
  std::cout << " x = " << xv << std::endl;
  std::cout << "\n Second derivative of solution x w.r.t. parameter r:\n";
  std::cout << " d2x/dr2(x) = " << d2x_dr2 << std::endl;
  
  return 0;
}

// Driver with the tangent calls.
// Finds the zero point f(xv) = 0 for the function
// f(x) =  exp(-x) - r*x.
// Also, computes the Hessian d2x_dr2 = d2xv/dr2.
void driver(const double &rv, double &xv, double &d2x_dr2)
{
  using T = dco::gt1s<dco::gt1s<double>::type>::type;

  // Function parameter r
  T r = rv;
  // Variable to differentiate w.r.t.
  dco::derivative(dco::value(r)) = 1.0;
  dco::value(dco::derivative(r)) = 1.0;

  // Variable to differentiate
  T x;

  // Call the NAG AD Lib functions
  func(r,x);

  // Extract the computed solution
  xv = dco::passive_value(x);
  // Extract the 2nd order tangent of x
  d2x_dr2 = dco::derivative(dco::derivative(x));
}

// Function which calls NAG AD Library routines.
template<typename T>
void func(T r, T &x)
{
  // Active variables
  T a = 0.0, b = 1.0;
  T eps =  1.0e-5, eta = 0.0;
  // Create AD configuration data object
  Integer ifail = 0;
  void *ad_handle = 0;
  nag::ad::x10aa(ad_handle, ifail);
  // Call routine for computing an approximation to a simple zero of the function f
  ifail = 0;
  nag::ad::c05ay(ad_handle,a,b,eps,eta,f<T>,x,0,nullptr,1,&r,ifail);
  // Remove computational data object
  ifail = 0;
  nag::ad::x10ab(ad_handle, ifail);
}

// The function f
template<typename T>
void (NAG_CALL f)(void* &ad_handle, const T &x, T &z, Integer iuser[], T ruser[])
{
  T r = ruser[0];
  // Evaluate nonlinear function
  z = exp(-x) - x*r;
  
}