diff --git a/src/api/options.c b/src/api/options.c index c917977c..703e11ba 100644 --- a/src/api/options.c +++ b/src/api/options.c @@ -111,12 +111,8 @@ nlopt_opt NLOPT_STDCALL nlopt_create(nlopt_algorithm algorithm, unsigned n) opt->ub = (double *) calloc(n, sizeof(double)); if (!opt->ub) goto oom; - opt->xtol_abs = (double *) calloc(n, sizeof(double)); - if (!opt->xtol_abs) - goto oom; nlopt_set_lower_bounds1(opt, -HUGE_VAL); nlopt_set_upper_bounds1(opt, +HUGE_VAL); - nlopt_set_xtol_abs1(opt, 0.0); } } @@ -156,9 +152,11 @@ nlopt_opt NLOPT_STDCALL nlopt_copy(const nlopt_opt opt) nopt->ub = (double *) malloc(sizeof(double) * (opt->n)); if (!opt->ub) goto oom; - nopt->xtol_abs = (double *) malloc(sizeof(double) * (opt->n)); - if (!opt->xtol_abs) - goto oom; + if (opt->xtol_abs) { + nopt->xtol_abs = (double *) malloc(sizeof(double) * (opt->n)); + if (!opt->xtol_abs) + goto oom; + } if (opt->x_weights) { nopt->x_weights = (double *) malloc(sizeof(double) * (opt->n)); if (!opt->x_weights) @@ -168,7 +166,9 @@ nlopt_opt NLOPT_STDCALL nlopt_copy(const nlopt_opt opt) memcpy(nopt->lb, opt->lb, sizeof(double) * (opt->n)); memcpy(nopt->ub, opt->ub, sizeof(double) * (opt->n)); - memcpy(nopt->xtol_abs, opt->xtol_abs, sizeof(double) * (opt->n)); + if (opt->xtol_abs) { + memcpy(nopt->xtol_abs, opt->xtol_abs, sizeof(double) * (opt->n)); + } } if (opt->m) { @@ -612,6 +612,10 @@ GETSET(ftol_rel, double, ftol_rel) GETSET(ftol_abs, double, ftol_abs) GETSET(xto { if (opt) { nlopt_unset_errmsg(opt); + if (!opt->xtol_abs && opt->n > 0) { + opt->xtol_abs = (double *) calloc(opt->n, sizeof(double)); + if (!opt->xtol_abs) return NLOPT_OUT_OF_MEMORY; + } memcpy(opt->xtol_abs, xtol_abs, opt->n * sizeof(double)); return NLOPT_SUCCESS; } @@ -623,6 +627,10 @@ nlopt_result NLOPT_STDCALL nlopt_set_xtol_abs1(nlopt_opt opt, double xtol_abs) if (opt) { unsigned i; nlopt_unset_errmsg(opt); + if (!opt->xtol_abs && opt->n > 0) { + opt->xtol_abs = (double *) calloc(opt->n, sizeof(double)); + if (!opt->xtol_abs) return NLOPT_OUT_OF_MEMORY; + } for (i = 0; i < opt->n; ++i) opt->xtol_abs[i] = xtol_abs; return NLOPT_SUCCESS; @@ -634,7 +642,13 @@ nlopt_result NLOPT_STDCALL nlopt_get_xtol_abs(const nlopt_opt opt, double *xtol_ { nlopt_unset_errmsg(opt); if (opt && (opt->n == 0 || xtol_abs)) { - memcpy(xtol_abs, opt->xtol_abs, opt->n * sizeof(double)); + if (opt->xtol_abs) { + memcpy(xtol_abs, opt->xtol_abs, sizeof(double) * (opt->n)); + } else { + unsigned i; + for (i = 0; i < opt->n; ++i) + xtol_abs[i] = 0; + } return NLOPT_SUCCESS; } return NLOPT_INVALID_ARGS; diff --git a/src/util/stop.c b/src/util/stop.c index aaeb69f6..c68d57df 100644 --- a/src/util/stop.c +++ b/src/util/stop.c @@ -100,6 +100,7 @@ int nlopt_stop_x(const nlopt_stopping * s, const double *x, const double *oldx) unsigned i; if (diff_norm(s->n, x, oldx, s->x_weights, NULL, NULL) <= s->xtol_rel * vector_norm(s->n, x, s->x_weights, NULL, NULL)) return 1; + if (!s->xtol_abs) return 0; for (i = 0; i < s->n; ++i) if (fabs(x[i] - oldx[i]) > s->xtol_abs[i]) return 0; @@ -111,6 +112,7 @@ int nlopt_stop_dx(const nlopt_stopping * s, const double *x, const double *dx) unsigned i; if (vector_norm(s->n, dx, s->x_weights, NULL, NULL) <= s->xtol_rel * vector_norm(s->n, x, s->x_weights, NULL, NULL)) return 1; + if (!s->xtol_abs) return 0; for (i = 0; i < s->n; ++i) if (fabs(dx[i]) > s->xtol_abs[i]) return 0; @@ -124,6 +126,7 @@ int nlopt_stop_xs(const nlopt_stopping * s, const double *xs, const double *oldx unsigned i; if (diff_norm(s->n, xs, oldxs, s->x_weights, scale_min, scale_max) <= s->xtol_rel * vector_norm(s->n, xs, s->x_weights, scale_min, scale_max)) return 1; + if (!s->xtol_abs) return 0; for (i = 0; i < s->n; ++i) if (fabs(sc(xs[i], scale_min[i], scale_max[i]) - sc(oldxs[i], scale_min[i], scale_max[i])) > s->xtol_abs[i]) return 0;