/* nag_roots_sys_deriv_check (c05zdc) Example Program.
*
* Copyright 2024 Numerical Algorithms Group.
*
* Mark 30.3, 2024.
*/
#include <nag.h>
#include <stdio.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_roots_sys_deriv_check (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_roots_sys_deriv_check (c05zdc).
* Derivative checker for user-supplied Jacobian
*/
mode = 1;
nag_roots_sys_deriv_check(mode, m, n, x, fvec, fjac, xp, fvecp, err, &fail);
if (fail.code != NE_NOERROR) {
printf("Error from nag_roots_sys_deriv_check (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_roots_sys_deriv_check(mode, m, n, x, fvec, fjac, xp, fvecp, err, &fail);
if (fail.code != NE_NOERROR) {
printf("Error from nag_roots_sys_deriv_check (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;
}
}
}