Example description
/* C05AU_A1W_F C++ Header Example Program.
 *
 * Copyright 2019 Numerical Algorithms Group.
 * Mark 27, 2019.
 */

#include <nag.h>
#include <stdio.h>
#include <math.h>
#include <nag.h>
#include <dco.hpp>
#include <nagad.h>
#include <stdio.h>
#include <math.h>
#include <nag_stdlib.h>
#include <iostream>
#include <string>

typedef double DCO_BASE_TYPE;
typedef dco::ga1s<DCO_BASE_TYPE> DCO_MODE;
typedef DCO_MODE::type DCO_TYPE;
typedef DCO_MODE::tape_t DCO_TAPE_TYPE;

extern "C"
{
  static void NAG_CALL f(void * &ad_handle,
                         const DCO_TYPE &x,
                         DCO_TYPE &z,
                         Integer iuser[],
                         DCO_TYPE ruser[]);
}

int main(void)
{
  /* Scalars */
  Integer exit_status = 0;
  DCO_TYPE a, b, eps, eta, h, x;
  Integer ifail;
  /* Arrays */
  DCO_TYPE ruser[1];
  Integer iuser[1];

  printf("C05AU_A1W_F C++ Header Example Program Results\n");

  // Create AD tape
  DCO_MODE::global_tape=DCO_TAPE_TYPE::create();
  void    *ad_handle = 0;
  x10aa_a1w_f_(ad_handle,ifail);

  ruser[0] = 1.0;
  x = 1.0;
  h = 0.1;
  eps = 1e-05;
  eta = 0.0;

  DCO_MODE::global_tape->register_variable(ruser[0]);

  c05au_a1w_f_(ad_handle, x, h, eps, eta, f, a, b, iuser,ruser, ifail);
  if (ifail == 0) {
    printf("Root is %13.5f\n", dco::value(x));
    printf("Interval searched is [%8.5f,%8.5f]\n", dco::value(a),
           dco::value(b));
  } else {
    printf("%" NAG_IFMT "\n", ifail);
    if (ifail == 3 || ifail == 4)
      printf("Final value = %13.5f\n", dco::value(x));
    exit_status = 1;
  }
  dco::derivative(x) = 1.0;
  DCO_MODE::global_tape->interpret_adjoint();

  printf("dx/druser %26.16f\n", dco::derivative(ruser[0]));

  // Remove computational data object and tape
  x10ab_a1w_f_(ad_handle,ifail);
  DCO_TAPE_TYPE::remove(DCO_MODE::global_tape);

  return exit_status;
}

static void (NAG_CALL f)(void * &ad_handle,
                       const DCO_TYPE &x,
                       DCO_TYPE &z,
                       Integer iuser[],
                       DCO_TYPE ruser[])
{
  z = x - exp(-ruser[0]*x);
}