```/* nag_opt_lsq_deriv (e04gbc) Example Program.
*
* Copyright 2014 Numerical Algorithms Group.
*
* Mark 2, 1991.
* Mark 7 revised, 2001.
* Mark 7a revised, 2003.
* Mark 8 revised, 2004.
*
*/

#include <nag.h>
#include <stdio.h>
#include <string.h>
#include <nag_stdlib.h>
#include <math.h>
#include <nage04.h>

#ifdef __cplusplus
extern "C" {
#endif
static void NAG_CALL lsqfun(Integer m, Integer n, const double x[],
double fvec[], double fjac[], Integer tdfjac,
Nag_Comm *comm);
#ifdef __cplusplus
}
#endif

#define MMAX 15
#define TMAX 3

/* Define a user structure template to store data in lsqfun. */
struct user
{
double y[MMAX];
double t[MMAX][TMAX];
};

int main(void)
{
const char  *optionsfile = "e04gbce.opt";
Integer     exit_status = 0;
Nag_Boolean print;
Integer     i, j, m, n, nt, tdfjac;
Nag_Comm    comm;
Nag_E04_Opt options;
double      *fjac = 0, fsumsq, *fvec = 0, *x = 0;
struct user s;
NagError    fail;

INIT_FAIL(fail);

printf("nag_opt_lsq_deriv (e04gbc) Example Program Results\n");
fflush(stdout);
scanf(" %*[^\n]"); /* Skip heading in data file */
n = 3;
m = 15;
nt = 3;
if (m >= 1 && n <= m)
{
if (!(fjac = NAG_ALLOC(m*n, double)) ||
!(fvec = NAG_ALLOC(m, double)) ||
!(x = NAG_ALLOC(n, double)))
{
printf("Allocation failure\n");
exit_status = -1;
goto END;
}
tdfjac = n;
}
else
{
printf("Invalid m or n.\n");
exit_status = 1;
return exit_status;
}

* Observations t (j = 0, 1, 2) are held in s->t[i][j]
* (i = 0, 1, 2, . . .,  14)
*/
nt = 3;
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.5;
x = 1.0;
x = 1.5;

/* Initialise options structure and read option values from file */
print = Nag_TRUE;
/* nag_opt_init (e04xxc).
* Initialization function for option setting
*/
nag_opt_init(&options);
* Read options from a text file
*/
nag_opt_read("e04gbc", optionsfile, &options, print, "stdout", &fail);
if (fail.code != NE_NOERROR)
{
exit_status = 1;
goto END;
}

/* Assign address of user defined structure to
* comm.p for communication to lsqfun().
*/
comm.p = (Pointer)&s;

/* Call the optimization routine */
/* nag_opt_lsq_deriv (e04gbc), see above. */
nag_opt_lsq_deriv(m, n, lsqfun, x, &fsumsq, fvec, fjac, tdfjac,
&options, &comm, &fail);
if (fail.code != NE_NOERROR)
{
printf("Error/Warning from nag_opt_lsq_deriv (e04gbc).\n%s\n",
fail.message);
if (fail.code != NW_COND_MIN)
exit_status = 1;
}

/* Free memory allocated by nag_opt_lsq_deriv (e04gbc) 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 = 2;
}
END:
NAG_FREE(fjac);
NAG_FREE(fvec);
NAG_FREE(x);

return exit_status;
}

static void NAG_CALL lsqfun(Integer m, Integer n, const double x[],
double fvec[], double fjac[], Integer tdfjac,
Nag_Comm *comm)
{
/* Function to evaluate the residuals and their 1st derivatives.
*
* This function is also suitable for use when Nag_Lin_NoDeriv is specified
* for linear minimization instead of the default of Nag_Lin_Deriv,
* since it can deal with comm->flag = 0 or 1 as well as comm->flag = 2.
*
* To avoid the use of a global varibale this example assigns the address
* of a user defined structure to comm.p in the main program (where the
* data was also read in).
* The address of this structure is recovered in each call to lsqfun()
* from comm->p and the structure used in the calculation of the residuals.
*/

#define FJAC(I, J) fjac[(I) *tdfjac + (J)]

Integer     i;
double      denom, dummy;
struct user *s = (struct user *) comm->p;

for (i = 0; i < m; ++i)
{
denom = x*s->t[i] + x*s->t[i];
if (comm->flag != 1)
fvec[i] = x + s->t[i]/denom - s->y[i];
if (comm->flag != 0)
{
FJAC(i, 0) = 1.0;
dummy = -1.0 / (denom * denom);
FJAC(i, 1) = s->t[i]*s->t[i]*dummy;
FJAC(i, 2) = s->t[i]*s->t[i]*dummy;
}
}
} /* lsqfun */
```