/* nag_opt_lsq_no_deriv (e04fcc) Example Program. * * Copyright 1991 Numerical Algorithms Group. * * Mark 2, 1991. * Mark 7 revised, 2001. * Mark 8 revised, 2004. * */ #include #include #include #include #include #include #include #include #ifdef __cplusplus extern "C" { #endif static void NAG_CALL lsqfun(Integer m, Integer n, double x[], double fvec[], 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(int argc, char *argv[]) { FILE *fpin, *fpout; char *optionsfile = 0; char *outfile = 0; 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); /* Check for command-line IO options */ fpin = nag_example_file_io(argc, argv, "-data", NULL); fpout = nag_example_file_io(argc, argv, "-results", NULL); (void) nag_example_file_io(argc, argv, "-options", &optionsfile); (void) nag_example_file_io(argc, argv, "-nag_write", &outfile); if (!outfile) { outfile = NAG_ALLOC(7, char); strcpy(outfile, "stdout"); } fprintf(fpout, "nag_opt_lsq_no_deriv (e04fcc) Example Program Results\n"); fscanf(fpin, " %*[^\n]"); /* Skip heading in data file */ n = 3; m = 15; if (m >= 1 && n <= m) { if (!(fjac = NAG_ALLOC(m*n, double)) || !(fvec = NAG_ALLOC(m, double)) || !(x = NAG_ALLOC(n, double))) { fprintf(fpout, "Allocation failure\n"); exit_status = -1; goto END; } tdfjac = n; } else { fprintf(fpout, "Invalid m or n.\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) */ nt = 3; for (i = 0; i < m; ++i) { fscanf(fpin, "%lf", &s.y[i]); for (j = 0; j < nt; ++j) fscanf(fpin, "%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); /* Initialise options structure */ strcpy(options.outfile, outfile); /* Set one option directly. */ /* nag_machine_precision (x02ajc). * The machine precision */ options.optim_tol = 10.0*sqrt(X02AJC); /* Read remaining option values from file */ print = Nag_FALSE; /* nag_opt_read (e04xyc). * Read options from a text file */ if (strcmp(outfile, "stdout")) fclose(fpout); nag_opt_read("e04fcc", optionsfile, &options, print, outfile, &fail); if (strcmp(outfile, "stdout")) { fpout = fopen(outfile, "a"); } if (fail.code != NE_NOERROR) { fprintf(fpout, "Error from nag_opt_read (e04xyc).\n%s\n", fail.message); exit_status = 1; goto END; } /* Assign address of user defined structure to * comm.p for communication to lsqfun(). */ comm.p = (Pointer)&s; /* nag_opt_lsq_no_deriv (e04fcc), see above. */ if (strcmp(outfile, "stdout")) fclose(fpout); nag_opt_lsq_no_deriv(m, n, lsqfun, x, &fsumsq, fvec, fjac, tdfjac, &options, &comm, &fail); if (strcmp(outfile, "stdout")) { fpout = fopen(outfile, "a"); } if (fail.code != NE_NOERROR) { fprintf(fpout, "Error/Warning from nag_opt_lsq_no_deriv (e04fcc).\n%s\n", fail.message); if (fail.code != NW_COND_MIN) exit_status = 1; } /* 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) { fprintf(fpout, "Error from nag_opt_free (e04xzc).\n%s\n", fail.message); exit_status = 2; goto END; } END: if (fpin != stdin) fclose(fpin); if (fpout != stdout) fclose(fpout); if (fjac) NAG_FREE(fjac); if (fvec) NAG_FREE(fvec); if (x) NAG_FREE(x); if (optionsfile) NAG_FREE(optionsfile); if (outfile) NAG_FREE(outfile); return exit_status; } static void NAG_CALL lsqfun(Integer m, Integer n, double x[], double fvec[], Nag_Comm *comm) { /* Function to evaluate the residuals. * * 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. */ Integer i; struct user *s = (struct user *) comm->p; 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 */