/* nag_opt_lsq_uncon_covariance (e04ycc) Example Program.
*
* Copyright 2023 Numerical Algorithms Group.
*
* Mark 29.0, 2023.
*
*/
#include <math.h>
#include <nag.h>
#include <stdio.h>
#include <string.h>
#ifdef __cplusplus
extern "C" {
#endif
static void NAG_CALL lsqfun(Integer m, Integer n, const double x[],
double fvec[], Nag_Comm *comm);
#ifdef __cplusplus
}
#endif
/* Define a user structure template to store data in lsqfun */
struct user {
double *y;
double *t;
};
#define T(I, J) t[(I)*tdt + J]
int main(void) {
Integer exit_status = 0, i, j, job, m, n, nt, tdj, tdt;
NagError fail;
Nag_Comm comm;
Nag_E04_Opt options;
double *cj = 0, *fjac = 0, fsumsq, *fvec = 0, *x = 0;
struct user s;
INIT_FAIL(fail);
s.y = 0;
s.t = 0;
printf("nag_opt_lsq_uncon_covariance (e04ycc) Example Program Results\n");
scanf(" %*[^\n]"); /* Skip heading in data file */
n = 3;
m = 15;
nt = 3;
if (n >= 1 && n <= m) {
if (!(fjac = NAG_ALLOC(m * n, double)) || !(fvec = NAG_ALLOC(m, double)) ||
!(x = NAG_ALLOC(n, double)) || !(cj = NAG_ALLOC(n, double)) ||
!(s.y = NAG_ALLOC(m, double)) || !(s.t = NAG_ALLOC(m * nt, double))) {
printf("Allocation failure\n");
exit_status = -1;
goto END;
}
tdj = n;
tdt = nt;
} else {
printf("Invalid n or m.\n");
exit_status = 1;
return exit_status;
}
/* Read data into structure.
* Observations t (j = 0, 1, 2) are held in s->t[i][j]
* (i = 0, 1, 2, . . ., 14)
*/
for (i = 0; i < m; ++i) {
scanf("%lf", &s.y[i]);
for (j = 0; j < nt; ++j)
scanf("%lf", &s.T(i, j));
}
/* Set up the starting point */
x[0] = 0.5;
x[1] = 1.0;
x[2] = 1.5;
/* nag_opt_init (e04xxc).
* Initialization function for option setting
*/
nag_opt_init(&options); /* Initialize options structure */
/* Turn off most monitoring information from e04fcc */
options.list = Nag_FALSE;
options.print_level = Nag_Soln;
/* Assign address of user defined structure to
* comm.p for communication to lsqfun().
*/
comm.p = (Pointer)&s;
/* nag_opt_lsq_uncon_mod_func_comp (e04fcc).
* Unconstrained nonlinear least squares (no derivatives
* required)
*/
fflush(stdout);
nag_opt_lsq_uncon_mod_func_comp(m, n, lsqfun, x, &fsumsq, fvec, fjac, tdj,
&options, &comm, &fail);
if (fail.code != NE_NOERROR && fail.code != NW_COND_MIN) {
printf("Error from nag_opt_lsq_uncon_mod_func_comp (e04fcc).\n%s\n",
fail.message);
exit_status = 1;
goto END;
}
job = 0;
/* nag_opt_lsq_uncon_covariance (e04ycc).
* Covariance matrix for nonlinear least squares
*/
nag_opt_lsq_uncon_covariance(job, m, n, fsumsq, cj, &options, &fail);
if (fail.code != NE_NOERROR) {
printf("Error from nag_opt_lsq_uncon_covariance (e04ycc).\n%s\n",
fail.message);
exit_status = 1;
goto END;
}
printf("\nEstimates of the variances of the sample regression");
printf(" coefficients are:\n");
for (i = 0; i < n; ++i)
printf(" %15.5e", cj[i]);
printf("\n");
/* Free memory allocated to pointers s and v */
/* nag_opt_free (e04xzc).
* Memory freeing function for use with option setting
*/
nag_opt_free(&options, "all", &fail);
if (fail.code != NE_NOERROR) {
printf("Error from nag_opt_free (e04xzc).\n%s\n", fail.message);
exit_status = 1;
goto END;
}
END:
NAG_FREE(fjac);
NAG_FREE(fvec);
NAG_FREE(x);
NAG_FREE(cj);
NAG_FREE(s.y);
NAG_FREE(s.t);
return exit_status;
}
static void NAG_CALL lsqfun(Integer m, Integer n, const double x[],
double fvec[], Nag_Comm *comm) {
/* Function to evaluate the residuals.
*
* The address of the user defined structure is recovered in each call
* to lsqfun() from comm->p and the structure used in the calculation
* of the residuals.
*/
Integer i, tdt;
struct user *s = (struct user *)comm->p;
tdt = n;
for (i = 0; i < m; ++i)
fvec[i] =
x[0] + s->T(i, 0) / (x[1] * s->T(i, 1) + x[2] * s->T(i, 2)) - s->y[i];
} /* lsqfun */