/* nag_check_derivs (c05zdc) Example Program.
*
* Copyright 2014 Numerical Algorithms Group.
*
* Mark 23, 2011.
*/
#include <nag.h>
#include <stdio.h>
#include <nag_stdlib.h>
#include <nagc05.h>
#ifdef __cplusplus
extern "C" {
#endif
static void NAG_CALL f(Integer m, Integer n, double x[], double fvec[],
double fjac[], Integer iflag);
#ifdef __cplusplus
}
#endif
int main(void)
{
Integer exit_status = 0, j, m, n, mode, iflag, err_detected;
NagError fail;
double *fjac = 0, *fvec = 0, *x = 0, *xp = 0, *fvecp = 0, *err = 0;
INIT_FAIL(fail);
printf("nag_check_derivs (c05zdc) Example Program Results\n");
n = 3;
m = n;
if (n > 0)
{
if (!(fjac = NAG_ALLOC(m*n, double)) ||
!(fvec = NAG_ALLOC(m, double)) ||
!(fvecp = NAG_ALLOC(m, double)) ||
!(err = NAG_ALLOC(m, double)) ||
!(x = NAG_ALLOC(n, double)) ||
!(xp = NAG_ALLOC(n, double)))
{
printf("Allocation failure\n");
exit_status = -1;
goto END;
}
}
else
{
printf("Invalid n.\n");
exit_status = 1;
goto END;
}
/* Set up an arbitrary point at which to check the 1st derivatives */
x[0] = 9.2e-01;
x[1] = 1.3e-01;
x[2] = 5.4e-01;
/* nag_check_derivs (c05zdc).
* Derivative checker for user-supplied Jacobian
*/
mode = 1;
nag_check_derivs(mode, m, n, x, fvec, fjac, xp, fvecp, err, &fail);
if (fail.code != NE_NOERROR)
{
printf("Error from nag_check_derivs (c05zdc).\n%s\n",
fail.message);
exit_status = 1;
goto END;
}
/* Evaluate at the original point x and the update point xp */
/* Get fvec, the functions at x */
iflag = 1;
f(m, n, x, fvec, fjac, iflag);
/* Get fvecp, the functions at xp */
iflag = 1;
f(m, n, xp, fvecp, fjac, iflag);
/* Get fjac, the Jacobian at x */
iflag = 2;
f(m, n, x, fvec, fjac, iflag);
mode = 2;
nag_check_derivs(mode, m, n, x, fvec, fjac, xp, fvecp, err, &fail);
if (fail.code != NE_NOERROR)
{
printf("Error from nag_check_derivs (c05zdc).\n%s\n",
fail.message);
exit_status = 1;
goto END;
}
printf("\nAt point ");
for (j = 0; j < n; ++j)
printf("%13.5e", x[j]);
printf(",\n");
err_detected = 0;
for (j = 0; j < n; ++j)
{
if (err[j] <= 0.5)
{
printf("suspicious gradient number %"NAG_IFMT
" with error measure %13.5e\n", j, err[j]);
err_detected = 1;
}
}
if (!err_detected)
{
printf("gradients appear correct\n");
}
END:
NAG_FREE(fjac);
NAG_FREE(fvec);
NAG_FREE(fvecp);
NAG_FREE(err);
NAG_FREE(x);
NAG_FREE(xp);
return exit_status;
}
static void NAG_CALL f(Integer m, Integer n, double x[], double fvec[],
double fjac[], Integer iflag)
{
Integer j, k;
if (iflag == 1)
{
/* Calculate the function values */
for (k = 0; k < m; k++)
{
fvec[k] = (3.0-x[k]*2.0) * x[k] + 1.0;
if (k > 0) fvec[k] -= x[k-1];
if (k < m-1) fvec[k] -= x[k+1] * 2.0;
}
}
else if (iflag == 2)
{
/* Calculate the corresponding first derivatives */
for (k = 0; k < m; k++)
{
for (j = 0; j < n; j++)
fjac[j*m + k] = 0.0;
fjac[k*m + k] = 3.0 - x[k] * 4.0;
if (k > 0)
fjac[(k-1)*m + k] = -1.0;
if (k < m-1)
fjac[(k+1)*m + k] = -2.0;
}
}
}