31 #define omp_get_max_threads() 1
57 static void lm_initialize_control(lm_control_type * control);
60 static double lm_enorm(
int,
double *);
63 static void lm_minimize(
int m_dat,
int n_par,
double *par,
64 void (*evaluate) (
double *par,
int m_dat,
double *fvec,
65 void *data,
int *info),
66 void (*printout) (
const char *func,
int n_par,
67 double *par,
int m_dat,
68 double *fvec,
void *data,
int iflag,
70 void *data, lm_control_type * control);
77 static void lm_lmdif(
int m,
int n,
double *x,
double *fvec,
double ftol,
78 double xtol,
double gtol,
int maxfev,
double epsfcn,
79 double *diag,
int mode,
double factor,
int *info,
80 int *nfev,
double *fjac,
int *ipvt,
double *qtf,
81 double *wa1,
double *wa2,
double *wa3,
double *wa4,
82 void (*evaluate) (
double *par,
int m_dat,
double *fvec,
83 void *data,
int *info),
84 void (*printout) (
const char *func,
int n_par,
85 double *par,
int m_dat,
86 double *fvec,
void *data,
int iflag,
100 #include "muse_optimize.h"
101 #include "muse_utils.h"
111 cpl_error_code retval;
112 } muse_cpl_optimize_eval_struct;
121 lm_evaluate_cpl (
double *par,
int m_dat,
double *fvec,
void *data,
int *info) {
122 muse_cpl_optimize_eval_struct *s = data;
124 cpl_array *cpl_par = cpl_array_wrap_double(par, s->npar);
125 cpl_array *cpl_fvec = cpl_array_wrap_double(fvec, m_dat);
127 s->retval = (*(s->func))(s->data, cpl_par, cpl_fvec);
129 cpl_array_unwrap(cpl_par);
130 cpl_array_unwrap(cpl_fvec);
132 if (s->retval != CPL_ERROR_NONE) {
137 static const cpl_error_code error_code_tbl[] = {
138 CPL_ERROR_ILLEGAL_INPUT,
142 CPL_ERROR_SINGULAR_MATRIX,
147 CPL_ERROR_ILLEGAL_OUTPUT,
151 static const char *lm_infmsg[] = {
152 "fatal coding error (improper input parameters)",
153 "success (the relative error in the sum of squares is at most tol)",
154 "success (the relative error between x and the solution is at most tol)",
155 "success (both errors are at most tol)",
156 "trapped by degeneracy (fvec is orthogonal to the columns of the jacobian)"
157 "timeout (number of calls to fcn has reached maxcall*(n+1))",
158 "failure (ftol<tol: cannot reduce sum of squares any further)",
159 "failure (xtol<tol: cannot improve approximate solution any further)",
160 "failure (gtol<tol: cannot improve approximate solution any further)",
161 "exception (not enough memory)",
162 "exception (break requested within function evaluation)"
179 int m_dat,
double *fvec,
180 void *data,
int iflag,
int iter,
int nfev) {
182 cpl_msg_debug(func,
"trying step in gradient direction");
183 }
else if (iflag == 1) {
184 cpl_msg_debug(func,
"determining gradient (iteration %d)", iter);
185 }
else if (iflag == 0) {
186 cpl_msg_debug(func,
"starting minimization");
187 }
else if (iflag == -1) {
188 cpl_msg_debug(func,
"terminated after %d evaluations", nfev);
191 char *parstring = cpl_calloc(n_par * 15 + 30,
sizeof(
char));
192 snprintf(parstring, 5,
"par:");
194 for (i = 0; i < n_par; ++i) {
195 snprintf(parstring + strlen(parstring), 15,
" %7.3g", par[i]);
197 snprintf(parstring + strlen(parstring), 25,
" => norm: %7g",
198 lm_enorm(m_dat, fvec));
199 cpl_msg_debug(func,
"%s", parstring);
204 muse_cpl_optimize_eval_struct *mydata
205 = (muse_cpl_optimize_eval_struct *) data;
208 cpl_msg_debug(func,
" fitting data as follows:", mydata);
209 for (i = 0; i < m_dat; ++i) {
210 t = (mydata->tvec)[i];
211 y = (mydata->yvec)[i];
212 f = mydata->f(t, par);
213 cpl_msg_debug(func,
" t[%2d]=%12g y=%12g fit=%12g residue=%12g",
218 UNUSED_ARGUMENT(data);
256 cpl_ensure_code(aPar != NULL, CPL_ERROR_NULL_INPUT);
257 int npars = cpl_array_get_size(aPar);
258 cpl_ensure_code(npars > 0, CPL_ERROR_ILLEGAL_INPUT);
259 cpl_ensure_code(aSize > 0, CPL_ERROR_ILLEGAL_INPUT);
260 cpl_ensure_code(aFunction != NULL, CPL_ERROR_NULL_INPUT);
262 muse_cpl_optimize_eval_struct s = {
269 void (*debug_func) (
const char *, int,
double *, int,
double *,
void *,
270 int, int, int) = NULL;
271 lm_control_type control;
272 lm_initialize_control(&control);
275 control.maxcall = aCtrl->
maxcall;
277 if (aCtrl->
ftol > 0) {
278 control.ftol = aCtrl->
ftol;
280 if (aCtrl->
xtol > 0) {
281 control.xtol = aCtrl->
xtol;
283 if (aCtrl->
gtol > 0) {
284 control.gtol = aCtrl->
gtol;
286 if (aCtrl->
debug == CPL_TRUE) {
291 double timeinit = cpl_test_get_walltime();
292 double cpuinit = cpl_test_get_cputime();
294 cpl_array_get_size(aPar),
295 cpl_array_get_data_double(aPar),
300 double timefini = cpl_test_get_walltime();
301 double cpufini = cpl_test_get_cputime();
303 cpl_msg_debug(__func__,
"Minimizing finished after %i steps: %s",
305 lm_infmsg[control.info]);
307 cpl_msg_debug(__func__,
"processing time %.3fs (%.3fs CPU, %d CPUs)",
308 timefini - timeinit, cpufini - cpuinit, omp_get_max_threads());
311 cpl_error_code res = error_code_tbl[control.info];
313 cpl_ensure_code(res == CPL_ERROR_NONE, res);
348 #define LM_MACHEP DBL_EPSILON
349 #define LM_DWARF DBL_MIN
351 #define LM_SQRT_DWARF sqrt(DBL_MIN)
352 #define LM_SQRT_GIANT sqrt(DBL_MAX)
354 #define LM_SQRT_DWARF 1.e-150
355 #define LM_SQRT_GIANT 1.e150
357 #define LM_USERTOL 30*LM_MACHEP
374 static void lm_initialize_control( lm_control_type * control ) {
375 control->maxcall = 100;
376 control->epsilon = LM_USERTOL;
377 control->stepbound = 100.;
378 control->ftol = LM_USERTOL;
379 control->xtol = LM_USERTOL;
380 control->gtol = LM_USERTOL;
383 static void lm_minimize(
int m_dat,
int n_par,
double *par,
384 void (*evaluate) (
double *par,
int m_dat,
double *fvec,
385 void *data,
int *info),
386 void (*printout) (
const char *func,
387 int n_par,
double *par,
int m_dat,
388 double *fvec,
void *data,
int iflag,
390 void *data, lm_control_type * control ) {
394 double *fvec, *diag, *fjac, *qtf, *wa1, *wa2, *wa3, *wa4;
400 if ( (fvec = (
double *) cpl_malloc(m *
sizeof(
double))) == NULL ||
401 (diag = (
double *) cpl_malloc(n *
sizeof(
double))) == NULL ||
402 (qtf = (
double *) cpl_malloc(n *
sizeof(
double))) == NULL ||
403 (fjac = (
double *) cpl_malloc(n*m*
sizeof(
double))) == NULL ||
404 (wa1 = (
double *) cpl_malloc(n *
sizeof(
double))) == NULL ||
405 (wa2 = (
double *) cpl_malloc(n *
sizeof(
double))) == NULL ||
406 (wa3 = (
double *) cpl_malloc(n *
sizeof(
double))) == NULL ||
407 (wa4 = (
double *) cpl_malloc(m *
sizeof(
double))) == NULL ||
408 (ipvt = (
int *) cpl_malloc(n *
sizeof(
int) )) == NULL ) {
419 lm_lmdif( m, n, par, fvec, control->ftol, control->xtol, control->gtol,
420 control->maxcall * (n + 1), control->epsilon, diag, 1,
421 control->stepbound, &(control->info),
422 &(control->nfev), fjac, ipvt, qtf, wa1, wa2, wa3, wa4,
423 evaluate, printout, data );
426 (*printout) (__func__, n, par, m, fvec, data, -1, 0, control->nfev);
427 control->fnorm = lm_enorm(m, fvec);
428 if ( control->info < 0 )
448 static const char *lm_infmsg[] = {
449 "fatal coding error (improper input parameters)",
450 "success (the relative error in the sum of squares is at most tol)",
451 "success (the relative error between x and the solution is at most tol)",
452 "success (both errors are at most tol)",
453 "trapped by degeneracy (fvec is orthogonal to the columns of the jacobian)"
454 "timeout (number of calls to fcn has reached maxcall*(n+1))",
455 "failure (ftol<tol: cannot reduce sum of squares any further)",
456 "failure (xtol<tol: cannot improve approximate solution any further)",
457 "failure (gtol<tol: cannot improve approximate solution any further)",
458 "exception (not enough memory)",
459 "exception (break requested within function evaluation)"
462 static const char *lm_shortmsg[] = {
485 static void lm_qrfac(
int m,
int n,
double *a,
int pivot,
int *ipvt,
486 double *rdiag,
double *acnorm,
double *wa);
487 static void lm_qrsolv(
int n,
double *r,
int ldr,
int *ipvt,
double *diag,
488 double *qtb,
double *x,
double *sdiag,
double *wa);
489 static void lm_lmpar(
int n,
double *r,
int ldr,
int *ipvt,
double *diag,
490 double *qtb,
double delta,
double *par,
double *x,
491 double *sdiag,
double *wa1,
double *wa2);
493 #define MIN(a,b) (((a)<=(b)) ? (a) : (b))
494 #define MAX(a,b) (((a)>=(b)) ? (a) : (b))
495 #define SQR(x) (x)*(x)
674 static void lm_lmdif(
int m,
int n,
double *x,
double *fvec,
double ftol,
675 double xtol,
double gtol,
int maxfev,
double epsfcn,
676 double *diag,
int mode,
double factor,
int *info,
677 int *nfev,
double *fjac,
int *ipvt,
double *qtf,
678 double *wa1,
double *wa2,
double *wa3,
double *wa4,
679 void (*evaluate) (
double *par,
int m_dat,
double *fvec,
680 void *data,
int *info),
681 void (*printout) (
const char *func,
int n_par,
double *par,
int m_dat,
682 double *fvec,
void *data,
int iflag,
687 double actred, delta, dirder, eps, fnorm, fnorm1, gnorm, par, pnorm,
688 prered, ratio, sum, temp, temp1, temp2, temp3, xnorm;
689 static double p1 = 0.1;
690 static double p0001 = 1.0e-4;
697 temp = MAX(epsfcn, LM_MACHEP);
702 if ((n <= 0) || (m < n) || (ftol < 0.)
703 || (xtol < 0.) || (gtol < 0.) || (maxfev <= 0) || (factor <= 0.)) {
708 for (j = 0; j < n; j++) {
709 if (diag[j] <= 0.0) {
722 (*evaluate) (x, m, fvec, data, info); ++(*nfev);
724 (*printout) (__func__, n, x, m, fvec, data, 0, 0, *nfev);
727 fnorm = lm_enorm(m, fvec);
733 cpl_msg_debug(__func__,
"iter=%d nfev=%d fnorm=%g\n",
740 #pragma omp parallel for default(none) \
741 shared(n, info, m, x, eps, evaluate, data, printout, nfev, iter, \
744 for (j = 0; j < n; j++) {
747 double *wa5 = (
double *) cpl_malloc(m *
sizeof(
double));
748 double *xd = (
double *) cpl_malloc(n *
sizeof(
double));
749 memcpy(xd, x, n *
sizeof(
double));
750 double step = eps * fabs(xd[j]);
755 (*evaluate) (xd, m, wa5, data, &infod);
757 (*printout) (__func__, n, xd, m, wa5, data, 1, iter, ++(*nfev));
765 double diff = xd[j] - x[j];
766 double *fjacm = fjac + j * m;
767 for (i = 0; i < m; i++) {
768 fjacm[i] = (wa5[i] - fvec[i]) / diff;
780 for (i = 0; i < m; i++) {
781 for (j = 0; j < n; j++)
782 printf(
"%.5e ", fjac[j * m + i]);
790 lm_qrfac(m, n, fjac, 1, ipvt, wa1, wa2, wa3);
795 for (j = 0; j < n; j++) {
802 for (j = 0; j < n; j++)
803 wa3[j] = diag[j] * x[j];
804 xnorm = lm_enorm(n, wa3);
806 delta = factor * xnorm;
814 for (i = 0; i < m; i++)
817 for (j = 0; j < n; j++) {
818 temp3 = fjac[j * m + j];
821 for (i = j; i < m; i++)
822 sum += fjac[j * m + i] * wa4[i];
824 for (i = j; i < m; i++)
825 wa4[i] += fjac[j * m + i] * temp;
827 fjac[j * m + j] = wa1[j];
835 for (j = 0; j < n; j++) {
836 if (wa2[ipvt[j]] == 0)
840 for (i = 0; i <= j; i++)
841 sum += fjac[j * m + i] * qtf[i] / fnorm;
842 gnorm = MAX(gnorm, fabs(sum / wa2[ipvt[j]]));
854 for (j = 0; j < n; j++)
855 diag[j] = MAX(diag[j], wa2[j]);
861 printf(
"lmdif/ inner loop iter=%d nfev=%d\n", iter, *nfev);
866 lm_lmpar(n, fjac, m, ipvt, diag, qtf, delta, &par,
871 for (j = 0; j < n; j++) {
873 wa2[j] = x[j] + wa1[j];
874 wa3[j] = diag[j] * wa1[j];
876 pnorm = lm_enorm(n, wa3);
881 delta = MIN(delta, pnorm);
886 (*evaluate) (wa2, m, wa4, data, info); ++(*nfev);
888 (*printout) (__func__, n, x, m, wa4, data, 2, iter, *nfev);
892 fnorm1 = lm_enorm(m, wa4);
894 printf(
"lmdif/ pnorm %.10e fnorm1 %.10e fnorm %.10e"
895 " delta=%.10e par=%.10e\n",
896 pnorm, fnorm1, fnorm, delta, par);
901 if (p1 * fnorm1 < fnorm)
902 actred = 1 - SQR(fnorm1 / fnorm);
909 for (j = 0; j < n; j++) {
911 for (i = 0; i <= j; i++)
912 wa3[i] += fjac[j * m + i] * wa1[ipvt[j]];
914 temp1 = lm_enorm(n, wa3) / fnorm;
915 temp2 = sqrt(par) * pnorm / fnorm;
916 prered = SQR(temp1) + 2 * SQR(temp2);
917 dirder = -(SQR(temp1) + SQR(temp2));
921 ratio = prered != 0 ? actred / prered : 0;
923 printf(
"lmdif/ actred=%.10e prered=%.10e ratio=%.10e"
924 " sq(1)=%.10e sq(2)=%.10e dd=%.10e\n",
925 actred, prered, prered != 0 ? ratio : 0.,
926 SQR(temp1), SQR(temp2), dirder);
935 temp = 0.5 * dirder / (dirder + 0.55 * actred);
936 if (p1 * fnorm1 >= fnorm || temp < p1)
938 delta = temp * MIN(delta, pnorm / p1);
940 }
else if (par == 0. || ratio >= 0.75) {
947 if (ratio >= p0001) {
949 for (j = 0; j < n; j++) {
951 wa2[j] = diag[j] * x[j];
953 for (i = 0; i < m; i++)
955 xnorm = lm_enorm(n, wa2);
961 printf(
"ATTN: iteration considered unsuccessful\n");
968 if (fabs(actred) <= ftol && prered <= ftol && 0.5 * ratio <= 1)
970 if (delta <= xtol * xnorm)
979 if (fabs(actred) <= LM_MACHEP &&
980 prered <= LM_MACHEP && 0.5 * ratio <= 1)
982 if (delta <= LM_MACHEP * xnorm)
984 if (gnorm <= LM_MACHEP)
991 }
while (ratio < p0001);
1069 static void lm_lmpar(
int n,
double *r,
int ldr,
int *ipvt,
double *diag,
1070 double *qtb,
double delta,
double *par,
double *x,
1071 double *sdiag,
double *wa1,
double *wa2)
1073 int i, iter, j, nsing;
1074 double dxnorm, fp, fp_old, gnorm, parc, parl, paru;
1076 static double p1 = 0.1;
1086 for (j = 0; j < n; j++) {
1088 if (r[j * ldr + j] == 0 && nsing == n)
1094 printf(
"nsing %d ", nsing);
1096 for (j = nsing - 1; j >= 0; j--) {
1097 wa1[j] = wa1[j] / r[j + ldr * j];
1099 for (i = 0; i < j; i++)
1100 wa1[i] -= r[j * ldr + i] * temp;
1103 for (j = 0; j < n; j++)
1104 x[ipvt[j]] = wa1[j];
1110 for (j = 0; j < n; j++)
1111 wa2[j] = diag[j] * x[j];
1112 dxnorm = lm_enorm(n, wa2);
1113 fp = dxnorm - delta;
1114 if (fp <= p1 * delta) {
1116 printf(
"lmpar/ terminate (fp<p1*delta)\n");
1128 for (j = 0; j < n; j++)
1129 wa1[j] = diag[ipvt[j]] * wa2[ipvt[j]] / dxnorm;
1131 for (j = 0; j < n; j++) {
1133 for (i = 0; i < j; i++)
1134 sum += r[j * ldr + i] * wa1[i];
1135 wa1[j] = (wa1[j] - sum) / r[j + ldr * j];
1137 temp = lm_enorm(n, wa1);
1138 parl = fp / delta / temp / temp;
1143 for (j = 0; j < n; j++) {
1145 for (i = 0; i <= j; i++)
1146 sum += r[j * ldr + i] * qtb[i];
1147 wa1[j] = sum / diag[ipvt[j]];
1149 gnorm = lm_enorm(n, wa1);
1150 paru = gnorm / delta;
1152 paru = LM_DWARF / MIN(delta, p1);
1157 *par = MAX(*par, parl);
1158 *par = MIN(*par, paru);
1160 *par = gnorm / dxnorm;
1162 printf(
"lmpar/ parl %.4e par %.4e paru %.4e\n", parl, *par, paru);
1172 *par = MAX(LM_DWARF, 0.001 * paru);
1174 for (j = 0; j < n; j++)
1175 wa1[j] = temp * diag[j];
1176 lm_qrsolv(n, r, ldr, ipvt, wa1, qtb, x, sdiag, wa2);
1177 for (j = 0; j < n; j++)
1178 wa2[j] = diag[j] * x[j];
1179 dxnorm = lm_enorm(n, wa2);
1181 fp = dxnorm - delta;
1187 if (fabs(fp) <= p1 * delta
1188 || (parl == 0. && fp <= fp_old && fp_old < 0.)
1194 for (j = 0; j < n; j++)
1195 wa1[j] = diag[ipvt[j]] * wa2[ipvt[j]] / dxnorm;
1197 for (j = 0; j < n; j++) {
1198 wa1[j] = wa1[j] / sdiag[j];
1199 for (i = j + 1; i < n; i++)
1200 wa1[i] -= r[j * ldr + i] * wa1[j];
1202 temp = lm_enorm(n, wa1);
1203 parc = fp / delta / temp / temp;
1208 parl = MAX(parl, *par);
1210 paru = MIN(paru, *par);
1215 *par = MAX(parl, *par + parc);
1271 static void lm_qrfac(
int m,
int n,
double *a,
int pivot,
int *ipvt,
1272 double *rdiag,
double *acnorm,
double *wa)
1276 static double p05 = 0.05;
1280 for (j = 0; j < n; j++) {
1281 acnorm[j] = lm_enorm(m, &a[j * m]);
1282 rdiag[j] = acnorm[j];
1294 for (j = 0; j < minmn; j++) {
1295 double *am = a + j *m;
1301 for (k = j + 1; k < n; k++)
1302 if (rdiag[k] > rdiag[kmax])
1305 double *akmaxm = a + kmax * m;
1306 for (i = 0; i < m; i++) {
1307 double temp = am[i];
1311 rdiag[kmax] = rdiag[j];
1314 ipvt[j] = ipvt[kmax];
1321 ajnorm = lm_enorm(m - j, &am[j]);
1329 for (i = j; i < m; i++)
1336 for (k = j + 1; k < n; k++) {
1338 double *akm = a + k * m;
1340 for (i = j; i < m; i++)
1341 sum += am[i] * akm[i];
1343 double temp = sum / am[j];
1345 for (i = j; i < m; i++)
1346 akm[i] -= temp * am[i];
1348 if (pivot && rdiag[k] != 0.) {
1349 temp = akm[j] / rdiag[k];
1350 temp = MAX(0., 1 - temp * temp);
1351 rdiag[k] *= sqrt(temp);
1352 temp = rdiag[k] / wa[k];
1353 if (p05 * SQR(temp) <= LM_MACHEP) {
1354 rdiag[k] = lm_enorm(m - j - 1, &akm[j + 1]);
1426 lm_qrsolv(
int n,
double *r,
int ldr,
int *ipvt,
double *diag,
1427 double *qtb,
double *x,
double *sdiag,
double *wa)
1429 int i, kk, j, k, nsing;
1430 double qtbpj, sum, temp;
1431 double _sin, _cos, _tan, _cot;
1436 for (j = 0; j < n; j++) {
1437 for (i = j; i < n; i++)
1438 r[j * ldr + i] = r[i * ldr + j];
1439 x[j] = r[j * ldr + j];
1448 for (j = 0; j < n; j++) {
1453 if (diag[ipvt[j]] == 0.)
1455 for (k = j; k < n; k++)
1457 sdiag[j] = diag[ipvt[j]];
1464 for (k = j; k < n; k++) {
1472 if (fabs(r[kk]) < fabs(sdiag[k])) {
1473 _cot = r[kk] / sdiag[k];
1474 _sin = 1 / sqrt(1 + SQR(_cot));
1477 _tan = sdiag[k] / r[kk];
1478 _cos = 1 / sqrt(1 + SQR(_tan));
1485 r[kk] = _cos * r[kk] + _sin * sdiag[k];
1486 temp = _cos * wa[k] + _sin * qtbpj;
1487 qtbpj = -_sin * wa[k] + _cos * qtbpj;
1492 for (i = k + 1; i < n; i++) {
1493 temp = _cos * r[k * ldr + i] + _sin * sdiag[i];
1494 sdiag[i] = -_sin * r[k * ldr + i] + _cos * sdiag[i];
1495 r[k * ldr + i] = temp;
1503 sdiag[j] = r[j * ldr + j];
1504 r[j * ldr + j] = x[j];
1511 for (j = 0; j < n; j++) {
1512 if (sdiag[j] == 0. && nsing == n)
1518 for (j = nsing - 1; j >= 0; j--) {
1520 for (i = j + 1; i < nsing; i++)
1521 sum += r[j * ldr + i] * wa[i];
1522 wa[j] = (wa[j] - sum) / sdiag[j];
1527 for (j = 0; j < n; j++)
1549 lm_enorm(
int n,
double *x) {
1551 double agiant, s1, s2, s3, xabs, x1max, x3max, temp;
1558 agiant = LM_SQRT_GIANT / ((double) n);
1561 for (i = 0; i < n; i++) {
1563 if (xabs > LM_SQRT_DWARF && xabs < agiant) {
1569 if (xabs > LM_SQRT_DWARF) {
1572 temp = x1max / xabs;
1573 s1 = 1 + s1 * SQR(temp);
1576 temp = xabs / x1max;
1583 temp = x3max / xabs;
1584 s3 = 1 + s3 * SQR(temp);
1588 temp = xabs / x3max;
1597 return x1max * sqrt(s1 + (s2 / x1max) / x1max);
1600 return sqrt(s2 * (1 + (x3max / s2) * (x3max * s3)));
1602 return sqrt(x3max * ((s2 / x3max) + (x3max * s3)));
1605 return x3max * sqrt(s3);
cpl_error_code muse_cpl_optimize_lvmq(void *aData, cpl_array *aPar, int aSize, muse_cpl_evaluate_func *aFunction, muse_cpl_optimize_control_t *aCtrl)
Minimize a function with the Levenberg-Marquardt algorithm.
int debug
Flag to switch on debugging messages. Default value: CPL_FALSE.
int maxcall
Maximum number of iterations. Default value (when set to -1): 100.
double xtol
Relative error between last two approximations. Default value (when set to -1): 30 * DBL_EPSILON...
double ftol
Relative error desired in the sum of squares. Default value (when set to -1): 30 * DBL_EPSILON...
double gtol
Orthogonality desired between fvec and its derivs. Default value (when set to -1): 30 * DBL_EPSILON...
Optimization control parameters.
cpl_error_code( muse_cpl_evaluate_func)(void *aData, cpl_array *aPar, cpl_array *aRetval)
User provided function to evaluate in muse_cpl_optimize_lvmq().
static void muse_cpl_optimize_print(const char *func, int n_par, double *par, int m_dat, double *fvec, void *data, int iflag, int iter, int nfev)
Default printout method adopted to CPL.