```/* nag_opt_estimate_deriv (e04xac) Example Program.
*
* Copyright 2017 Numerical Algorithms Group.
*
* Mark 26.1, 2017.
*
*/
#include <nag.h>
#include <nag_stdlib.h>
#include <stdio.h>
#include <string.h>
#include <nage04.h>

#ifdef __cplusplus
extern "C"
{
#endif
static void NAG_CALL objfun(Integer n, const double x[], double *objf,
double g[], Nag_Comm *comm);
#ifdef __cplusplus
}
#endif

#define H(I, J) h[(I) *tdh + J]

int main(void)
{
Integer exit_status = 0, i, j, n, tdh;
double *g = 0, *h = 0, *h_central = 0, *h_forward = 0, *hess_diag = 0,
objf, *x = 0;
Nag_Comm comm;
Nag_DerivInfo *deriv_info = 0;
Nag_E04_Opt options;
NagError fail;

INIT_FAIL(fail);

printf("nag_opt_estimate_deriv (e04xac) Example Program Results\n");
n = 4;

if (!(x = NAG_ALLOC(n, double)) ||
!(h_central = NAG_ALLOC(n, double)) ||
!(h_forward = NAG_ALLOC(n, double)) ||
!(g = NAG_ALLOC(n, double)) ||
!(h = NAG_ALLOC(n * n, double)) ||
!(hess_diag = NAG_ALLOC(n, double)) ||
!(deriv_info = NAG_ALLOC(n, Nag_DerivInfo))
)
{
printf("Allocation failure\n");
exit_status = -1;
goto END;
}
tdh = n;

x[0] = 3.0;
x[1] = -1.0;
x[2] = 0.0;
x[3] = 1.0;

/* nag_opt_init (e04xxc).
* Initialization function for option setting
*/
nag_opt_init(&options);
options.list = Nag_FALSE;
options.print_deriv = Nag_D_NoPrint;

printf("\nEstimate gradient and Hessian diagonals given function only\n");

/* Note: it is acceptable to pass an array of length n (hess_diag)
* as the Hessian parameter in this case.
*/
/* nag_opt_estimate_deriv (e04xac), see above. */
nag_opt_estimate_deriv(n, x, objfun, &objf, g, h_forward, h_central,
hess_diag, tdh, deriv_info, &options, &comm, &fail);
if (fail.code != NE_NOERROR) {
printf("Error from nag_opt_estimate_deriv (e04xac).\n%s\n", fail.message);
exit_status = 1;
goto END;
}

printf("\nFunction value: %13.4e\n", objf);
for (i = 0; i < n; ++i)
printf("%13.4e  ", g[i]);
printf("\nEstimated Hessian matrix diagonal\n");
for (i = 0; i < n; ++i)
printf("%13.4e  ", hess_diag[i]);
printf("\n");

options.deriv_want = Nag_HessFull;

printf("\nEstimate full Hessian given function and gradients\n");
/* nag_opt_estimate_deriv (e04xac), see above. */
nag_opt_estimate_deriv(n, x, objfun, &objf, g, h_forward, h_central,
h, tdh, deriv_info, &options, &comm, &fail);
if (fail.code != NE_NOERROR) {
printf("Error from nag_opt_estimate_deriv (e04xac).\n%s\n", fail.message);
exit_status = 1;
goto END;
}

printf("\nFunction value: %13.4e\n", objf);
for (i = 0; i < n; ++i)
printf("%13.4e  ", g[i]);
printf("\nEstimated Hessian matrix\n");
for (i = 0; i < n; ++i) {
for (j = 0; j < n; ++j)
printf("%13.4e  ", H(i, j));
printf("\n");
}

END:
NAG_FREE(x);
NAG_FREE(h_central);
NAG_FREE(h_forward);
NAG_FREE(g);
NAG_FREE(h);
NAG_FREE(hess_diag);
NAG_FREE(deriv_info);

return exit_status;
}

static void NAG_CALL objfun(Integer n, const double x[], double *objf,
double g[], Nag_Comm *comm)
{
double a, asq, b, bsq, c, csq, d, dsq;

a = x[0] + 10.0 * x[1];
b = x[2] - x[3];
c = x[1] - 2.0 * x[2];
d = x[0] - x[3];
asq = a * a;
bsq = b * b;
csq = c * c;
dsq = d * d;
*objf = asq + 5.0 * bsq + csq * csq + 10.0 * dsq * dsq;
if (comm->flag == 2) {
g[0] = 2.0 * a + 40.0 * d * dsq;
g[1] = 20.0 * a + 4.0 * c * csq;
g[2] = 10.0 * b - 8.0 * c * csq;
g[3] = -10.0 * b - 40.0 * d * dsq;
}
}

/* objfun */
```