From 65adc05708879943ac0ccf79762ecf3811d1462b Mon Sep 17 00:00:00 2001 From: "Steven G. Johnson" Date: Thu, 26 Jul 2018 11:31:41 -0400 Subject: [PATCH] untabify source files, make indenting more uniform with GNU indent -kr --no-tabs -l200 --- src/api/deprecated.c | 243 +++--- src/api/f77api.c | 64 +- src/api/f77funcs.h | 136 ++- src/api/f77funcs_.h | 206 +++-- src/api/general.c | 125 +-- src/api/nlopt-internal.h | 99 ++- src/api/nlopt.h | 303 +++---- src/api/optimize.c | 1481 ++++++++++++++++----------------- src/api/options.c | 1321 +++++++++++++++-------------- src/util/nlopt-getopt.c | 40 +- src/util/nlopt-getopt.h | 10 +- src/util/nlopt-util.h | 142 ++-- src/util/qsort_r.c | 121 ++- src/util/redblack.c | 667 ++++++++------- src/util/redblack.h | 74 +- src/util/redblack_test.c | 358 ++++---- src/util/rescale.c | 70 +- src/util/soboldata.h | 1698 +++++++++++++++++++------------------- src/util/sobolseq.c | 248 +++--- src/util/sobolseq_test.c | 14 +- src/util/stop.c | 129 ++- src/util/timer.c | 72 +- test/box.c | 217 +++-- test/lorentzfit.c | 143 ++-- test/testfuncs.c | 759 ++++++++--------- test/testfuncs.h | 34 +- test/testopt.c | 616 +++++++------- 27 files changed, 4671 insertions(+), 4719 deletions(-) diff --git a/src/api/deprecated.c b/src/api/deprecated.c index e6e4b40..b48c38a 100644 --- a/src/api/deprecated.c +++ b/src/api/deprecated.c @@ -26,26 +26,22 @@ nlopt_algorithm nlopt_local_search_alg_deriv = NLOPT_LD_MMA; nlopt_algorithm nlopt_local_search_alg_nonderiv = NLOPT_LN_COBYLA; -int nlopt_local_search_maxeval = -1; /* no maximum by default */ +int nlopt_local_search_maxeval = -1; /* no maximum by default */ void -NLOPT_STDCALL nlopt_get_local_search_algorithm(nlopt_algorithm *deriv, - nlopt_algorithm *nonderiv, - int *maxeval) +NLOPT_STDCALL nlopt_get_local_search_algorithm(nlopt_algorithm * deriv, nlopt_algorithm * nonderiv, int *maxeval) { - *deriv = nlopt_local_search_alg_deriv; - *nonderiv = nlopt_local_search_alg_nonderiv; - *maxeval = nlopt_local_search_maxeval; + *deriv = nlopt_local_search_alg_deriv; + *nonderiv = nlopt_local_search_alg_nonderiv; + *maxeval = nlopt_local_search_maxeval; } void -NLOPT_STDCALL nlopt_set_local_search_algorithm(nlopt_algorithm deriv, - nlopt_algorithm nonderiv, - int maxeval) +NLOPT_STDCALL nlopt_set_local_search_algorithm(nlopt_algorithm deriv, nlopt_algorithm nonderiv, int maxeval) { - nlopt_local_search_alg_deriv = deriv; - nlopt_local_search_alg_nonderiv = nonderiv; - nlopt_local_search_maxeval = maxeval; + nlopt_local_search_alg_deriv = deriv; + nlopt_local_search_alg_nonderiv = nonderiv; + nlopt_local_search_maxeval = maxeval; } /*************************************************************************/ @@ -53,119 +49,132 @@ NLOPT_STDCALL nlopt_set_local_search_algorithm(nlopt_algorithm deriv, int nlopt_stochastic_population = 0; int -NLOPT_STDCALL nlopt_get_stochastic_population(void) { - return nlopt_stochastic_population; } +NLOPT_STDCALL nlopt_get_stochastic_population(void) +{ + return nlopt_stochastic_population; +} + void -NLOPT_STDCALL nlopt_set_stochastic_population(int pop) { - nlopt_stochastic_population = pop <= 0 ? 0 : (unsigned) pop; } +NLOPT_STDCALL nlopt_set_stochastic_population(int pop) +{ + nlopt_stochastic_population = pop <= 0 ? 0 : (unsigned) pop; +} /*************************************************************************/ -nlopt_result -NLOPT_STDCALL nlopt_minimize_econstrained( - nlopt_algorithm algorithm, - int n, nlopt_func_old f, void *f_data, - int m, nlopt_func_old fc, void *fc_data_, ptrdiff_t fc_datum_size, - int p, nlopt_func_old h, void *h_data_, ptrdiff_t h_datum_size, - const double *lb, const double *ub, /* bounds */ - double *x, /* in: initial guess, out: minimizer */ - double *minf, /* out: minimum */ - double minf_max, double ftol_rel, double ftol_abs, - double xtol_rel, const double *xtol_abs, - double htol_rel, double htol_abs, - int maxeval, double maxtime) +nlopt_result NLOPT_STDCALL nlopt_minimize_econstrained(nlopt_algorithm algorithm, int n, nlopt_func_old f, void *f_data, int m, nlopt_func_old fc, void *fc_data_, ptrdiff_t fc_datum_size, int p, nlopt_func_old h, void *h_data_, ptrdiff_t h_datum_size, const double *lb, const double *ub, /* bounds */ + double *x, /* in: initial guess, out: minimizer */ + double *minf, /* out: minimum */ + double minf_max, double ftol_rel, double ftol_abs, + double xtol_rel, const double *xtol_abs, double htol_rel, double htol_abs, int maxeval, double maxtime) { - char *fc_data = (char *) fc_data_; - char *h_data = (char *) h_data_; - nlopt_opt opt; - nlopt_result ret; - int i; - - if (n < 0 || m < 0 || p < 0) return NLOPT_INVALID_ARGS; - - opt = nlopt_create(algorithm, (unsigned) n); - if (!opt) return NLOPT_INVALID_ARGS; - - ret = nlopt_set_min_objective(opt, (nlopt_func) f, f_data); - if (ret != NLOPT_SUCCESS) { nlopt_destroy(opt); return ret; } - - for (i = 0; i < m; ++i) { - ret = nlopt_add_inequality_constraint(opt, (nlopt_func) fc, - fc_data + i*fc_datum_size, - 0.0); - if (ret != NLOPT_SUCCESS) { nlopt_destroy(opt); return ret; } - } - - (void) htol_rel; /* unused */ - for (i = 0; i < p; ++i) { - ret = nlopt_add_equality_constraint(opt, (nlopt_func) h, - h_data + i*h_datum_size, - htol_abs); - if (ret != NLOPT_SUCCESS) { nlopt_destroy(opt); return ret; } - } - - ret = nlopt_set_lower_bounds(opt, lb); - if (ret != NLOPT_SUCCESS) { nlopt_destroy(opt); return ret; } - ret = nlopt_set_upper_bounds(opt, ub); - if (ret != NLOPT_SUCCESS) { nlopt_destroy(opt); return ret; } - - ret = nlopt_set_stopval(opt, minf_max); - if (ret != NLOPT_SUCCESS) { nlopt_destroy(opt); return ret; } - - ret = nlopt_set_ftol_rel(opt, ftol_rel); - if (ret != NLOPT_SUCCESS) { nlopt_destroy(opt); return ret; } - ret = nlopt_set_ftol_abs(opt, ftol_abs); - if (ret != NLOPT_SUCCESS) { nlopt_destroy(opt); return ret; } - - ret = nlopt_set_xtol_rel(opt, xtol_rel); - if (ret != NLOPT_SUCCESS) { nlopt_destroy(opt); return ret; } - if (xtol_abs) ret = nlopt_set_xtol_abs(opt, xtol_abs); - if (ret != NLOPT_SUCCESS) { nlopt_destroy(opt); return ret; } - - ret = nlopt_set_maxeval(opt, maxeval); - if (ret != NLOPT_SUCCESS) { nlopt_destroy(opt); return ret; } - - ret = nlopt_set_maxtime(opt, maxtime); - if (ret != NLOPT_SUCCESS) { nlopt_destroy(opt); return ret; } - - ret = nlopt_optimize(opt, x, minf); - - nlopt_destroy(opt); - return ret; + char *fc_data = (char *) fc_data_; + char *h_data = (char *) h_data_; + nlopt_opt opt; + nlopt_result ret; + int i; + + if (n < 0 || m < 0 || p < 0) + return NLOPT_INVALID_ARGS; + + opt = nlopt_create(algorithm, (unsigned) n); + if (!opt) + return NLOPT_INVALID_ARGS; + + ret = nlopt_set_min_objective(opt, (nlopt_func) f, f_data); + if (ret != NLOPT_SUCCESS) { + nlopt_destroy(opt); + return ret; + } + + for (i = 0; i < m; ++i) { + ret = nlopt_add_inequality_constraint(opt, (nlopt_func) fc, fc_data + i * fc_datum_size, 0.0); + if (ret != NLOPT_SUCCESS) { + nlopt_destroy(opt); + return ret; + } + } + + (void) htol_rel; /* unused */ + for (i = 0; i < p; ++i) { + ret = nlopt_add_equality_constraint(opt, (nlopt_func) h, h_data + i * h_datum_size, htol_abs); + if (ret != NLOPT_SUCCESS) { + nlopt_destroy(opt); + return ret; + } + } + + ret = nlopt_set_lower_bounds(opt, lb); + if (ret != NLOPT_SUCCESS) { + nlopt_destroy(opt); + return ret; + } + ret = nlopt_set_upper_bounds(opt, ub); + if (ret != NLOPT_SUCCESS) { + nlopt_destroy(opt); + return ret; + } + + ret = nlopt_set_stopval(opt, minf_max); + if (ret != NLOPT_SUCCESS) { + nlopt_destroy(opt); + return ret; + } + + ret = nlopt_set_ftol_rel(opt, ftol_rel); + if (ret != NLOPT_SUCCESS) { + nlopt_destroy(opt); + return ret; + } + ret = nlopt_set_ftol_abs(opt, ftol_abs); + if (ret != NLOPT_SUCCESS) { + nlopt_destroy(opt); + return ret; + } + + ret = nlopt_set_xtol_rel(opt, xtol_rel); + if (ret != NLOPT_SUCCESS) { + nlopt_destroy(opt); + return ret; + } + if (xtol_abs) + ret = nlopt_set_xtol_abs(opt, xtol_abs); + if (ret != NLOPT_SUCCESS) { + nlopt_destroy(opt); + return ret; + } + + ret = nlopt_set_maxeval(opt, maxeval); + if (ret != NLOPT_SUCCESS) { + nlopt_destroy(opt); + return ret; + } + + ret = nlopt_set_maxtime(opt, maxtime); + if (ret != NLOPT_SUCCESS) { + nlopt_destroy(opt); + return ret; + } + + ret = nlopt_optimize(opt, x, minf); + + nlopt_destroy(opt); + return ret; } -nlopt_result -NLOPT_STDCALL nlopt_minimize_constrained( - nlopt_algorithm algorithm, - int n, nlopt_func_old f, void *f_data, - int m, nlopt_func_old fc, void *fc_data, ptrdiff_t fc_datum_size, - const double *lb, const double *ub, /* bounds */ - double *x, /* in: initial guess, out: minimizer */ - double *minf, /* out: minimum */ - double minf_max, double ftol_rel, double ftol_abs, - double xtol_rel, const double *xtol_abs, - int maxeval, double maxtime) +nlopt_result NLOPT_STDCALL nlopt_minimize_constrained(nlopt_algorithm algorithm, int n, nlopt_func_old f, void *f_data, int m, nlopt_func_old fc, void *fc_data, ptrdiff_t fc_datum_size, const double *lb, const double *ub, /* bounds */ + double *x, /* in: initial guess, out: minimizer */ + double *minf, /* out: minimum */ + double minf_max, double ftol_rel, double ftol_abs, double xtol_rel, const double *xtol_abs, int maxeval, double maxtime) { - return nlopt_minimize_econstrained( - algorithm, n, f, f_data, - m, fc, fc_data, fc_datum_size, 0, NULL, NULL, 0, - lb, ub, x, minf, minf_max, ftol_rel, ftol_abs, - xtol_rel, xtol_abs, ftol_rel, ftol_abs, maxeval, maxtime); + return nlopt_minimize_econstrained(algorithm, n, f, f_data, + m, fc, fc_data, fc_datum_size, 0, NULL, NULL, 0, lb, ub, x, minf, minf_max, ftol_rel, ftol_abs, xtol_rel, xtol_abs, ftol_rel, ftol_abs, maxeval, maxtime); } -nlopt_result -NLOPT_STDCALL nlopt_minimize( - nlopt_algorithm algorithm, - int n, nlopt_func_old f, void *f_data, - const double *lb, const double *ub, /* bounds */ - double *x, /* in: initial guess, out: minimizer */ - double *minf, /* out: minimum */ - double minf_max, double ftol_rel, double ftol_abs, - double xtol_rel, const double *xtol_abs, - int maxeval, double maxtime) +nlopt_result NLOPT_STDCALL nlopt_minimize(nlopt_algorithm algorithm, int n, nlopt_func_old f, void *f_data, const double *lb, const double *ub, /* bounds */ + double *x, /* in: initial guess, out: minimizer */ + double *minf, /* out: minimum */ + double minf_max, double ftol_rel, double ftol_abs, double xtol_rel, const double *xtol_abs, int maxeval, double maxtime) { - return nlopt_minimize_constrained( - algorithm, n, f, f_data, 0, NULL, NULL, 0, - lb, ub, x, minf, minf_max, ftol_rel, ftol_abs, - xtol_rel, xtol_abs, maxeval, maxtime); + return nlopt_minimize_constrained(algorithm, n, f, f_data, 0, NULL, NULL, 0, lb, ub, x, minf, minf_max, ftol_rel, ftol_abs, xtol_rel, xtol_abs, maxeval, maxtime); } diff --git a/src/api/f77api.c b/src/api/f77api.c index e753c86..99b3d00 100644 --- a/src/api/f77api.c +++ b/src/api/f77api.c @@ -28,54 +28,56 @@ /*-----------------------------------------------------------------------*/ /* wrappers around f77 procedures */ -typedef void (*nlopt_f77_func)(double *val, const int *n, const double *x, - double *gradient, const int *need_gradient, - void *func_data); +typedef void (*nlopt_f77_func) (double *val, const int *n, const double *x, double *gradient, const int *need_gradient, void *func_data); -typedef void (*nlopt_f77_mfunc)(const int *m, - double *val, const int *n, const double *x, - double *gradient, const int *need_gradient, - void *func_data); +typedef void (*nlopt_f77_mfunc) (const int *m, double *val, const int *n, const double *x, double *gradient, const int *need_gradient, void *func_data); typedef struct { - nlopt_f77_func f; - nlopt_f77_mfunc mf; - void *f_data; + nlopt_f77_func f; + nlopt_f77_mfunc mf; + void *f_data; } f77_func_data; -static void *free_f77_func_data(void *p) { free(p); return NULL; } -static void *dup_f77_func_data(void *p) { - void *pnew = (void*) malloc(sizeof(f77_func_data)); - if (pnew) memcpy(pnew, p, sizeof(f77_func_data)); - return pnew; +static void *free_f77_func_data(void *p) +{ + free(p); + return NULL; +} + +static void *dup_f77_func_data(void *p) +{ + void *pnew = (void *) malloc(sizeof(f77_func_data)); + if (pnew) + memcpy(pnew, p, sizeof(f77_func_data)); + return pnew; } static double f77_func_wrap_old(int n, const double *x, double *grad, void *data) { - f77_func_data *d = (f77_func_data *) data; - double val; - int need_gradient = grad != 0; - d->f(&val, &n, x, grad, &need_gradient, d->f_data); - return val; + f77_func_data *d = (f77_func_data *) data; + double val; + int need_gradient = grad != 0; + d->f(&val, &n, x, grad, &need_gradient, d->f_data); + return val; } static double f77_func_wrap(unsigned n, const double *x, double *grad, void *data) { - f77_func_data *d = (f77_func_data *) data; - int ni = (int) n; - double val; - int need_gradient = grad != 0; - d->f(&val, &ni, x, grad, &need_gradient, d->f_data); - return val; + f77_func_data *d = (f77_func_data *) data; + int ni = (int) n; + double val; + int need_gradient = grad != 0; + d->f(&val, &ni, x, grad, &need_gradient, d->f_data); + return val; } static void f77_mfunc_wrap(unsigned m, double *result, unsigned n, const double *x, double *grad, void *data) { - f77_func_data *d = (f77_func_data *) data; - int mi = (int) m; - int ni = (int) n; - int need_gradient = grad != 0; - d->mf(&mi, result, &ni, x, grad, &need_gradient, d->f_data); + f77_func_data *d = (f77_func_data *) data; + int mi = (int) m; + int ni = (int) n; + int need_gradient = grad != 0; + d->mf(&mi, result, &ni, x, grad, &need_gradient, d->f_data); } /*-----------------------------------------------------------------------*/ diff --git a/src/api/f77funcs.h b/src/api/f77funcs.h index 332b16b..90e79c5 100644 --- a/src/api/f77funcs.h +++ b/src/api/f77funcs.h @@ -29,88 +29,86 @@ of the subroutine. */ /* nlopt_minimize_constrained */ -void F77(nloptc,NLOPTC)(int *info, - const int *algorithm, - const int *n, nlopt_f77_func f, void *f_data, - const int *m, nlopt_f77_func fc, - char *fc_data, char *fc_second_datum, - const double *lb, const double *ub, - double *x, double *minf, - const double *minf_max, - const double *ftol_rel, const double *ftol_abs, - const double *xtol_rel, const double *xtol_abs, - const int *have_xtol_abs, - const int *maxeval, const double *maxtime) -{ - f77_func_data d, *dc; - int i; +void F77(nloptc, NLOPTC) (int *info, + const int *algorithm, + const int *n, nlopt_f77_func f, void *f_data, + const int *m, nlopt_f77_func fc, + char *fc_data, char *fc_second_datum, + const double *lb, const double *ub, + double *x, double *minf, + const double *minf_max, + const double *ftol_rel, const double *ftol_abs, const double *xtol_rel, const double *xtol_abs, const int *have_xtol_abs, const int *maxeval, const double *maxtime) { + f77_func_data d, *dc; + int i; - d.f = f; d.f_data = f_data; - if (*m < 0) { *info = NLOPT_INVALID_ARGS; return; } - dc = (f77_func_data *) malloc(sizeof(f77_func_data) * *m); - if (*m > 0 && !dc) { *info = NLOPT_OUT_OF_MEMORY; return; } - for (i = 0; i < *m; ++i) { - dc[i].f = fc; - dc[i].f_data = fc_data + i * (fc_second_datum - fc_data); - } + d.f = f; + d.f_data = f_data; + if (*m < 0) { + *info = NLOPT_INVALID_ARGS; + return; + } + dc = (f77_func_data *) malloc(sizeof(f77_func_data) * *m); + if (*m > 0 && !dc) { + *info = NLOPT_OUT_OF_MEMORY; + return; + } + for (i = 0; i < *m; ++i) { + dc[i].f = fc; + dc[i].f_data = fc_data + i * (fc_second_datum - fc_data); + } - *info = nlopt_minimize_constrained((nlopt_algorithm) *algorithm, - *n, f77_func_wrap_old, &d, - *m, f77_func_wrap_old, - dc, sizeof(f77_func_data), - lb, ub, x, minf, - *minf_max, *ftol_rel, *ftol_abs, - *xtol_rel, - *have_xtol_abs ? xtol_abs : 0, - *maxeval, *maxtime); + *info = nlopt_minimize_constrained((nlopt_algorithm) * algorithm, + *n, f77_func_wrap_old, &d, + *m, f77_func_wrap_old, + dc, sizeof(f77_func_data), lb, ub, x, minf, *minf_max, *ftol_rel, *ftol_abs, *xtol_rel, *have_xtol_abs ? xtol_abs : 0, *maxeval, *maxtime); - if (dc) free(dc); + if (dc) + free(dc); } /* nlopt_minimize */ -void F77(nloptm,NLOPTM)(int *info, - const int *algorithm, - const int *n, nlopt_f77_func f, void *f_data, - const double *lb, const double *ub, - double *x, double *minf, - const double *minf_max, - const double *ftol_rel, const double *ftol_abs, - const double *xtol_rel, const double *xtol_abs, - const int *have_xtol_abs, - const int *maxeval, const double *maxtime) -{ - int m = 0; - F77CALL(nloptc,NLOPTC)(info, algorithm, n, f, f_data, &m, 0, 0, 0, - lb, ub, x, minf, minf_max, ftol_rel, ftol_abs, - xtol_rel, xtol_abs, have_xtol_abs, maxeval, maxtime); +void F77(nloptm, NLOPTM) (int *info, + const int *algorithm, + const int *n, nlopt_f77_func f, void *f_data, + const double *lb, const double *ub, + double *x, double *minf, + const double *minf_max, + const double *ftol_rel, const double *ftol_abs, const double *xtol_rel, const double *xtol_abs, const int *have_xtol_abs, const int *maxeval, const double *maxtime) { + int m = 0; + F77CALL(nloptc, NLOPTC) (info, algorithm, n, f, f_data, &m, 0, 0, 0, lb, ub, x, minf, minf_max, ftol_rel, ftol_abs, xtol_rel, xtol_abs, have_xtol_abs, maxeval, maxtime); } -void F77(nlosr,NLOSR)(const int *seed) { nlopt_srand((unsigned long) *seed); } -void F77(nlosrt,NLOSRT)(void) { nlopt_srand_time(); } -void F77(nloptv,NLOPTV)(int *major, int *minor, int *bugfix) { - nlopt_version(major, minor, bugfix); +void F77(nlosr, NLOSR) (const int *seed) { + nlopt_srand((unsigned long) *seed); } -void F77(nlogls,NLOGLS)(int *ideriv, int *inonderiv, int *maxeval) -{ - nlopt_algorithm deriv, nonderiv; - nlopt_get_local_search_algorithm(&deriv, &nonderiv, maxeval); - *ideriv = deriv; - *inonderiv = nonderiv; + +void F77(nlosrt, NLOSRT) (void) { + nlopt_srand_time(); +} + +void F77(nloptv, NLOPTV) (int *major, int *minor, int *bugfix) { + nlopt_version(major, minor, bugfix); } -void F77(nlosls,NLOSLS)(int *ideriv, int *inonderiv, int *maxeval) -{ - nlopt_algorithm deriv = (nlopt_algorithm) *ideriv; - nlopt_algorithm nonderiv = (nlopt_algorithm) *inonderiv; - nlopt_set_local_search_algorithm(deriv, nonderiv, *maxeval); + +void F77(nlogls, NLOGLS) (int *ideriv, int *inonderiv, int *maxeval) { + nlopt_algorithm deriv, nonderiv; + nlopt_get_local_search_algorithm(&deriv, &nonderiv, maxeval); + *ideriv = deriv; + *inonderiv = nonderiv; } -void F77(nlogsp,NLOGSP)(int *pop) -{ - *pop = nlopt_get_stochastic_population(); +void F77(nlosls, NLOSLS) (int *ideriv, int *inonderiv, int *maxeval) { + nlopt_algorithm deriv = (nlopt_algorithm) * ideriv; + nlopt_algorithm nonderiv = (nlopt_algorithm) * inonderiv; + nlopt_set_local_search_algorithm(deriv, nonderiv, *maxeval); } -void F77(nlossp,NLOSSP)(const int *pop) -{ - nlopt_set_stochastic_population(*pop); + +void F77(nlogsp, NLOGSP) (int *pop) { + *pop = nlopt_get_stochastic_population(); +} + +void F77(nlossp, NLOSSP) (const int *pop) { + nlopt_set_stochastic_population(*pop); } #define F77_(name,NAME) F77(name,NAME) diff --git a/src/api/f77funcs_.h b/src/api/f77funcs_.h index 1f10ba2..4bac153 100644 --- a/src/api/f77funcs_.h +++ b/src/api/f77funcs_.h @@ -31,139 +31,137 @@ The return value of a function is converted to the first argument of a subroutine. */ -void F77_(nlo_create,NLO_CREATE)(nlopt_opt *opt, int *alg, int *n) -{ - if (*n < 0) *opt = NULL; - else { - *opt = nlopt_create((nlopt_algorithm) *alg, (unsigned) *n); - nlopt_set_munge(*opt, free_f77_func_data, dup_f77_func_data); - } +void F77_(nlo_create, NLO_CREATE) (nlopt_opt * opt, int *alg, int *n) { + if (*n < 0) + *opt = NULL; + else { + *opt = nlopt_create((nlopt_algorithm) * alg, (unsigned) *n); + nlopt_set_munge(*opt, free_f77_func_data, dup_f77_func_data); + } } -void F77_(nlo_copy,NLO_COPY)(nlopt_opt *nopt, nlopt_opt *opt) -{ - *nopt = nlopt_copy(*opt); +void F77_(nlo_copy, NLO_COPY) (nlopt_opt * nopt, nlopt_opt * opt) { + *nopt = nlopt_copy(*opt); } -void F77_(nlo_destroy,NLO_DESTROY)(nlopt_opt *opt) -{ - nlopt_destroy(*opt); +void F77_(nlo_destroy, NLO_DESTROY) (nlopt_opt * opt) { + nlopt_destroy(*opt); } -void F77_(nlo_optimize,NLO_OPTIMIZE)(int *ret, - nlopt_opt *opt, double *x, double *optf) -{ - *ret = (int) nlopt_optimize(*opt, x, optf); +void F77_(nlo_optimize, NLO_OPTIMIZE) (int *ret, nlopt_opt * opt, double *x, double *optf) { + *ret = (int) nlopt_optimize(*opt, x, optf); } -void F77_(nlo_set_min_objective,NLO_SET_MIN_OBJECTIVE)( - int *ret, nlopt_opt *opt, nlopt_f77_func f, void *f_data) -{ - f77_func_data *d = (f77_func_data*) malloc(sizeof(f77_func_data)); - if (!d) { *ret = (int) NLOPT_OUT_OF_MEMORY; return; } - d->f = f; - d->f_data = f_data; - *ret = (int) nlopt_set_min_objective(*opt, f77_func_wrap, d); +void F77_(nlo_set_min_objective, NLO_SET_MIN_OBJECTIVE) (int *ret, nlopt_opt * opt, nlopt_f77_func f, void *f_data) { + f77_func_data *d = (f77_func_data *) malloc(sizeof(f77_func_data)); + if (!d) { + *ret = (int) NLOPT_OUT_OF_MEMORY; + return; + } + d->f = f; + d->f_data = f_data; + *ret = (int) nlopt_set_min_objective(*opt, f77_func_wrap, d); } -void F77_(nlo_set_max_objective,NLO_SET_MAX_OBJECTIVE)( - int *ret, nlopt_opt *opt, nlopt_f77_func f, void *f_data) -{ - f77_func_data *d = (f77_func_data*) malloc(sizeof(f77_func_data)); - if (!d) { *ret = (int) NLOPT_OUT_OF_MEMORY; return; } - d->f = f; - d->f_data = f_data; - *ret = (int) nlopt_set_max_objective(*opt, f77_func_wrap, d); +void F77_(nlo_set_max_objective, NLO_SET_MAX_OBJECTIVE) (int *ret, nlopt_opt * opt, nlopt_f77_func f, void *f_data) { + f77_func_data *d = (f77_func_data *) malloc(sizeof(f77_func_data)); + if (!d) { + *ret = (int) NLOPT_OUT_OF_MEMORY; + return; + } + d->f = f; + d->f_data = f_data; + *ret = (int) nlopt_set_max_objective(*opt, f77_func_wrap, d); } -F77_GET(algorithm, ALGORITHM, int) -F77_GET(dimension, DIMENSION, int) - -F77_GETSETA(lower_bounds, LOWER_BOUNDS, double) -F77_GETSETA(upper_bounds, UPPER_BOUNDS, double) +F77_GET(algorithm, ALGORITHM, int) F77_GET(dimension, DIMENSION, int) + F77_GETSETA(lower_bounds, LOWER_BOUNDS, double) F77_GETSETA(upper_bounds, UPPER_BOUNDS, double) -void F77_(nlo_remove_inequality_constraints,NLO_REMOVE_INEQUALITY_CONSTRAINTS)( - int *ret, nlopt_opt *opt) { - *ret = (int) nlopt_remove_inequality_constraints(*opt); +void F77_(nlo_remove_inequality_constraints, NLO_REMOVE_INEQUALITY_CONSTRAINTS) (int *ret, nlopt_opt * opt) +{ + *ret = (int) nlopt_remove_inequality_constraints(*opt); } -void F77_(nlo_add_inequality_constraint,NLO_ADD_INEQUALITY_CONSTRAINT)( - int *ret, nlopt_opt *opt, nlopt_f77_func fc, void *fc_data, double *tol) -{ - f77_func_data *d = (f77_func_data*) malloc(sizeof(f77_func_data)); - if (!d) { *ret = (int) NLOPT_OUT_OF_MEMORY; return; } - d->f = fc; - d->f_data = fc_data; - *ret = (int) nlopt_add_inequality_constraint(*opt, f77_func_wrap,d, *tol); +void F77_(nlo_add_inequality_constraint, NLO_ADD_INEQUALITY_CONSTRAINT) (int *ret, nlopt_opt * opt, nlopt_f77_func fc, void *fc_data, double *tol) { + f77_func_data *d = (f77_func_data *) malloc(sizeof(f77_func_data)); + if (!d) { + *ret = (int) NLOPT_OUT_OF_MEMORY; + return; + } + d->f = fc; + d->f_data = fc_data; + *ret = (int) nlopt_add_inequality_constraint(*opt, f77_func_wrap, d, *tol); } -void F77_(nlo_add_inequality_mconstraint,NLO_ADD_INEQUALITY_MCONSTRAINT)( - int *ret, nlopt_opt *opt, int *m, - nlopt_f77_mfunc mfc, void *mfc_data, double *tol) -{ - f77_func_data *d; - if (*m < 0) { *ret = (int) NLOPT_INVALID_ARGS; return; } - if (*m == 0) { *ret = (int) NLOPT_SUCCESS; return; } - d = (f77_func_data*) malloc(sizeof(f77_func_data)); - if (!d) { *ret = (int) NLOPT_OUT_OF_MEMORY; return; } - d->mf = mfc; - d->f_data = mfc_data; - *ret = (int) nlopt_add_inequality_mconstraint(*opt, (unsigned) *m, - f77_mfunc_wrap, d, tol); +void F77_(nlo_add_inequality_mconstraint, NLO_ADD_INEQUALITY_MCONSTRAINT) (int *ret, nlopt_opt * opt, int *m, nlopt_f77_mfunc mfc, void *mfc_data, double *tol) { + f77_func_data *d; + if (*m < 0) { + *ret = (int) NLOPT_INVALID_ARGS; + return; + } + if (*m == 0) { + *ret = (int) NLOPT_SUCCESS; + return; + } + d = (f77_func_data *) malloc(sizeof(f77_func_data)); + if (!d) { + *ret = (int) NLOPT_OUT_OF_MEMORY; + return; + } + d->mf = mfc; + d->f_data = mfc_data; + *ret = (int) nlopt_add_inequality_mconstraint(*opt, (unsigned) *m, f77_mfunc_wrap, d, tol); } -void F77_(nlo_remove_equality_constraints,NLO_REMOVE_EQUALITY_CONSTRAINTS)( - int *ret, nlopt_opt *opt) { - *ret = (int) nlopt_remove_equality_constraints(*opt); +void F77_(nlo_remove_equality_constraints, NLO_REMOVE_EQUALITY_CONSTRAINTS) (int *ret, nlopt_opt * opt) { + *ret = (int) nlopt_remove_equality_constraints(*opt); } -void F77_(nlo_add_equality_constraint,NLO_ADD_EQUALITY_CONSTRAINT)( - int *ret, nlopt_opt *opt, nlopt_f77_func fc, void *fc_data, double *tol) -{ - f77_func_data *d = (f77_func_data*) malloc(sizeof(f77_func_data)); - if (!d) { *ret = (int) NLOPT_OUT_OF_MEMORY; return; } - d->f = fc; - d->f_data = fc_data; - *ret = (int) nlopt_add_equality_constraint(*opt, f77_func_wrap,d, *tol); +void F77_(nlo_add_equality_constraint, NLO_ADD_EQUALITY_CONSTRAINT) (int *ret, nlopt_opt * opt, nlopt_f77_func fc, void *fc_data, double *tol) { + f77_func_data *d = (f77_func_data *) malloc(sizeof(f77_func_data)); + if (!d) { + *ret = (int) NLOPT_OUT_OF_MEMORY; + return; + } + d->f = fc; + d->f_data = fc_data; + *ret = (int) nlopt_add_equality_constraint(*opt, f77_func_wrap, d, *tol); } -void F77_(nlo_add_equality_mconstraint,NLO_ADD_EQUALITY_MCONSTRAINT)( - int *ret, nlopt_opt *opt, int *m, - nlopt_f77_mfunc mfc, void *mfc_data, double *tol) -{ - f77_func_data *d; - if (*m < 0) { *ret = (int) NLOPT_INVALID_ARGS; return; } - if (*m == 0) { *ret = (int) NLOPT_SUCCESS; return; } - d = (f77_func_data*) malloc(sizeof(f77_func_data)); - if (!d) { *ret = (int) NLOPT_OUT_OF_MEMORY; return; } - d->mf = mfc; - d->f_data = mfc_data; - *ret = (int) nlopt_add_equality_mconstraint(*opt, (unsigned) *m, - f77_mfunc_wrap, d, tol); +void F77_(nlo_add_equality_mconstraint, NLO_ADD_EQUALITY_MCONSTRAINT) (int *ret, nlopt_opt * opt, int *m, nlopt_f77_mfunc mfc, void *mfc_data, double *tol) { + f77_func_data *d; + if (*m < 0) { + *ret = (int) NLOPT_INVALID_ARGS; + return; + } + if (*m == 0) { + *ret = (int) NLOPT_SUCCESS; + return; + } + d = (f77_func_data *) malloc(sizeof(f77_func_data)); + if (!d) { + *ret = (int) NLOPT_OUT_OF_MEMORY; + return; + } + d->mf = mfc; + d->f_data = mfc_data; + *ret = (int) nlopt_add_equality_mconstraint(*opt, (unsigned) *m, f77_mfunc_wrap, d, tol); } F77_GETSET(stopval, STOPVAL, double) F77_GETSET(ftol_rel, FTOL_REL, double) F77_GETSET(ftol_abs, FTOL_ABS, double) -F77_GETSET(xtol_rel, XTOL_REL, double) -F77_GETSETA(xtol_abs, XTOL_ABS, double) -F77_GETSET(maxeval, MAXEVAL, int) -F77_GET(numevals, NUMEVALS, int) -F77_GETSET(maxtime, MAXTIME, double) - -F77_GETSET(force_stop, FORCE_STOP, int) -void F77_(nlo_force_stop,NLO_FORCE_STOP)(int *ret, nlopt_opt *opt) { - *ret = (int) nlopt_force_stop(*opt); +F77_GETSET(xtol_rel, XTOL_REL, double) F77_GETSETA(xtol_abs, XTOL_ABS, double) F77_GETSET(maxeval, MAXEVAL, int) F77_GET(numevals, NUMEVALS, int) F77_GETSET(maxtime, MAXTIME, double) + F77_GETSET(force_stop, FORCE_STOP, int) +void F77_(nlo_force_stop, NLO_FORCE_STOP) (int *ret, nlopt_opt * opt) +{ + *ret = (int) nlopt_force_stop(*opt); } F77_SET(local_optimizer, LOCAL_OPTIMIZER, nlopt_opt) -F77_GETSET(population, POPULATION, unsigned) -F77_GETSET(vector_storage, vector_storage, unsigned) - -F77_SETA(default_initial_step, DEFAULT_INITIAL_STEP, double) -F77_SETA(initial_step, INITIAL_STEP, double) -F77_SET(initial_step1, INITIAL_STEP1, double) -void F77_(nlo_get_initial_step, NLO_GET_INITIAL_STEP)( - int *ret, nlopt_opt *opt, const double *x, double *dx) { - *ret = (int) nlopt_get_initial_step(*opt, x, dx); +F77_GETSET(population, POPULATION, unsigned) F77_GETSET(vector_storage, vector_storage, unsigned) + F77_SETA(default_initial_step, DEFAULT_INITIAL_STEP, double) F77_SETA(initial_step, INITIAL_STEP, double) F77_SET(initial_step1, INITIAL_STEP1, double) +void F77_(nlo_get_initial_step, NLO_GET_INITIAL_STEP) (int *ret, nlopt_opt * opt, const double *x, double *dx) +{ + *ret = (int) nlopt_get_initial_step(*opt, x, dx); } diff --git a/src/api/general.c b/src/api/general.c index 6e75074..b151eca 100644 --- a/src/api/general.c +++ b/src/api/general.c @@ -26,73 +26,74 @@ void NLOPT_STDCALL nlopt_version(int *major, int *minor, int *bugfix) { - *major = MAJOR_VERSION; - *minor = MINOR_VERSION; - *bugfix = BUGFIX_VERSION; + *major = MAJOR_VERSION; + *minor = MINOR_VERSION; + *bugfix = BUGFIX_VERSION; } /*************************************************************************/ static const char nlopt_algorithm_names[NLOPT_NUM_ALGORITHMS][256] = { - "DIRECT (global, no-derivative)", - "DIRECT-L (global, no-derivative)", - "Randomized DIRECT-L (global, no-derivative)", - "Unscaled DIRECT (global, no-derivative)", - "Unscaled DIRECT-L (global, no-derivative)", - "Unscaled Randomized DIRECT-L (global, no-derivative)", - "Original DIRECT version (global, no-derivative)", - "Original DIRECT-L version (global, no-derivative)", + "DIRECT (global, no-derivative)", + "DIRECT-L (global, no-derivative)", + "Randomized DIRECT-L (global, no-derivative)", + "Unscaled DIRECT (global, no-derivative)", + "Unscaled DIRECT-L (global, no-derivative)", + "Unscaled Randomized DIRECT-L (global, no-derivative)", + "Original DIRECT version (global, no-derivative)", + "Original DIRECT-L version (global, no-derivative)", #ifdef NLOPT_CXX - "StoGO (global, derivative-based)", - "StoGO with randomized search (global, derivative-based)", + "StoGO (global, derivative-based)", + "StoGO with randomized search (global, derivative-based)", #else - "StoGO (NOT COMPILED)", - "StoGO randomized (NOT COMPILED)", + "StoGO (NOT COMPILED)", + "StoGO randomized (NOT COMPILED)", #endif - "original L-BFGS code by Nocedal et al. (NOT COMPILED)", - "Limited-memory BFGS (L-BFGS) (local, derivative-based)", - "Principal-axis, praxis (local, no-derivative)", - "Limited-memory variable-metric, rank 1 (local, derivative-based)", - "Limited-memory variable-metric, rank 2 (local, derivative-based)", - "Truncated Newton (local, derivative-based)", - "Truncated Newton with restarting (local, derivative-based)", - "Preconditioned truncated Newton (local, derivative-based)", - "Preconditioned truncated Newton with restarting (local, derivative-based)", - "Controlled random search (CRS2) with local mutation (global, no-derivative)", - "Multi-level single-linkage (MLSL), random (global, no-derivative)", - "Multi-level single-linkage (MLSL), random (global, derivative)", - "Multi-level single-linkage (MLSL), quasi-random (global, no-derivative)", - "Multi-level single-linkage (MLSL), quasi-random (global, derivative)", - "Method of Moving Asymptotes (MMA) (local, derivative)", - "COBYLA (Constrained Optimization BY Linear Approximations) (local, no-derivative)", - "NEWUOA unconstrained optimization via quadratic models (local, no-derivative)", - "Bound-constrained optimization via NEWUOA-based quadratic models (local, no-derivative)", - "Nelder-Mead simplex algorithm (local, no-derivative)", - "Sbplx variant of Nelder-Mead (re-implementation of Rowan's Subplex) (local, no-derivative)", - "Augmented Lagrangian method (local, no-derivative)", - "Augmented Lagrangian method (local, derivative)", - "Augmented Lagrangian method for equality constraints (local, no-derivative)", - "Augmented Lagrangian method for equality constraints (local, derivative)", - "BOBYQA bound-constrained optimization via quadratic models (local, no-derivative)", - "ISRES evolutionary constrained optimization (global, no-derivative)", - "Augmented Lagrangian method (needs sub-algorithm)", - "Augmented Lagrangian method for equality constraints (needs sub-algorithm)", - "Multi-level single-linkage (MLSL), random (global, needs sub-algorithm)", - "Multi-level single-linkage (MLSL), quasi-random (global, needs sub-algorithm)", - "Sequential Quadratic Programming (SQP) (local, derivative)", - "CCSA (Conservative Convex Separable Approximations) with simple quadratic approximations (local, derivative)", - "ESCH evolutionary strategy", + "original L-BFGS code by Nocedal et al. (NOT COMPILED)", + "Limited-memory BFGS (L-BFGS) (local, derivative-based)", + "Principal-axis, praxis (local, no-derivative)", + "Limited-memory variable-metric, rank 1 (local, derivative-based)", + "Limited-memory variable-metric, rank 2 (local, derivative-based)", + "Truncated Newton (local, derivative-based)", + "Truncated Newton with restarting (local, derivative-based)", + "Preconditioned truncated Newton (local, derivative-based)", + "Preconditioned truncated Newton with restarting (local, derivative-based)", + "Controlled random search (CRS2) with local mutation (global, no-derivative)", + "Multi-level single-linkage (MLSL), random (global, no-derivative)", + "Multi-level single-linkage (MLSL), random (global, derivative)", + "Multi-level single-linkage (MLSL), quasi-random (global, no-derivative)", + "Multi-level single-linkage (MLSL), quasi-random (global, derivative)", + "Method of Moving Asymptotes (MMA) (local, derivative)", + "COBYLA (Constrained Optimization BY Linear Approximations) (local, no-derivative)", + "NEWUOA unconstrained optimization via quadratic models (local, no-derivative)", + "Bound-constrained optimization via NEWUOA-based quadratic models (local, no-derivative)", + "Nelder-Mead simplex algorithm (local, no-derivative)", + "Sbplx variant of Nelder-Mead (re-implementation of Rowan's Subplex) (local, no-derivative)", + "Augmented Lagrangian method (local, no-derivative)", + "Augmented Lagrangian method (local, derivative)", + "Augmented Lagrangian method for equality constraints (local, no-derivative)", + "Augmented Lagrangian method for equality constraints (local, derivative)", + "BOBYQA bound-constrained optimization via quadratic models (local, no-derivative)", + "ISRES evolutionary constrained optimization (global, no-derivative)", + "Augmented Lagrangian method (needs sub-algorithm)", + "Augmented Lagrangian method for equality constraints (needs sub-algorithm)", + "Multi-level single-linkage (MLSL), random (global, needs sub-algorithm)", + "Multi-level single-linkage (MLSL), quasi-random (global, needs sub-algorithm)", + "Sequential Quadratic Programming (SQP) (local, derivative)", + "CCSA (Conservative Convex Separable Approximations) with simple quadratic approximations (local, derivative)", + "ESCH evolutionary strategy", #ifdef NLOPT_CXX11 - "AGS (global, no-derivative)" + "AGS (global, no-derivative)" #else - "AGS (NOT COMPILED)" + "AGS (NOT COMPILED)" #endif }; -const char * NLOPT_STDCALL nlopt_algorithm_name(nlopt_algorithm a) +const char *NLOPT_STDCALL nlopt_algorithm_name(nlopt_algorithm a) { - if (((int) a) < 0 || a >= NLOPT_NUM_ALGORITHMS) return "UNKNOWN"; - return nlopt_algorithm_names[a]; + if (((int) a) < 0 || a >= NLOPT_NUM_ALGORITHMS) + return "UNKNOWN"; + return nlopt_algorithm_names[a]; } /*************************************************************************/ @@ -118,17 +119,21 @@ const char * NLOPT_STDCALL nlopt_algorithm_name(nlopt_algorithm a) /*************************************************************************/ static THREADLOCAL int nlopt_srand_called = 0; -void NLOPT_STDCALL nlopt_srand(unsigned long seed) { - nlopt_srand_called = 1; - nlopt_init_genrand(seed); +void NLOPT_STDCALL nlopt_srand(unsigned long seed) +{ + nlopt_srand_called = 1; + nlopt_init_genrand(seed); } -void NLOPT_STDCALL nlopt_srand_time(void) { - nlopt_srand(nlopt_time_seed() + (unsigned long)my_gettid() * 314159); +void NLOPT_STDCALL nlopt_srand_time(void) +{ + nlopt_srand(nlopt_time_seed() + (unsigned long) my_gettid() * 314159); } -void nlopt_srand_time_default(void) { - if (!nlopt_srand_called) nlopt_srand_time(); +void nlopt_srand_time_default(void) +{ + if (!nlopt_srand_called) + nlopt_srand_time(); } /*************************************************************************/ diff --git a/src/api/nlopt-internal.h b/src/api/nlopt-internal.h index b1aa318..bf6fecc 100644 --- a/src/api/nlopt-internal.h +++ b/src/api/nlopt-internal.h @@ -27,67 +27,67 @@ #include "nlopt-util.h" #ifdef __cplusplus -extern "C" -{ -#endif /* __cplusplus */ +extern "C" { +#endif /* __cplusplus */ /*********************************************************************/ -struct nlopt_opt_s { - nlopt_algorithm algorithm; /* the optimization algorithm (immutable) */ - unsigned n; /* the dimension of the problem (immutable) */ + struct nlopt_opt_s { + nlopt_algorithm algorithm; /* the optimization algorithm (immutable) */ + unsigned n; /* the dimension of the problem (immutable) */ - nlopt_func f; void *f_data; /* objective function to minimize */ - nlopt_precond pre; /* optional preconditioner for f (NULL if none) */ - int maximize; /* nonzero if we are maximizing, not minimizing */ + nlopt_func f; + void *f_data; /* objective function to minimize */ + nlopt_precond pre; /* optional preconditioner for f (NULL if none) */ + int maximize; /* nonzero if we are maximizing, not minimizing */ - double *lb, *ub; /* lower and upper bounds (length n) */ + double *lb, *ub; /* lower and upper bounds (length n) */ - unsigned m; /* number of inequality constraints */ - unsigned m_alloc; /* number of inequality constraints allocated */ - nlopt_constraint *fc; /* inequality constraints, length m_alloc */ + unsigned m; /* number of inequality constraints */ + unsigned m_alloc; /* number of inequality constraints allocated */ + nlopt_constraint *fc; /* inequality constraints, length m_alloc */ - unsigned p; /* number of equality constraints */ - unsigned p_alloc; /* number of inequality constraints allocated */ - nlopt_constraint *h; /* equality constraints, length p_alloc */ + unsigned p; /* number of equality constraints */ + unsigned p_alloc; /* number of inequality constraints allocated */ + nlopt_constraint *h; /* equality constraints, length p_alloc */ - nlopt_munge munge_on_destroy, munge_on_copy; /* hack for wrappers */ + nlopt_munge munge_on_destroy, munge_on_copy; /* hack for wrappers */ - /* stopping criteria */ - double stopval; /* stop when f reaches stopval or better */ - double ftol_rel, ftol_abs; /* relative/absolute f tolerances */ - double xtol_rel, *xtol_abs; /* rel/abs x tolerances */ - int maxeval; /* max # evaluations */ - int numevals; /* number of evaluations */ - double maxtime; /* max time (seconds) */ + /* stopping criteria */ + double stopval; /* stop when f reaches stopval or better */ + double ftol_rel, ftol_abs; /* relative/absolute f tolerances */ + double xtol_rel, *xtol_abs; /* rel/abs x tolerances */ + int maxeval; /* max # evaluations */ + int numevals; /* number of evaluations */ + double maxtime; /* max time (seconds) */ - int force_stop; /* if nonzero, force a halt the next time we - try to evaluate the objective during optimization */ - /* when local optimization is used, we need a force_stop in the - parent object to force a stop in child optimizations */ - struct nlopt_opt_s *force_stop_child; + int force_stop; /* if nonzero, force a halt the next time we + try to evaluate the objective during optimization */ + /* when local optimization is used, we need a force_stop in the + parent object to force a stop in child optimizations */ + struct nlopt_opt_s *force_stop_child; - /* algorithm-specific parameters */ - nlopt_opt local_opt; /* local optimizer */ - unsigned stochastic_population; /* population size for stochastic algs */ - double *dx; /* initial step sizes (length n) for nonderivative algs */ - unsigned vector_storage; /* max subspace dimension (0 for default) */ + /* algorithm-specific parameters */ + nlopt_opt local_opt; /* local optimizer */ + unsigned stochastic_population; /* population size for stochastic algs */ + double *dx; /* initial step sizes (length n) for nonderivative algs */ + unsigned vector_storage; /* max subspace dimension (0 for default) */ - void *work; /* algorithm-specific workspace during optimization */ + void *work; /* algorithm-specific workspace during optimization */ - char *errmsg; /* description of most recent error */ -}; + char *errmsg; /* description of most recent error */ + }; /*********************************************************************/ -extern void nlopt_srand_time_default(void); /* init the rand. seed only if unset */ + extern void nlopt_srand_time_default(void); /* init the rand. seed only if unset */ /*********************************************************************/ /* global defaults set by deprecated API: */ -extern nlopt_algorithm nlopt_local_search_alg_deriv; -extern nlopt_algorithm nlopt_local_search_alg_nonderiv; -extern int nlopt_local_search_maxeval; -extern unsigned nlopt_stochastic_population; + extern nlopt_algorithm nlopt_local_search_alg_deriv; + extern nlopt_algorithm nlopt_local_search_alg_nonderiv; + extern int nlopt_local_search_maxeval; + extern unsigned nlopt_stochastic_population; /*********************************************************************/ @@ -96,17 +96,16 @@ extern unsigned nlopt_stochastic_population; return err; \ } while (0) -extern const char *nlopt_set_errmsg(nlopt_opt opt, const char *format, ...) + extern const char *nlopt_set_errmsg(nlopt_opt opt, const char *format, ...) #ifdef __GNUC__ -__attribute__ ((format (printf, 2, 3))) + __attribute__ ((format(printf, 2, 3))) #endif -; -extern void nlopt_unset_errmsg(nlopt_opt opt); + ; + extern void nlopt_unset_errmsg(nlopt_opt opt); /*********************************************************************/ #ifdef __cplusplus -} /* extern "C" */ -#endif /* __cplusplus */ - -#endif /* NLOPT_INTERNAL_H */ +} /* extern "C" */ +#endif /* __cplusplus */ +#endif /* NLOPT_INTERNAL_H */ diff --git a/src/api/nlopt.h b/src/api/nlopt.h index 998db3c..4bda368 100644 --- a/src/api/nlopt.h +++ b/src/api/nlopt.h @@ -23,7 +23,7 @@ #ifndef NLOPT_H #define NLOPT_H -#include /* for ptrdiff_t and size_t */ +#include /* for ptrdiff_t and size_t */ /* Change 0 to 1 to use stdcall convention under Win32 */ #if 0 && (defined(_WIN32) || defined(__WIN32__)) @@ -54,122 +54,119 @@ #endif #ifdef __cplusplus -extern "C" -{ +extern "C" { #endif /* __cplusplus */ -typedef double (*nlopt_func)(unsigned n, const double *x, - double *gradient, /* NULL if not needed */ - void *func_data); +typedef double (*nlopt_func) (unsigned n, const double *x, + double *gradient, /* NULL if not needed */ + void *func_data); -typedef void (*nlopt_mfunc)(unsigned m, double *result, - unsigned n, const double *x, - double *gradient, /* NULL if not needed */ - void *func_data); +typedef void (*nlopt_mfunc) (unsigned m, double *result, unsigned n, const double *x, + double *gradient, /* NULL if not needed */ + void *func_data); /* A preconditioner, which preconditions v at x to return vpre. (The meaning of "preconditioning" is algorithm-dependent.) */ -typedef void (*nlopt_precond)(unsigned n, const double *x, const double *v, - double *vpre, void *data); +typedef void (*nlopt_precond) (unsigned n, const double *x, const double *v, double *vpre, void *data); typedef enum { - /* Naming conventions: + /* Naming conventions: - NLOPT_{G/L}{D/N}_* - = global/local derivative/no-derivative optimization, - respectively + NLOPT_{G/L}{D/N}_* + = global/local derivative/no-derivative optimization, + respectively - *_RAND algorithms involve some randomization. + *_RAND algorithms involve some randomization. - *_NOSCAL algorithms are *not* scaled to a unit hypercube - (i.e. they are sensitive to the units of x) - */ + *_NOSCAL algorithms are *not* scaled to a unit hypercube + (i.e. they are sensitive to the units of x) + */ - NLOPT_GN_DIRECT = 0, - NLOPT_GN_DIRECT_L, - NLOPT_GN_DIRECT_L_RAND, - NLOPT_GN_DIRECT_NOSCAL, - NLOPT_GN_DIRECT_L_NOSCAL, - NLOPT_GN_DIRECT_L_RAND_NOSCAL, + NLOPT_GN_DIRECT = 0, + NLOPT_GN_DIRECT_L, + NLOPT_GN_DIRECT_L_RAND, + NLOPT_GN_DIRECT_NOSCAL, + NLOPT_GN_DIRECT_L_NOSCAL, + NLOPT_GN_DIRECT_L_RAND_NOSCAL, - NLOPT_GN_ORIG_DIRECT, - NLOPT_GN_ORIG_DIRECT_L, + NLOPT_GN_ORIG_DIRECT, + NLOPT_GN_ORIG_DIRECT_L, - NLOPT_GD_STOGO, - NLOPT_GD_STOGO_RAND, + NLOPT_GD_STOGO, + NLOPT_GD_STOGO_RAND, - NLOPT_LD_LBFGS_NOCEDAL, + NLOPT_LD_LBFGS_NOCEDAL, - NLOPT_LD_LBFGS, + NLOPT_LD_LBFGS, - NLOPT_LN_PRAXIS, + NLOPT_LN_PRAXIS, - NLOPT_LD_VAR1, - NLOPT_LD_VAR2, + NLOPT_LD_VAR1, + NLOPT_LD_VAR2, - NLOPT_LD_TNEWTON, - NLOPT_LD_TNEWTON_RESTART, - NLOPT_LD_TNEWTON_PRECOND, - NLOPT_LD_TNEWTON_PRECOND_RESTART, + NLOPT_LD_TNEWTON, + NLOPT_LD_TNEWTON_RESTART, + NLOPT_LD_TNEWTON_PRECOND, + NLOPT_LD_TNEWTON_PRECOND_RESTART, - NLOPT_GN_CRS2_LM, + NLOPT_GN_CRS2_LM, - NLOPT_GN_MLSL, - NLOPT_GD_MLSL, - NLOPT_GN_MLSL_LDS, - NLOPT_GD_MLSL_LDS, + NLOPT_GN_MLSL, + NLOPT_GD_MLSL, + NLOPT_GN_MLSL_LDS, + NLOPT_GD_MLSL_LDS, - NLOPT_LD_MMA, + NLOPT_LD_MMA, - NLOPT_LN_COBYLA, + NLOPT_LN_COBYLA, - NLOPT_LN_NEWUOA, - NLOPT_LN_NEWUOA_BOUND, + NLOPT_LN_NEWUOA, + NLOPT_LN_NEWUOA_BOUND, - NLOPT_LN_NELDERMEAD, - NLOPT_LN_SBPLX, + NLOPT_LN_NELDERMEAD, + NLOPT_LN_SBPLX, - NLOPT_LN_AUGLAG, - NLOPT_LD_AUGLAG, - NLOPT_LN_AUGLAG_EQ, - NLOPT_LD_AUGLAG_EQ, + NLOPT_LN_AUGLAG, + NLOPT_LD_AUGLAG, + NLOPT_LN_AUGLAG_EQ, + NLOPT_LD_AUGLAG_EQ, - NLOPT_LN_BOBYQA, + NLOPT_LN_BOBYQA, - NLOPT_GN_ISRES, + NLOPT_GN_ISRES, - /* new variants that require local_optimizer to be set, - not with older constants for backwards compatibility */ - NLOPT_AUGLAG, - NLOPT_AUGLAG_EQ, - NLOPT_G_MLSL, - NLOPT_G_MLSL_LDS, + /* new variants that require local_optimizer to be set, + not with older constants for backwards compatibility */ + NLOPT_AUGLAG, + NLOPT_AUGLAG_EQ, + NLOPT_G_MLSL, + NLOPT_G_MLSL_LDS, - NLOPT_LD_SLSQP, + NLOPT_LD_SLSQP, - NLOPT_LD_CCSAQ, + NLOPT_LD_CCSAQ, - NLOPT_GN_ESCH, + NLOPT_GN_ESCH, - NLOPT_GN_AGS, + NLOPT_GN_AGS, - NLOPT_NUM_ALGORITHMS /* not an algorithm, just the number of them */ + NLOPT_NUM_ALGORITHMS /* not an algorithm, just the number of them */ } nlopt_algorithm; NLOPT_EXTERN(const char *) nlopt_algorithm_name(nlopt_algorithm a); typedef enum { - NLOPT_FAILURE = -1, /* generic failure code */ - NLOPT_INVALID_ARGS = -2, - NLOPT_OUT_OF_MEMORY = -3, - NLOPT_ROUNDOFF_LIMITED = -4, - NLOPT_FORCED_STOP = -5, - NLOPT_SUCCESS = 1, /* generic success code */ - NLOPT_STOPVAL_REACHED = 2, - NLOPT_FTOL_REACHED = 3, - NLOPT_XTOL_REACHED = 4, - NLOPT_MAXEVAL_REACHED = 5, - NLOPT_MAXTIME_REACHED = 6 + NLOPT_FAILURE = -1, /* generic failure code */ + NLOPT_INVALID_ARGS = -2, + NLOPT_OUT_OF_MEMORY = -3, + NLOPT_ROUNDOFF_LIMITED = -4, + NLOPT_FORCED_STOP = -5, + NLOPT_SUCCESS = 1, /* generic success code */ + NLOPT_STOPVAL_REACHED = 2, + NLOPT_FTOL_REACHED = 3, + NLOPT_XTOL_REACHED = 4, + NLOPT_MAXEVAL_REACHED = 5, + NLOPT_MAXTIME_REACHED = 6 } nlopt_result; #define NLOPT_MINF_MAX_REACHED NLOPT_STOPVAL_REACHED @@ -187,7 +184,7 @@ NLOPT_EXTERN(void) nlopt_version(int *major, int *minor, int *bugfix); compatibility, having functions with zillions of parameters, or relying non-reentrantly on global variables.*/ -struct nlopt_opt_s; /* opaque structure, defined internally */ +struct nlopt_opt_s; /* opaque structure, defined internally */ typedef struct nlopt_opt_s *nlopt_opt; /* the only immutable parameters of an optimization are the algorithm and @@ -197,13 +194,10 @@ NLOPT_EXTERN(nlopt_opt) nlopt_create(nlopt_algorithm algorithm, unsigned n); NLOPT_EXTERN(void) nlopt_destroy(nlopt_opt opt); NLOPT_EXTERN(nlopt_opt) nlopt_copy(const nlopt_opt opt); -NLOPT_EXTERN(nlopt_result) nlopt_optimize(nlopt_opt opt, double *x, - double *opt_f); +NLOPT_EXTERN(nlopt_result) nlopt_optimize(nlopt_opt opt, double *x, double *opt_f); -NLOPT_EXTERN(nlopt_result) nlopt_set_min_objective(nlopt_opt opt, nlopt_func f, - void *f_data); -NLOPT_EXTERN(nlopt_result) nlopt_set_max_objective(nlopt_opt opt, nlopt_func f, - void *f_data); +NLOPT_EXTERN(nlopt_result) nlopt_set_min_objective(nlopt_opt opt, nlopt_func f, void *f_data); +NLOPT_EXTERN(nlopt_result) nlopt_set_max_objective(nlopt_opt opt, nlopt_func f, void *f_data); NLOPT_EXTERN(nlopt_result) nlopt_set_precond_min_objective(nlopt_opt opt, nlopt_func f, nlopt_precond pre, void *f_data); NLOPT_EXTERN(nlopt_result) nlopt_set_precond_max_objective(nlopt_opt opt, nlopt_func f, nlopt_precond pre, void *f_data); @@ -211,48 +205,26 @@ NLOPT_EXTERN(nlopt_result) nlopt_set_precond_max_objective(nlopt_opt opt, nlopt_ NLOPT_EXTERN(nlopt_algorithm) nlopt_get_algorithm(const nlopt_opt opt); NLOPT_EXTERN(unsigned) nlopt_get_dimension(const nlopt_opt opt); -NLOPT_EXTERN(const char*) nlopt_get_errmsg(nlopt_opt opt); +NLOPT_EXTERN(const char *) nlopt_get_errmsg(nlopt_opt opt); /* constraints: */ -NLOPT_EXTERN(nlopt_result) nlopt_set_lower_bounds(nlopt_opt opt, - const double *lb); +NLOPT_EXTERN(nlopt_result) nlopt_set_lower_bounds(nlopt_opt opt, const double *lb); NLOPT_EXTERN(nlopt_result) nlopt_set_lower_bounds1(nlopt_opt opt, double lb); -NLOPT_EXTERN(nlopt_result) nlopt_get_lower_bounds(const nlopt_opt opt, - double *lb); -NLOPT_EXTERN(nlopt_result) nlopt_set_upper_bounds(nlopt_opt opt, - const double *ub); +NLOPT_EXTERN(nlopt_result) nlopt_get_lower_bounds(const nlopt_opt opt, double *lb); +NLOPT_EXTERN(nlopt_result) nlopt_set_upper_bounds(nlopt_opt opt, const double *ub); NLOPT_EXTERN(nlopt_result) nlopt_set_upper_bounds1(nlopt_opt opt, double ub); -NLOPT_EXTERN(nlopt_result) nlopt_get_upper_bounds(const nlopt_opt opt, - double *ub); +NLOPT_EXTERN(nlopt_result) nlopt_get_upper_bounds(const nlopt_opt opt, double *ub); NLOPT_EXTERN(nlopt_result) nlopt_remove_inequality_constraints(nlopt_opt opt); -NLOPT_EXTERN(nlopt_result) nlopt_add_inequality_constraint(nlopt_opt opt, - nlopt_func fc, - void *fc_data, - double tol); -NLOPT_EXTERN(nlopt_result) nlopt_add_precond_inequality_constraint( - nlopt_opt opt, nlopt_func fc, nlopt_precond pre, void *fc_data, - double tol); -NLOPT_EXTERN(nlopt_result) nlopt_add_inequality_mconstraint(nlopt_opt opt, - unsigned m, - nlopt_mfunc fc, - void *fc_data, - const double *tol); +NLOPT_EXTERN(nlopt_result) nlopt_add_inequality_constraint(nlopt_opt opt, nlopt_func fc, void *fc_data, double tol); +NLOPT_EXTERN(nlopt_result) nlopt_add_precond_inequality_constraint(nlopt_opt opt, nlopt_func fc, nlopt_precond pre, void *fc_data, double tol); +NLOPT_EXTERN(nlopt_result) nlopt_add_inequality_mconstraint(nlopt_opt opt, unsigned m, nlopt_mfunc fc, void *fc_data, const double *tol); NLOPT_EXTERN(nlopt_result) nlopt_remove_equality_constraints(nlopt_opt opt); -NLOPT_EXTERN(nlopt_result) nlopt_add_equality_constraint(nlopt_opt opt, - nlopt_func h, - void *h_data, - double tol); -NLOPT_EXTERN(nlopt_result) nlopt_add_precond_equality_constraint( - nlopt_opt opt, nlopt_func h, nlopt_precond pre, void *h_data, - double tol); -NLOPT_EXTERN(nlopt_result) nlopt_add_equality_mconstraint(nlopt_opt opt, - unsigned m, - nlopt_mfunc h, - void *h_data, - const double *tol); +NLOPT_EXTERN(nlopt_result) nlopt_add_equality_constraint(nlopt_opt opt, nlopt_func h, void *h_data, double tol); +NLOPT_EXTERN(nlopt_result) nlopt_add_precond_equality_constraint(nlopt_opt opt, nlopt_func h, nlopt_precond pre, void *h_data, double tol); +NLOPT_EXTERN(nlopt_result) nlopt_add_equality_mconstraint(nlopt_opt opt, unsigned m, nlopt_mfunc h, void *h_data, const double *tol); /* stopping criteria: */ @@ -268,8 +240,7 @@ NLOPT_EXTERN(nlopt_result) nlopt_set_xtol_rel(nlopt_opt opt, double tol); NLOPT_EXTERN(double) nlopt_get_xtol_rel(const nlopt_opt opt); NLOPT_EXTERN(nlopt_result) nlopt_set_xtol_abs1(nlopt_opt opt, double tol); NLOPT_EXTERN(nlopt_result) nlopt_set_xtol_abs(nlopt_opt opt, const double *tol); -NLOPT_EXTERN(nlopt_result) nlopt_get_xtol_abs(const nlopt_opt opt, - double *tol); +NLOPT_EXTERN(nlopt_result) nlopt_get_xtol_abs(const nlopt_opt opt, double *tol); NLOPT_EXTERN(nlopt_result) nlopt_set_maxeval(nlopt_opt opt, int maxeval); NLOPT_EXTERN(int) nlopt_get_maxeval(const nlopt_opt opt); @@ -285,8 +256,7 @@ NLOPT_EXTERN(int) nlopt_get_force_stop(const nlopt_opt opt); /* more algorithm-specific parameters */ -NLOPT_EXTERN(nlopt_result) nlopt_set_local_optimizer(nlopt_opt opt, - const nlopt_opt local_opt); +NLOPT_EXTERN(nlopt_result) nlopt_set_local_optimizer(nlopt_opt opt, const nlopt_opt local_opt); NLOPT_EXTERN(nlopt_result) nlopt_set_population(nlopt_opt opt, unsigned pop); NLOPT_EXTERN(unsigned) nlopt_get_population(const nlopt_opt opt); @@ -294,25 +264,19 @@ NLOPT_EXTERN(unsigned) nlopt_get_population(const nlopt_opt opt); NLOPT_EXTERN(nlopt_result) nlopt_set_vector_storage(nlopt_opt opt, unsigned dim); NLOPT_EXTERN(unsigned) nlopt_get_vector_storage(const nlopt_opt opt); -NLOPT_EXTERN(nlopt_result) nlopt_set_default_initial_step(nlopt_opt opt, - const double *x); -NLOPT_EXTERN(nlopt_result) nlopt_set_initial_step(nlopt_opt opt, - const double *dx); +NLOPT_EXTERN(nlopt_result) nlopt_set_default_initial_step(nlopt_opt opt, const double *x); +NLOPT_EXTERN(nlopt_result) nlopt_set_initial_step(nlopt_opt opt, const double *dx); NLOPT_EXTERN(nlopt_result) nlopt_set_initial_step1(nlopt_opt opt, double dx); -NLOPT_EXTERN(nlopt_result) nlopt_get_initial_step(const nlopt_opt opt, - const double *x, double *dx); +NLOPT_EXTERN(nlopt_result) nlopt_get_initial_step(const nlopt_opt opt, const double *x, double *dx); /* the following are functions mainly designed to be used internally by the Fortran and SWIG wrappers, allow us to tel nlopt_destroy and nlopt_copy to do something to the f_data pointers (e.g. free or duplicate them, respectively) */ -typedef void* (*nlopt_munge)(void *p); -NLOPT_EXTERN(void) nlopt_set_munge(nlopt_opt opt, - nlopt_munge munge_on_destroy, - nlopt_munge munge_on_copy); -typedef void* (*nlopt_munge2)(void *p, void *data); -NLOPT_EXTERN(void) nlopt_munge_data(nlopt_opt opt, - nlopt_munge2 munge, void *data); +typedef void *(*nlopt_munge) (void *p); +NLOPT_EXTERN(void) nlopt_set_munge(nlopt_opt opt, nlopt_munge munge_on_destroy, nlopt_munge munge_on_copy); +typedef void *(*nlopt_munge2) (void *p, void *data); +NLOPT_EXTERN(void) nlopt_munge_data(nlopt_opt opt, nlopt_munge2 munge, void *data); /*************************** DEPRECATED API **************************/ /* The new "object-oriented" API is preferred, since it allows us to @@ -328,50 +292,30 @@ NLOPT_EXTERN(void) nlopt_munge_data(nlopt_opt opt, # define NLOPT_DEPRECATED #endif -typedef double (*nlopt_func_old)(int n, const double *x, - double *gradient, /* NULL if not needed */ - void *func_data); - -NLOPT_EXTERN(nlopt_result) nlopt_minimize( - nlopt_algorithm algorithm, - int n, nlopt_func_old f, void *f_data, - const double *lb, const double *ub, /* bounds */ - double *x, /* in: initial guess, out: minimizer */ - double *minf, /* out: minimum */ - double minf_max, double ftol_rel, double ftol_abs, - double xtol_rel, const double *xtol_abs, - int maxeval, double maxtime) NLOPT_DEPRECATED; - -NLOPT_EXTERN(nlopt_result) nlopt_minimize_constrained( - nlopt_algorithm algorithm, - int n, nlopt_func_old f, void *f_data, - int m, nlopt_func_old fc, void *fc_data, ptrdiff_t fc_datum_size, - const double *lb, const double *ub, /* bounds */ - double *x, /* in: initial guess, out: minimizer */ - double *minf, /* out: minimum */ - double minf_max, double ftol_rel, double ftol_abs, - double xtol_rel, const double *xtol_abs, - int maxeval, double maxtime) NLOPT_DEPRECATED; - -NLOPT_EXTERN(nlopt_result) nlopt_minimize_econstrained( - nlopt_algorithm algorithm, - int n, nlopt_func_old f, void *f_data, - int m, nlopt_func_old fc, void *fc_data, ptrdiff_t fc_datum_size, - int p, nlopt_func_old h, void *h_data, ptrdiff_t h_datum_size, - const double *lb, const double *ub, /* bounds */ - double *x, /* in: initial guess, out: minimizer */ - double *minf, /* out: minimum */ - double minf_max, double ftol_rel, double ftol_abs, - double xtol_rel, const double *xtol_abs, - double htol_rel, double htol_abs, - int maxeval, double maxtime) NLOPT_DEPRECATED; - -NLOPT_EXTERN(void) nlopt_get_local_search_algorithm(nlopt_algorithm *deriv, - nlopt_algorithm *nonderiv, - int *maxeval) NLOPT_DEPRECATED; -NLOPT_EXTERN(void) nlopt_set_local_search_algorithm(nlopt_algorithm deriv, - nlopt_algorithm nonderiv, - int maxeval) NLOPT_DEPRECATED; +typedef double (*nlopt_func_old) (int n, const double *x, double *gradient, /* NULL if not needed */ + void *func_data); + +NLOPT_EXTERN(nlopt_result) nlopt_minimize(nlopt_algorithm algorithm, int n, nlopt_func_old f, void *f_data, + const double *lb, const double *ub, /* bounds */ + double *x, /* in: initial guess, out: minimizer */ + double *minf, /* out: minimum */ + double minf_max, double ftol_rel, double ftol_abs, double xtol_rel, const double *xtol_abs, int maxeval, double maxtime) NLOPT_DEPRECATED; + +NLOPT_EXTERN(nlopt_result) nlopt_minimize_constrained(nlopt_algorithm algorithm, int n, nlopt_func_old f, void *f_data, int m, nlopt_func_old fc, void *fc_data, ptrdiff_t fc_datum_size, + const double *lb, const double *ub, /* bounds */ + double *x, /* in: initial guess, out: minimizer */ + double *minf, /* out: minimum */ + double minf_max, double ftol_rel, double ftol_abs, double xtol_rel, const double *xtol_abs, int maxeval, double maxtime) NLOPT_DEPRECATED; + +NLOPT_EXTERN(nlopt_result) nlopt_minimize_econstrained(nlopt_algorithm algorithm, int n, nlopt_func_old f, void *f_data, int m, nlopt_func_old fc, void *fc_data, ptrdiff_t fc_datum_size, int p, nlopt_func_old h, void *h_data, ptrdiff_t h_datum_size, + const double *lb, const double *ub, /* bounds */ + double *x, /* in: initial guess, out: minimizer */ + double *minf, /* out: minimum */ + double minf_max, double ftol_rel, double ftol_abs, + double xtol_rel, const double *xtol_abs, double htol_rel, double htol_abs, int maxeval, double maxtime) NLOPT_DEPRECATED; + +NLOPT_EXTERN(void) nlopt_get_local_search_algorithm(nlopt_algorithm * deriv, nlopt_algorithm * nonderiv, int *maxeval) NLOPT_DEPRECATED; +NLOPT_EXTERN(void) nlopt_set_local_search_algorithm(nlopt_algorithm deriv, nlopt_algorithm nonderiv, int maxeval) NLOPT_DEPRECATED; NLOPT_EXTERN(int) nlopt_get_stochastic_population(void) NLOPT_DEPRECATED; NLOPT_EXTERN(void) nlopt_set_stochastic_population(int pop) NLOPT_DEPRECATED; @@ -381,5 +325,4 @@ NLOPT_EXTERN(void) nlopt_set_stochastic_population(int pop) NLOPT_DEPRECATED; #ifdef __cplusplus } /* extern "C" */ #endif /* __cplusplus */ - #endif diff --git a/src/api/optimize.c b/src/api/optimize.c index 88d71ee..c5c9446 100644 --- a/src/api/optimize.c +++ b/src/api/optimize.c @@ -32,10 +32,10 @@ #include "direct.h" #ifdef NLOPT_CXX -# include "stogo.h" +#include "stogo.h" #endif #ifdef NLOPT_CXX11 -# include "ags.h" +#include "ags.h" #endif #include "cdirect.h" @@ -59,44 +59,46 @@ static double f_bound(int n, const double *x, void *data_) { - int i; - nlopt_opt data = (nlopt_opt) data_; - double f; - - /* some methods do not support bound constraints, but support - discontinuous objectives so we can just return Inf for invalid x */ - for (i = 0; i < n; ++i) - if (x[i] < data->lb[i] || x[i] > data->ub[i]) - return HUGE_VAL; - - f = data->f((unsigned) n, x, NULL, data->f_data); - return (nlopt_isnan(f) || nlopt_isinf(f) ? HUGE_VAL : f); + int i; + nlopt_opt data = (nlopt_opt) data_; + double f; + + /* some methods do not support bound constraints, but support + discontinuous objectives so we can just return Inf for invalid x */ + for (i = 0; i < n; ++i) + if (x[i] < data->lb[i] || x[i] > data->ub[i]) + return HUGE_VAL; + + f = data->f((unsigned) n, x, NULL, data->f_data); + return (nlopt_isnan(f) || nlopt_isinf(f) ? HUGE_VAL : f); } static double f_noderiv(int n, const double *x, void *data_) { - nlopt_opt data = (nlopt_opt) data_; - return data->f((unsigned) n, x, NULL, data->f_data); + nlopt_opt data = (nlopt_opt) data_; + return data->f((unsigned) n, x, NULL, data->f_data); } static double f_direct(int n, const double *x, int *undefined, void *data_) { - nlopt_opt data = (nlopt_opt) data_; - double *work = (double*) data->work; - double f; - unsigned i, j; - f = data->f((unsigned) n, x, NULL, data->f_data); - ++data->numevals; - *undefined = nlopt_isnan(f) || nlopt_isinf(f); - if (nlopt_get_force_stop(data)) return f; - for (i = 0; i < data->m && !*undefined; ++i) { - nlopt_eval_constraint(work, NULL, data->fc+i, (unsigned) n, x); - if (nlopt_get_force_stop(data)) return f; - for (j = 0; j < data->fc[i].m; ++j) - if (work[j] > 0) - *undefined = 1; - } - return f; + nlopt_opt data = (nlopt_opt) data_; + double *work = (double *) data->work; + double f; + unsigned i, j; + f = data->f((unsigned) n, x, NULL, data->f_data); + ++data->numevals; + *undefined = nlopt_isnan(f) || nlopt_isinf(f); + if (nlopt_get_force_stop(data)) + return f; + for (i = 0; i < data->m && !*undefined; ++i) { + nlopt_eval_constraint(work, NULL, data->fc + i, (unsigned) n, x); + if (nlopt_get_force_stop(data)) + return f; + for (j = 0; j < data->fc[i].m; ++j) + if (work[j] > 0) + *undefined = 1; + } + return f; } /*********************************************************************/ @@ -104,21 +106,24 @@ static double f_direct(int n, const double *x, int *undefined, void *data_) /* get min(dx) for algorithms requiring a scalar initial step size */ static nlopt_result initial_step(nlopt_opt opt, const double *x, double *step) { - unsigned freedx = 0, i; - - if (!opt->dx) { - freedx = 1; - if (nlopt_set_default_initial_step(opt, x) != NLOPT_SUCCESS) - return NLOPT_OUT_OF_MEMORY; - } - - *step = HUGE_VAL; - for (i = 0; i < opt->n; ++i) - if (*step > fabs(opt->dx[i])) - *step = fabs(opt->dx[i]); - - if (freedx) { free(opt->dx); opt->dx = NULL; } - return NLOPT_SUCCESS; + unsigned freedx = 0, i; + + if (!opt->dx) { + freedx = 1; + if (nlopt_set_default_initial_step(opt, x) != NLOPT_SUCCESS) + return NLOPT_OUT_OF_MEMORY; + } + + *step = HUGE_VAL; + for (i = 0; i < opt->n; ++i) + if (*step > fabs(opt->dx[i])) + *step = fabs(opt->dx[i]); + + if (freedx) { + free(opt->dx); + opt->dx = NULL; + } + return NLOPT_SUCCESS; } /*********************************************************************/ @@ -126,10 +131,11 @@ static nlopt_result initial_step(nlopt_opt opt, const double *x, double *step) /* return true if [lb,ub] is finite in every dimension (n dimensions) */ static int finite_domain(unsigned n, const double *lb, const double *ub) { - unsigned i; - for (i = 0; i < n; ++i) - if (nlopt_isinf(ub[i] - lb[i])) return 0; - return 1; + unsigned i; + for (i = 0; i < n; ++i) + if (nlopt_isinf(ub[i] - lb[i])) + return 0; + return 1; } /*********************************************************************/ @@ -139,799 +145,762 @@ static int finite_domain(unsigned n, const double *lb, const double *ub) larger vectors where I am loathe to make copies unnecessarily.) */ typedef struct { - nlopt_func f; - nlopt_mfunc mf; - void *f_data; - unsigned n; /* true dimension */ - double *x; /* scratch vector of length n */ - double *grad; /* optional scratch vector of length n */ - const double *lb, *ub; /* bounds, of length n */ + nlopt_func f; + nlopt_mfunc mf; + void *f_data; + unsigned n; /* true dimension */ + double *x; /* scratch vector of length n */ + double *grad; /* optional scratch vector of length n */ + const double *lb, *ub; /* bounds, of length n */ } elimdim_data; -static void *elimdim_makedata(nlopt_func f, nlopt_mfunc mf, void *f_data, - unsigned n, double *x, const double *lb, - const double *ub, double *grad) +static void *elimdim_makedata(nlopt_func f, nlopt_mfunc mf, void *f_data, unsigned n, double *x, const double *lb, const double *ub, double *grad) { - elimdim_data *d = (elimdim_data *) malloc(sizeof(elimdim_data)); - if (!d) return NULL; - d->f = f; d->mf = mf; d->f_data = f_data; d->n = n; d->x = x; - d->lb = lb; d->ub = ub; - d->grad = grad; - return d; + elimdim_data *d = (elimdim_data *) malloc(sizeof(elimdim_data)); + if (!d) + return NULL; + d->f = f; + d->mf = mf; + d->f_data = f_data; + d->n = n; + d->x = x; + d->lb = lb; + d->ub = ub; + d->grad = grad; + return d; } static double elimdim_func(unsigned n0, const double *x0, double *grad, void *d_) { - elimdim_data *d = (elimdim_data *) d_; - double *x = d->x; - const double *lb = d->lb, *ub = d->ub; - double val; - unsigned n = d->n, i, j; - - (void) n0; /* unused */ - for (i = j = 0; i < n; ++i) { - if (lb[i] == ub[i]) - x[i] = lb[i]; - else /* assert: j < n0 */ - x[i] = x0[j++]; - } - val = d->f(n, x, grad ? d->grad : NULL, d->f_data); - if (grad) { - /* assert: d->grad != NULL */ - for (i = j = 0; i < n; ++i) - if (lb[i] != ub[i]) - grad[j++] = d->grad[i]; - } - return val; + elimdim_data *d = (elimdim_data *) d_; + double *x = d->x; + const double *lb = d->lb, *ub = d->ub; + double val; + unsigned n = d->n, i, j; + + (void) n0; /* unused */ + for (i = j = 0; i < n; ++i) { + if (lb[i] == ub[i]) + x[i] = lb[i]; + else /* assert: j < n0 */ + x[i] = x0[j++]; + } + val = d->f(n, x, grad ? d->grad : NULL, d->f_data); + if (grad) { + /* assert: d->grad != NULL */ + for (i = j = 0; i < n; ++i) + if (lb[i] != ub[i]) + grad[j++] = d->grad[i]; + } + return val; } - -static void elimdim_mfunc(unsigned m, double *result, - unsigned n0, const double *x0, double *grad, void *d_) +static void elimdim_mfunc(unsigned m, double *result, unsigned n0, const double *x0, double *grad, void *d_) { - elimdim_data *d = (elimdim_data *) d_; - double *x = d->x; - const double *lb = d->lb, *ub = d->ub; - unsigned n = d->n, i, j; - - (void) n0; /* unused */ - (void) grad; /* assert: grad == NULL */ - for (i = j = 0; i < n; ++i) { - if (lb[i] == ub[i]) - x[i] = lb[i]; - else /* assert: j < n0 */ - x[i] = x0[j++]; - } - d->mf(m, result, n, x, NULL, d->f_data); + elimdim_data *d = (elimdim_data *) d_; + double *x = d->x; + const double *lb = d->lb, *ub = d->ub; + unsigned n = d->n, i, j; + + (void) n0; /* unused */ + (void) grad; /* assert: grad == NULL */ + for (i = j = 0; i < n; ++i) { + if (lb[i] == ub[i]) + x[i] = lb[i]; + else /* assert: j < n0 */ + x[i] = x0[j++]; + } + d->mf(m, result, n, x, NULL, d->f_data); } /* compute the eliminated dimension: number of dims with lb[i] != ub[i] */ static unsigned elimdim_dimension(unsigned n, const double *lb, const double *ub) { - unsigned n0 = 0, i; - for (i = 0; i < n; ++i) n0 += lb[i] != ub[i] ? 1U : 0; - return n0; + unsigned n0 = 0, i; + for (i = 0; i < n; ++i) + n0 += lb[i] != ub[i] ? 1U : 0; + return n0; } /* modify v to "shrunk" version, with dimensions for lb[i] == ub[i] elim'ed */ -static void elimdim_shrink(unsigned n, double *v, - const double *lb, const double *ub) +static void elimdim_shrink(unsigned n, double *v, const double *lb, const double *ub) { - unsigned i, j; - if (v) - for (i = j = 0; i < n; ++i) - if (lb[i] != ub[i]) - v[j++] = v[i]; + unsigned i, j; + if (v) + for (i = j = 0; i < n; ++i) + if (lb[i] != ub[i]) + v[j++] = v[i]; } /* inverse of elimdim_shrink */ -static void elimdim_expand(unsigned n, double *v, - const double *lb, const double *ub) +static void elimdim_expand(unsigned n, double *v, const double *lb, const double *ub) { - unsigned i, j; - if (v && n > 0) { - j = elimdim_dimension(n, lb, ub) - 1; - for (i = n - 1; i > 0; --i) { - if (lb[i] != ub[i]) - v[i] = v[j--]; - else - v[i] = lb[i]; - } - if (lb[0] == ub[0]) - v[0] = lb[0]; - } + unsigned i, j; + if (v && n > 0) { + j = elimdim_dimension(n, lb, ub) - 1; + for (i = n - 1; i > 0; --i) { + if (lb[i] != ub[i]) + v[i] = v[j--]; + else + v[i] = lb[i]; + } + if (lb[0] == ub[0]) + v[0] = lb[0]; + } } /* given opt, create a new opt with equal-constraint dimensions eliminated */ static nlopt_opt elimdim_create(nlopt_opt opt) { - nlopt_opt opt0; - nlopt_munge munge_copy_save = opt->munge_on_copy; - double *x, *grad = NULL; - unsigned i; - - opt->munge_on_copy = 0; /* hack: since this is an internal copy, - we can leave it un-munged; see issue #26 */ - opt0 = nlopt_copy(opt); - opt->munge_on_copy = munge_copy_save; - if (!opt0) return NULL; - x = (double *) malloc(sizeof(double) * opt->n); - if (opt->n && !x) { nlopt_destroy(opt0); return NULL; } - - if (opt->algorithm == NLOPT_GD_STOGO - || opt->algorithm == NLOPT_GD_STOGO_RAND) { - grad = (double *) malloc(sizeof(double) * opt->n); - if (opt->n && !grad) goto bad; - } - - opt0->n = elimdim_dimension(opt->n, opt->lb, opt->ub); - elimdim_shrink(opt->n, opt0->lb, opt->lb, opt->ub); - elimdim_shrink(opt->n, opt0->ub, opt->lb, opt->ub); - elimdim_shrink(opt->n, opt0->xtol_abs, opt->lb, opt->ub); - elimdim_shrink(opt->n, opt0->dx, opt->lb, opt->ub); - - opt0->munge_on_destroy = opt0->munge_on_copy = NULL; - - opt0->f = elimdim_func; - opt0->f_data = elimdim_makedata(opt->f, NULL, opt->f_data, - opt->n, x, opt->lb, opt->ub, grad); - if (!opt0->f_data) goto bad; - - for (i = 0; i < opt->m; ++i) { - opt0->fc[i].f = opt0->fc[i].f ? elimdim_func : NULL; - opt0->fc[i].mf = opt0->fc[i].mf ? elimdim_mfunc : NULL; - opt0->fc[i].f_data = elimdim_makedata(opt->fc[i].f, opt->fc[i].mf, - opt->fc[i].f_data, - opt->n, x, opt->lb, opt->ub, - NULL); - if (!opt0->fc[i].f_data) goto bad; - } - - for (i = 0; i < opt->p; ++i) { - opt0->h[i].f = opt0->h[i].f ? elimdim_func : NULL; - opt0->h[i].mf = opt0->h[i].mf ? elimdim_mfunc : NULL; - opt0->h[i].f_data = elimdim_makedata(opt->h[i].f, opt->h[i].mf, - opt->h[i].f_data, - opt->n, x, opt->lb, opt->ub, - NULL); - if (!opt0->h[i].f_data) goto bad; - } - - return opt0; -bad: - free(grad); - free(x); - nlopt_destroy(opt0); - return NULL; + nlopt_opt opt0; + nlopt_munge munge_copy_save = opt->munge_on_copy; + double *x, *grad = NULL; + unsigned i; + + opt->munge_on_copy = 0; /* hack: since this is an internal copy, + we can leave it un-munged; see issue #26 */ + opt0 = nlopt_copy(opt); + opt->munge_on_copy = munge_copy_save; + if (!opt0) + return NULL; + x = (double *) malloc(sizeof(double) * opt->n); + if (opt->n && !x) { + nlopt_destroy(opt0); + return NULL; + } + + if (opt->algorithm == NLOPT_GD_STOGO || opt->algorithm == NLOPT_GD_STOGO_RAND) { + grad = (double *) malloc(sizeof(double) * opt->n); + if (opt->n && !grad) + goto bad; + } + + opt0->n = elimdim_dimension(opt->n, opt->lb, opt->ub); + elimdim_shrink(opt->n, opt0->lb, opt->lb, opt->ub); + elimdim_shrink(opt->n, opt0->ub, opt->lb, opt->ub); + elimdim_shrink(opt->n, opt0->xtol_abs, opt->lb, opt->ub); + elimdim_shrink(opt->n, opt0->dx, opt->lb, opt->ub); + + opt0->munge_on_destroy = opt0->munge_on_copy = NULL; + + opt0->f = elimdim_func; + opt0->f_data = elimdim_makedata(opt->f, NULL, opt->f_data, opt->n, x, opt->lb, opt->ub, grad); + if (!opt0->f_data) + goto bad; + + for (i = 0; i < opt->m; ++i) { + opt0->fc[i].f = opt0->fc[i].f ? elimdim_func : NULL; + opt0->fc[i].mf = opt0->fc[i].mf ? elimdim_mfunc : NULL; + opt0->fc[i].f_data = elimdim_makedata(opt->fc[i].f, opt->fc[i].mf, opt->fc[i].f_data, opt->n, x, opt->lb, opt->ub, NULL); + if (!opt0->fc[i].f_data) + goto bad; + } + + for (i = 0; i < opt->p; ++i) { + opt0->h[i].f = opt0->h[i].f ? elimdim_func : NULL; + opt0->h[i].mf = opt0->h[i].mf ? elimdim_mfunc : NULL; + opt0->h[i].f_data = elimdim_makedata(opt->h[i].f, opt->h[i].mf, opt->h[i].f_data, opt->n, x, opt->lb, opt->ub, NULL); + if (!opt0->h[i].f_data) + goto bad; + } + + return opt0; + bad: + free(grad); + free(x); + nlopt_destroy(opt0); + return NULL; } /* like nlopt_destroy, but also frees elimdim_data */ static void elimdim_destroy(nlopt_opt opt) { - unsigned i; - if (!opt) return; - - free(((elimdim_data*) opt->f_data)->x); - free(((elimdim_data*) opt->f_data)->grad); - free(opt->f_data); opt->f_data = NULL; - - for (i = 0; i < opt->m; ++i) { - free(opt->fc[i].f_data); - opt->fc[i].f_data = NULL; - } - for (i = 0; i < opt->p; ++i) { - free(opt->h[i].f_data); - opt->h[i].f_data = NULL; - } - - nlopt_destroy(opt); + unsigned i; + if (!opt) + return; + + free(((elimdim_data *) opt->f_data)->x); + free(((elimdim_data *) opt->f_data)->grad); + free(opt->f_data); + opt->f_data = NULL; + + for (i = 0; i < opt->m; ++i) { + free(opt->fc[i].f_data); + opt->fc[i].f_data = NULL; + } + for (i = 0; i < opt->p; ++i) { + free(opt->h[i].f_data); + opt->h[i].f_data = NULL; + } + + nlopt_destroy(opt); } /* return whether to use elimdim wrapping. */ static int elimdim_wrapcheck(nlopt_opt opt) { - if (!opt) return 0; - if (elimdim_dimension(opt->n, opt->lb, opt->ub) == opt->n) return 0; - switch (opt->algorithm) { - case NLOPT_GN_DIRECT: - case NLOPT_GN_DIRECT_L: - case NLOPT_GN_DIRECT_L_RAND: - case NLOPT_GN_DIRECT_NOSCAL: - case NLOPT_GN_DIRECT_L_NOSCAL: - case NLOPT_GN_DIRECT_L_RAND_NOSCAL: - case NLOPT_GN_ORIG_DIRECT: - case NLOPT_GN_ORIG_DIRECT_L: - case NLOPT_GN_CRS2_LM: - case NLOPT_LN_PRAXIS: - case NLOPT_LN_COBYLA: - case NLOPT_LN_NEWUOA: - case NLOPT_LN_NEWUOA_BOUND: - case NLOPT_LN_BOBYQA: - case NLOPT_LN_NELDERMEAD: - case NLOPT_LN_SBPLX: - case NLOPT_GN_ISRES: - case NLOPT_GN_ESCH: - case NLOPT_GN_AGS: - case NLOPT_GD_STOGO: - case NLOPT_GD_STOGO_RAND: - return 1; - - default: return 0; - } + if (!opt) + return 0; + if (elimdim_dimension(opt->n, opt->lb, opt->ub) == opt->n) + return 0; + switch (opt->algorithm) { + case NLOPT_GN_DIRECT: + case NLOPT_GN_DIRECT_L: + case NLOPT_GN_DIRECT_L_RAND: + case NLOPT_GN_DIRECT_NOSCAL: + case NLOPT_GN_DIRECT_L_NOSCAL: + case NLOPT_GN_DIRECT_L_RAND_NOSCAL: + case NLOPT_GN_ORIG_DIRECT: + case NLOPT_GN_ORIG_DIRECT_L: + case NLOPT_GN_CRS2_LM: + case NLOPT_LN_PRAXIS: + case NLOPT_LN_COBYLA: + case NLOPT_LN_NEWUOA: + case NLOPT_LN_NEWUOA_BOUND: + case NLOPT_LN_BOBYQA: + case NLOPT_LN_NELDERMEAD: + case NLOPT_LN_SBPLX: + case NLOPT_GN_ISRES: + case NLOPT_GN_ESCH: + case NLOPT_GN_AGS: + case NLOPT_GD_STOGO: + case NLOPT_GD_STOGO_RAND: + return 1; + + default: + return 0; + } } /*********************************************************************/ -#define POP(defaultpop) (opt->stochastic_population > 0 ? \ - opt->stochastic_population : \ - (nlopt_stochastic_population > 0 ? \ - nlopt_stochastic_population : (defaultpop))) +#define POP(defaultpop) (opt->stochastic_population > 0 ? opt->stochastic_population : (nlopt_stochastic_population > 0 ? nlopt_stochastic_population : (defaultpop))) /* unlike nlopt_optimize() below, only handles minimization case */ static nlopt_result nlopt_optimize_(nlopt_opt opt, double *x, double *minf) { - const double *lb, *ub; - nlopt_algorithm algorithm; - nlopt_func f; void *f_data; - unsigned n, i; - int ni; - nlopt_stopping stop; - - if (!opt || !x || !minf || !opt->f - || opt->maximize) RETURN_ERR(NLOPT_INVALID_ARGS, opt, - "NULL args to nlopt_optimize_"); - - /* reset stopping flag */ - nlopt_set_force_stop(opt, 0); - opt->force_stop_child = NULL; - - /* copy a few params to local vars for convenience */ - n = opt->n; - ni = (int) n; /* most of the subroutines take "int" arg */ - lb = opt->lb; ub = opt->ub; - algorithm = opt->algorithm; - f = opt->f; f_data = opt->f_data; - - if (n == 0) { /* trivial case: no degrees of freedom */ - *minf = opt->f(n, x, NULL, opt->f_data); - return NLOPT_SUCCESS; - } - - *minf = HUGE_VAL; - - /* make sure rand generator is inited */ - nlopt_srand_time_default(); /* default is non-deterministic */ - - /* check bound constraints */ - for (i = 0; i < n; ++i) - if (lb[i] > ub[i] || x[i] < lb[i] || x[i] > ub[i]) { - nlopt_set_errmsg(opt, "bounds %d fail %g <= %g <= %g", - i, lb[i], x[i], ub[i]); - return NLOPT_INVALID_ARGS; - } - - stop.n = n; - stop.minf_max = opt->stopval; - stop.ftol_rel = opt->ftol_rel; - stop.ftol_abs = opt->ftol_abs; - stop.xtol_rel = opt->xtol_rel; - stop.xtol_abs = opt->xtol_abs; - opt->numevals = 0; - stop.nevals_p = &(opt->numevals); - stop.maxeval = opt->maxeval; - stop.maxtime = opt->maxtime; - stop.start = nlopt_seconds(); - stop.force_stop = &(opt->force_stop); - stop.stop_msg = &(opt->errmsg); - - switch (algorithm) { - case NLOPT_GN_DIRECT: - case NLOPT_GN_DIRECT_L: - case NLOPT_GN_DIRECT_L_RAND: - if (!finite_domain(n, lb, ub)) - RETURN_ERR(NLOPT_INVALID_ARGS, opt, - "finite domain required for global algorithm"); - return cdirect(ni, f, f_data, - lb, ub, x, minf, &stop, 0.0, - (algorithm != NLOPT_GN_DIRECT) - + 3 * (algorithm == NLOPT_GN_DIRECT_L_RAND - ? 2 : (algorithm != NLOPT_GN_DIRECT)) - + 9 * (algorithm == NLOPT_GN_DIRECT_L_RAND - ? 1 : (algorithm != NLOPT_GN_DIRECT))); - - case NLOPT_GN_DIRECT_NOSCAL: - case NLOPT_GN_DIRECT_L_NOSCAL: - case NLOPT_GN_DIRECT_L_RAND_NOSCAL: - if (!finite_domain(n, lb, ub)) - RETURN_ERR(NLOPT_INVALID_ARGS, opt, - "finite domain required for global algorithm"); - return cdirect_unscaled(ni, f, f_data, lb, ub, x, minf, - &stop, 0.0, - (algorithm != NLOPT_GN_DIRECT) - + 3 * (algorithm == NLOPT_GN_DIRECT_L_RAND ? 2 : (algorithm != NLOPT_GN_DIRECT)) - + 9 * (algorithm == NLOPT_GN_DIRECT_L_RAND ? 1 : (algorithm != NLOPT_GN_DIRECT))); - - case NLOPT_GN_ORIG_DIRECT: - case NLOPT_GN_ORIG_DIRECT_L: { - direct_return_code dret; - if (!finite_domain(n, lb, ub)) - RETURN_ERR(NLOPT_INVALID_ARGS, opt, - "finite domain required for global algorithm"); - opt->work = malloc(sizeof(double) * - nlopt_max_constraint_dim(opt->m, - opt->fc)); - if (!opt->work) return NLOPT_OUT_OF_MEMORY; - dret = direct_optimize(f_direct, opt, ni, lb, ub, x, minf, - stop.maxeval, -1, - stop.start, stop.maxtime, - 0.0, 0.0, - pow(stop.xtol_rel, (double) n), -1.0, - stop.force_stop, - stop.minf_max, 0.0, - NULL, - algorithm == NLOPT_GN_ORIG_DIRECT - ? DIRECT_ORIGINAL - : DIRECT_GABLONSKY); - free(opt->work); opt->work = NULL; - switch (dret) { - case DIRECT_INVALID_BOUNDS: - RETURN_ERR(NLOPT_INVALID_ARGS, opt, - "invalid bounds for DIRECT"); - case DIRECT_MAXFEVAL_TOOBIG: - RETURN_ERR(NLOPT_INVALID_ARGS, opt, - "maxeval too big for DIRECT"); - case DIRECT_INVALID_ARGS: - return NLOPT_INVALID_ARGS; - case DIRECT_INIT_FAILED: - RETURN_ERR(NLOPT_FAILURE, opt, - "init failed for DIRECT"); - case DIRECT_SAMPLEPOINTS_FAILED: - RETURN_ERR(NLOPT_FAILURE, opt, - "sample-points failed for DIRECT"); - case DIRECT_SAMPLE_FAILED: - RETURN_ERR(NLOPT_FAILURE, opt, - "sample failed for DIRECT"); - case DIRECT_MAXFEVAL_EXCEEDED: - case DIRECT_MAXITER_EXCEEDED: - return NLOPT_MAXEVAL_REACHED; - case DIRECT_MAXTIME_EXCEEDED: - return NLOPT_MAXTIME_REACHED; - case DIRECT_GLOBAL_FOUND: - return NLOPT_MINF_MAX_REACHED; - case DIRECT_VOLTOL: - case DIRECT_SIGMATOL: - return NLOPT_XTOL_REACHED; - case DIRECT_OUT_OF_MEMORY: - return NLOPT_OUT_OF_MEMORY; - case DIRECT_FORCED_STOP: - return NLOPT_FORCED_STOP; - } - break; - } - - case NLOPT_GN_AGS: + const double *lb, *ub; + nlopt_algorithm algorithm; + nlopt_func f; + void *f_data; + unsigned n, i; + int ni; + nlopt_stopping stop; + + if (!opt || !x || !minf || !opt->f || opt->maximize) + RETURN_ERR(NLOPT_INVALID_ARGS, opt, "NULL args to nlopt_optimize_"); + + /* reset stopping flag */ + nlopt_set_force_stop(opt, 0); + opt->force_stop_child = NULL; + + /* copy a few params to local vars for convenience */ + n = opt->n; + ni = (int) n; /* most of the subroutines take "int" arg */ + lb = opt->lb; + ub = opt->ub; + algorithm = opt->algorithm; + f = opt->f; + f_data = opt->f_data; + + if (n == 0) { /* trivial case: no degrees of freedom */ + *minf = opt->f(n, x, NULL, opt->f_data); + return NLOPT_SUCCESS; + } + + *minf = HUGE_VAL; + + /* make sure rand generator is inited */ + nlopt_srand_time_default(); /* default is non-deterministic */ + + /* check bound constraints */ + for (i = 0; i < n; ++i) + if (lb[i] > ub[i] || x[i] < lb[i] || x[i] > ub[i]) { + nlopt_set_errmsg(opt, "bounds %d fail %g <= %g <= %g", i, lb[i], x[i], ub[i]); + return NLOPT_INVALID_ARGS; + } + + stop.n = n; + stop.minf_max = opt->stopval; + stop.ftol_rel = opt->ftol_rel; + stop.ftol_abs = opt->ftol_abs; + stop.xtol_rel = opt->xtol_rel; + stop.xtol_abs = opt->xtol_abs; + opt->numevals = 0; + stop.nevals_p = &(opt->numevals); + stop.maxeval = opt->maxeval; + stop.maxtime = opt->maxtime; + stop.start = nlopt_seconds(); + stop.force_stop = &(opt->force_stop); + stop.stop_msg = &(opt->errmsg); + + switch (algorithm) { + case NLOPT_GN_DIRECT: + case NLOPT_GN_DIRECT_L: + case NLOPT_GN_DIRECT_L_RAND: + if (!finite_domain(n, lb, ub)) + RETURN_ERR(NLOPT_INVALID_ARGS, opt, "finite domain required for global algorithm"); + return cdirect(ni, f, f_data, lb, ub, x, minf, &stop, 0.0, (algorithm != NLOPT_GN_DIRECT) + 3 * (algorithm == NLOPT_GN_DIRECT_L_RAND ? 2 : (algorithm != NLOPT_GN_DIRECT)) + + 9 * (algorithm == NLOPT_GN_DIRECT_L_RAND ? 1 : (algorithm != NLOPT_GN_DIRECT))); + + case NLOPT_GN_DIRECT_NOSCAL: + case NLOPT_GN_DIRECT_L_NOSCAL: + case NLOPT_GN_DIRECT_L_RAND_NOSCAL: + if (!finite_domain(n, lb, ub)) + RETURN_ERR(NLOPT_INVALID_ARGS, opt, "finite domain required for global algorithm"); + return cdirect_unscaled(ni, f, f_data, lb, ub, x, minf, &stop, 0.0, (algorithm != NLOPT_GN_DIRECT) + 3 * (algorithm == NLOPT_GN_DIRECT_L_RAND ? 2 : (algorithm != NLOPT_GN_DIRECT)) + + 9 * (algorithm == NLOPT_GN_DIRECT_L_RAND ? 1 : (algorithm != NLOPT_GN_DIRECT))); + + case NLOPT_GN_ORIG_DIRECT: + case NLOPT_GN_ORIG_DIRECT_L: + { + direct_return_code dret; + if (!finite_domain(n, lb, ub)) + RETURN_ERR(NLOPT_INVALID_ARGS, opt, "finite domain required for global algorithm"); + opt->work = malloc(sizeof(double) * nlopt_max_constraint_dim(opt->m, opt->fc)); + if (!opt->work) + return NLOPT_OUT_OF_MEMORY; + dret = direct_optimize(f_direct, opt, ni, lb, ub, x, minf, + stop.maxeval, -1, + stop.start, stop.maxtime, + 0.0, 0.0, pow(stop.xtol_rel, (double) n), -1.0, stop.force_stop, stop.minf_max, 0.0, NULL, algorithm == NLOPT_GN_ORIG_DIRECT ? DIRECT_ORIGINAL : DIRECT_GABLONSKY); + free(opt->work); + opt->work = NULL; + switch (dret) { + case DIRECT_INVALID_BOUNDS: + RETURN_ERR(NLOPT_INVALID_ARGS, opt, "invalid bounds for DIRECT"); + case DIRECT_MAXFEVAL_TOOBIG: + RETURN_ERR(NLOPT_INVALID_ARGS, opt, "maxeval too big for DIRECT"); + case DIRECT_INVALID_ARGS: + return NLOPT_INVALID_ARGS; + case DIRECT_INIT_FAILED: + RETURN_ERR(NLOPT_FAILURE, opt, "init failed for DIRECT"); + case DIRECT_SAMPLEPOINTS_FAILED: + RETURN_ERR(NLOPT_FAILURE, opt, "sample-points failed for DIRECT"); + case DIRECT_SAMPLE_FAILED: + RETURN_ERR(NLOPT_FAILURE, opt, "sample failed for DIRECT"); + case DIRECT_MAXFEVAL_EXCEEDED: + case DIRECT_MAXITER_EXCEEDED: + return NLOPT_MAXEVAL_REACHED; + case DIRECT_MAXTIME_EXCEEDED: + return NLOPT_MAXTIME_REACHED; + case DIRECT_GLOBAL_FOUND: + return NLOPT_MINF_MAX_REACHED; + case DIRECT_VOLTOL: + case DIRECT_SIGMATOL: + return NLOPT_XTOL_REACHED; + case DIRECT_OUT_OF_MEMORY: + return NLOPT_OUT_OF_MEMORY; + case DIRECT_FORCED_STOP: + return NLOPT_FORCED_STOP; + } + break; + } + + case NLOPT_GN_AGS: #ifdef NLOPT_CXX11 - if (!finite_domain(n, lb, ub)) - RETURN_ERR(NLOPT_INVALID_ARGS, opt, - "finite domain required for global algorithm"); - return ags_minimize(ni, f, f_data, opt->m, opt->fc, x, minf, lb, ub, &stop); - break; + if (!finite_domain(n, lb, ub)) + RETURN_ERR(NLOPT_INVALID_ARGS, opt, "finite domain required for global algorithm"); + return ags_minimize(ni, f, f_data, opt->m, opt->fc, x, minf, lb, ub, &stop); + break; #else - return NLOPT_INVALID_ARGS; + return NLOPT_INVALID_ARGS; #endif - case NLOPT_GD_STOGO: - case NLOPT_GD_STOGO_RAND: + case NLOPT_GD_STOGO: + case NLOPT_GD_STOGO_RAND: #ifdef NLOPT_CXX - if (!finite_domain(n, lb, ub)) - RETURN_ERR(NLOPT_INVALID_ARGS, opt, - "finite domain required for global algorithm"); - if (!stogo_minimize(ni, f, f_data, x, minf, lb, ub, &stop, - algorithm == NLOPT_GD_STOGO - ? 0 : (int) POP(2*n))) - return NLOPT_FAILURE; - break; + if (!finite_domain(n, lb, ub)) + RETURN_ERR(NLOPT_INVALID_ARGS, opt, "finite domain required for global algorithm"); + if (!stogo_minimize(ni, f, f_data, x, minf, lb, ub, &stop, algorithm == NLOPT_GD_STOGO ? 0 : (int) POP(2 * n))) + return NLOPT_FAILURE; + break; #else - return NLOPT_INVALID_ARGS; + return NLOPT_INVALID_ARGS; #endif #if 0 - /* lacking a free/open-source license, we no longer use - Rowan's code, and instead use by "sbplx" re-implementation */ - case NLOPT_LN_SUBPLEX: { - int iret, freedx = 0; - if (!opt->dx) { - freedx = 1; - if (nlopt_set_default_initial_step(opt, x) != NLOPT_SUCCESS) - return NLOPT_OUT_OF_MEMORY; - } - iret = nlopt_subplex(f_bound, minf, x, n, opt, &stop, opt->dx); - if (freedx) { free(opt->dx); opt->dx = NULL; } - switch (iret) { - case -2: return NLOPT_INVALID_ARGS; - case -20: return NLOPT_FORCED_STOP; - case -10: return NLOPT_MAXTIME_REACHED; - case -1: return NLOPT_MAXEVAL_REACHED; - case 0: return NLOPT_XTOL_REACHED; - case 1: return NLOPT_SUCCESS; - case 2: return NLOPT_MINF_MAX_REACHED; - case 20: return NLOPT_FTOL_REACHED; - case -200: return NLOPT_OUT_OF_MEMORY; - default: return NLOPT_FAILURE; /* unknown return code */ - } - break; - } + /* lacking a free/open-source license, we no longer use + Rowan's code, and instead use by "sbplx" re-implementation */ + case NLOPT_LN_SUBPLEX: + { + int iret, freedx = 0; + if (!opt->dx) { + freedx = 1; + if (nlopt_set_default_initial_step(opt, x) != NLOPT_SUCCESS) + return NLOPT_OUT_OF_MEMORY; + } + iret = nlopt_subplex(f_bound, minf, x, n, opt, &stop, opt->dx); + if (freedx) { + free(opt->dx); + opt->dx = NULL; + } + switch (iret) { + case -2: + return NLOPT_INVALID_ARGS; + case -20: + return NLOPT_FORCED_STOP; + case -10: + return NLOPT_MAXTIME_REACHED; + case -1: + return NLOPT_MAXEVAL_REACHED; + case 0: + return NLOPT_XTOL_REACHED; + case 1: + return NLOPT_SUCCESS; + case 2: + return NLOPT_MINF_MAX_REACHED; + case 20: + return NLOPT_FTOL_REACHED; + case -200: + return NLOPT_OUT_OF_MEMORY; + default: + return NLOPT_FAILURE; /* unknown return code */ + } + break; + } #endif - case NLOPT_LN_PRAXIS: { - double step; - if (initial_step(opt, x, &step) != NLOPT_SUCCESS) - return NLOPT_OUT_OF_MEMORY; - return praxis_(0.0, DBL_EPSILON, - step, ni, x, f_bound, opt, &stop, minf); - } - - case NLOPT_LD_LBFGS: - return luksan_plis(ni, f, f_data, lb, ub, x, minf, - &stop, opt->vector_storage); - - case NLOPT_LD_VAR1: - case NLOPT_LD_VAR2: - return luksan_plip(ni, f, f_data, lb, ub, x, minf, - &stop, opt->vector_storage, - algorithm == NLOPT_LD_VAR1 ? 1 : 2); - - case NLOPT_LD_TNEWTON: - case NLOPT_LD_TNEWTON_RESTART: - case NLOPT_LD_TNEWTON_PRECOND: - case NLOPT_LD_TNEWTON_PRECOND_RESTART: - return luksan_pnet(ni, f, f_data, lb, ub, x, minf, - &stop, opt->vector_storage, - 1 + (algorithm - NLOPT_LD_TNEWTON) % 2, - 1 + (algorithm - NLOPT_LD_TNEWTON) / 2); - - case NLOPT_GN_CRS2_LM: - if (!finite_domain(n, lb, ub)) - RETURN_ERR(NLOPT_INVALID_ARGS, opt, - "finite domain required for global algorithm"); - return crs_minimize(ni, f, f_data, lb, ub, x, minf, &stop, - (int) POP(0), 0); - - case NLOPT_G_MLSL: - case NLOPT_G_MLSL_LDS: - case NLOPT_GN_MLSL: - case NLOPT_GD_MLSL: - case NLOPT_GN_MLSL_LDS: - case NLOPT_GD_MLSL_LDS: { - nlopt_opt local_opt = opt->local_opt; - nlopt_result ret; - if (!finite_domain(n, lb, ub)) - RETURN_ERR(NLOPT_INVALID_ARGS, opt, - "finite domain required for global algorithm"); - if (!local_opt && (algorithm == NLOPT_G_MLSL - || algorithm == NLOPT_G_MLSL_LDS)) - RETURN_ERR(NLOPT_INVALID_ARGS, opt, - "local optimizer must be specified for G_MLSL"); - if (!local_opt) { /* default */ - nlopt_algorithm local_alg = (algorithm == NLOPT_GN_MLSL || - algorithm == NLOPT_GN_MLSL_LDS) - ? nlopt_local_search_alg_nonderiv - : nlopt_local_search_alg_deriv; - /* don't call MLSL recursively! */ - if (local_alg >= NLOPT_GN_MLSL - && local_alg <= NLOPT_GD_MLSL_LDS) - local_alg = (algorithm == NLOPT_GN_MLSL || - algorithm == NLOPT_GN_MLSL_LDS) - ? NLOPT_LN_COBYLA : NLOPT_LD_MMA; - local_opt = nlopt_create(local_alg, n); - if (!local_opt) RETURN_ERR(NLOPT_FAILURE, opt, - "failed to create local_opt"); - nlopt_set_ftol_rel(local_opt, opt->ftol_rel); - nlopt_set_ftol_abs(local_opt, opt->ftol_abs); - nlopt_set_xtol_rel(local_opt, opt->xtol_rel); - nlopt_set_xtol_abs(local_opt, opt->xtol_abs); - nlopt_set_maxeval(local_opt, nlopt_local_search_maxeval); - } - if (opt->dx) nlopt_set_initial_step(local_opt, opt->dx); - for (i = 0; i < n && stop.xtol_abs[i] > 0; ++i) ; - if (local_opt->ftol_rel <= 0 && local_opt->ftol_abs <= 0 && - local_opt->xtol_rel <= 0 && i < n) { - /* it is not sensible to call MLSL without *some* - nonzero tolerance for the local search */ - nlopt_set_ftol_rel(local_opt, 1e-15); - nlopt_set_xtol_rel(local_opt, 1e-7); - } - opt->force_stop_child = local_opt; - ret = mlsl_minimize(ni, f, f_data, lb, ub, x, minf, &stop, - local_opt, (int) POP(0), - algorithm >= NLOPT_GN_MLSL_LDS && - algorithm != NLOPT_G_MLSL); - opt->force_stop_child = NULL; - if (!opt->local_opt) nlopt_destroy(local_opt); - return ret; - } - - case NLOPT_LD_MMA: case NLOPT_LD_CCSAQ: { - nlopt_opt dual_opt; - nlopt_result ret; + case NLOPT_LN_PRAXIS: + { + double step; + if (initial_step(opt, x, &step) != NLOPT_SUCCESS) + return NLOPT_OUT_OF_MEMORY; + return praxis_(0.0, DBL_EPSILON, step, ni, x, f_bound, opt, &stop, minf); + } + + case NLOPT_LD_LBFGS: + return luksan_plis(ni, f, f_data, lb, ub, x, minf, &stop, opt->vector_storage); + + case NLOPT_LD_VAR1: + case NLOPT_LD_VAR2: + return luksan_plip(ni, f, f_data, lb, ub, x, minf, &stop, opt->vector_storage, algorithm == NLOPT_LD_VAR1 ? 1 : 2); + + case NLOPT_LD_TNEWTON: + case NLOPT_LD_TNEWTON_RESTART: + case NLOPT_LD_TNEWTON_PRECOND: + case NLOPT_LD_TNEWTON_PRECOND_RESTART: + return luksan_pnet(ni, f, f_data, lb, ub, x, minf, &stop, opt->vector_storage, 1 + (algorithm - NLOPT_LD_TNEWTON) % 2, 1 + (algorithm - NLOPT_LD_TNEWTON) / 2); + + case NLOPT_GN_CRS2_LM: + if (!finite_domain(n, lb, ub)) + RETURN_ERR(NLOPT_INVALID_ARGS, opt, "finite domain required for global algorithm"); + return crs_minimize(ni, f, f_data, lb, ub, x, minf, &stop, (int) POP(0), 0); + + case NLOPT_G_MLSL: + case NLOPT_G_MLSL_LDS: + case NLOPT_GN_MLSL: + case NLOPT_GD_MLSL: + case NLOPT_GN_MLSL_LDS: + case NLOPT_GD_MLSL_LDS: + { + nlopt_opt local_opt = opt->local_opt; + nlopt_result ret; + if (!finite_domain(n, lb, ub)) + RETURN_ERR(NLOPT_INVALID_ARGS, opt, "finite domain required for global algorithm"); + if (!local_opt && (algorithm == NLOPT_G_MLSL || algorithm == NLOPT_G_MLSL_LDS)) + RETURN_ERR(NLOPT_INVALID_ARGS, opt, "local optimizer must be specified for G_MLSL"); + if (!local_opt) { /* default */ + nlopt_algorithm local_alg = (algorithm == NLOPT_GN_MLSL || algorithm == NLOPT_GN_MLSL_LDS) + ? nlopt_local_search_alg_nonderiv : nlopt_local_search_alg_deriv; + /* don't call MLSL recursively! */ + if (local_alg >= NLOPT_GN_MLSL && local_alg <= NLOPT_GD_MLSL_LDS) + local_alg = (algorithm == NLOPT_GN_MLSL || algorithm == NLOPT_GN_MLSL_LDS) + ? NLOPT_LN_COBYLA : NLOPT_LD_MMA; + local_opt = nlopt_create(local_alg, n); + if (!local_opt) + RETURN_ERR(NLOPT_FAILURE, opt, "failed to create local_opt"); + nlopt_set_ftol_rel(local_opt, opt->ftol_rel); + nlopt_set_ftol_abs(local_opt, opt->ftol_abs); + nlopt_set_xtol_rel(local_opt, opt->xtol_rel); + nlopt_set_xtol_abs(local_opt, opt->xtol_abs); + nlopt_set_maxeval(local_opt, nlopt_local_search_maxeval); + } + if (opt->dx) + nlopt_set_initial_step(local_opt, opt->dx); + for (i = 0; i < n && stop.xtol_abs[i] > 0; ++i); + if (local_opt->ftol_rel <= 0 && local_opt->ftol_abs <= 0 && local_opt->xtol_rel <= 0 && i < n) { + /* it is not sensible to call MLSL without *some* + nonzero tolerance for the local search */ + nlopt_set_ftol_rel(local_opt, 1e-15); + nlopt_set_xtol_rel(local_opt, 1e-7); + } + opt->force_stop_child = local_opt; + ret = mlsl_minimize(ni, f, f_data, lb, ub, x, minf, &stop, local_opt, (int) POP(0), algorithm >= NLOPT_GN_MLSL_LDS && algorithm != NLOPT_G_MLSL); + opt->force_stop_child = NULL; + if (!opt->local_opt) + nlopt_destroy(local_opt); + return ret; + } + + case NLOPT_LD_MMA: + case NLOPT_LD_CCSAQ: + { + nlopt_opt dual_opt; + nlopt_result ret; #define LO(param, def) (opt->local_opt ? opt->local_opt->param : (def)) - dual_opt = nlopt_create(LO(algorithm, - nlopt_local_search_alg_deriv), - nlopt_count_constraints(opt->m, - opt->fc)); - if (!dual_opt) RETURN_ERR(NLOPT_FAILURE, opt, - "failed creating dual optimizer"); - nlopt_set_ftol_rel(dual_opt, LO(ftol_rel, 1e-14)); - nlopt_set_ftol_abs(dual_opt, LO(ftol_abs, 0.0)); - nlopt_set_maxeval(dual_opt, LO(maxeval, 100000)); + dual_opt = nlopt_create(LO(algorithm, nlopt_local_search_alg_deriv), nlopt_count_constraints(opt->m, opt->fc)); + if (!dual_opt) + RETURN_ERR(NLOPT_FAILURE, opt, "failed creating dual optimizer"); + nlopt_set_ftol_rel(dual_opt, LO(ftol_rel, 1e-14)); + nlopt_set_ftol_abs(dual_opt, LO(ftol_abs, 0.0)); + nlopt_set_maxeval(dual_opt, LO(maxeval, 100000)); #undef LO - if (algorithm == NLOPT_LD_MMA) - ret = mma_minimize(n, f, f_data, opt->m, opt->fc, - lb, ub, x, minf, &stop, dual_opt); - else - ret = ccsa_quadratic_minimize( - n, f, f_data, opt->m, opt->fc, opt->pre, - lb, ub, x, minf, &stop, dual_opt); - nlopt_destroy(dual_opt); - return ret; - } - - case NLOPT_LN_COBYLA: { - nlopt_result ret; - int freedx = 0; - if (!opt->dx) { - freedx = 1; - if (nlopt_set_default_initial_step(opt, x) != NLOPT_SUCCESS) - RETURN_ERR(NLOPT_OUT_OF_MEMORY, opt, - "failed to allocate initial step"); - } - ret = cobyla_minimize(n, f, f_data, - opt->m, opt->fc, - opt->p, opt->h, - lb, ub, x, minf, &stop, - opt->dx); - if (freedx) { free(opt->dx); opt->dx = NULL; } - return ret; - } - - case NLOPT_LN_NEWUOA: { - double step; - if (initial_step(opt, x, &step) != NLOPT_SUCCESS) - RETURN_ERR(NLOPT_OUT_OF_MEMORY, opt, - "failed to allocate initial step"); - return newuoa(ni, 2*n+1, x, 0, 0, step, - &stop, minf, f_noderiv, opt); - } - - case NLOPT_LN_NEWUOA_BOUND: { - double step; - if (initial_step(opt, x, &step) != NLOPT_SUCCESS) - RETURN_ERR(NLOPT_OUT_OF_MEMORY, opt, - "failed to allocate initial step"); - return newuoa(ni, 2*n+1, x, lb, ub, step, - &stop, minf, f_noderiv, opt); - } - - case NLOPT_LN_BOBYQA: { - nlopt_result ret; - int freedx = 0; - if (!opt->dx) { - freedx = 1; - if (nlopt_set_default_initial_step(opt, x) != NLOPT_SUCCESS) - RETURN_ERR(NLOPT_OUT_OF_MEMORY, opt, - "failed to allocate initial step"); - } - ret = bobyqa(ni, 2*n+1, x, lb, ub, opt->dx, - &stop, minf, opt->f, opt->f_data); - if (freedx) { free(opt->dx); opt->dx = NULL; } - return ret; - } - - case NLOPT_LN_NELDERMEAD: - case NLOPT_LN_SBPLX: - { - nlopt_result ret; - int freedx = 0; - if (!opt->dx) { - freedx = 1; - if (nlopt_set_default_initial_step(opt, x) != NLOPT_SUCCESS) - RETURN_ERR(NLOPT_OUT_OF_MEMORY, opt, - "failed to allocate initial step"); - } - if (algorithm == NLOPT_LN_NELDERMEAD) - ret=nldrmd_minimize(ni,f,f_data,lb,ub,x,minf,opt->dx,&stop); - else - ret=sbplx_minimize(ni,f,f_data,lb,ub,x,minf,opt->dx,&stop); - if (freedx) { free(opt->dx); opt->dx = NULL; } - return ret; - } - - case NLOPT_AUGLAG: - case NLOPT_AUGLAG_EQ: - case NLOPT_LN_AUGLAG: - case NLOPT_LN_AUGLAG_EQ: - case NLOPT_LD_AUGLAG: - case NLOPT_LD_AUGLAG_EQ: { - nlopt_opt local_opt = opt->local_opt; - nlopt_result ret; - if ((algorithm == NLOPT_AUGLAG || algorithm == NLOPT_AUGLAG_EQ) - && !local_opt) - RETURN_ERR(NLOPT_INVALID_ARGS, opt, - "local optimizer must be specified for AUGLAG"); - if (!local_opt) { /* default */ - local_opt = nlopt_create( - algorithm == NLOPT_LN_AUGLAG || - algorithm == NLOPT_LN_AUGLAG_EQ - ? nlopt_local_search_alg_nonderiv - : nlopt_local_search_alg_deriv, n); - if (!local_opt) RETURN_ERR(NLOPT_FAILURE, opt, - "failed to create local_opt"); - nlopt_set_ftol_rel(local_opt, opt->ftol_rel); - nlopt_set_ftol_abs(local_opt, opt->ftol_abs); - nlopt_set_xtol_rel(local_opt, opt->xtol_rel); - nlopt_set_xtol_abs(local_opt, opt->xtol_abs); - nlopt_set_maxeval(local_opt, nlopt_local_search_maxeval); - } - if (opt->dx) nlopt_set_initial_step(local_opt, opt->dx); - opt->force_stop_child = local_opt; - ret = auglag_minimize(ni, f, f_data, - opt->m, opt->fc, - opt->p, opt->h, - lb, ub, x, minf, &stop, - local_opt, - algorithm == NLOPT_AUGLAG_EQ - || algorithm == NLOPT_LN_AUGLAG_EQ - || algorithm == NLOPT_LD_AUGLAG_EQ); - opt->force_stop_child = NULL; - if (!opt->local_opt) nlopt_destroy(local_opt); - return ret; - } - - case NLOPT_GN_ISRES: - if (!finite_domain(n, lb, ub)) - RETURN_ERR(NLOPT_INVALID_ARGS, opt, - "finite domain required for global algorithm"); - return isres_minimize(ni, f, f_data, - (int) (opt->m), opt->fc, - (int) (opt->p), opt->h, - lb, ub, x, minf, &stop, - (int) POP(0)); - - case NLOPT_GN_ESCH: - if (!finite_domain(n, lb, ub)) - RETURN_ERR(NLOPT_INVALID_ARGS, opt, - "finite domain required for global algorithm"); - return chevolutionarystrategy(n, f, f_data, - lb, ub, x, minf, &stop, - (unsigned) POP(0), - (unsigned) (POP(0)*1.5)); - - case NLOPT_LD_SLSQP: - return nlopt_slsqp(n, f, f_data, - opt->m, opt->fc, - opt->p, opt->h, - lb, ub, x, minf, &stop); - - default: - return NLOPT_INVALID_ARGS; - } - - return NLOPT_SUCCESS; /* never reached */ + if (algorithm == NLOPT_LD_MMA) + ret = mma_minimize(n, f, f_data, opt->m, opt->fc, lb, ub, x, minf, &stop, dual_opt); + else + ret = ccsa_quadratic_minimize(n, f, f_data, opt->m, opt->fc, opt->pre, lb, ub, x, minf, &stop, dual_opt); + nlopt_destroy(dual_opt); + return ret; + } + + case NLOPT_LN_COBYLA: + { + nlopt_result ret; + int freedx = 0; + if (!opt->dx) { + freedx = 1; + if (nlopt_set_default_initial_step(opt, x) != NLOPT_SUCCESS) + RETURN_ERR(NLOPT_OUT_OF_MEMORY, opt, "failed to allocate initial step"); + } + ret = cobyla_minimize(n, f, f_data, opt->m, opt->fc, opt->p, opt->h, lb, ub, x, minf, &stop, opt->dx); + if (freedx) { + free(opt->dx); + opt->dx = NULL; + } + return ret; + } + + case NLOPT_LN_NEWUOA: + { + double step; + if (initial_step(opt, x, &step) != NLOPT_SUCCESS) + RETURN_ERR(NLOPT_OUT_OF_MEMORY, opt, "failed to allocate initial step"); + return newuoa(ni, 2 * n + 1, x, 0, 0, step, &stop, minf, f_noderiv, opt); + } + + case NLOPT_LN_NEWUOA_BOUND: + { + double step; + if (initial_step(opt, x, &step) != NLOPT_SUCCESS) + RETURN_ERR(NLOPT_OUT_OF_MEMORY, opt, "failed to allocate initial step"); + return newuoa(ni, 2 * n + 1, x, lb, ub, step, &stop, minf, f_noderiv, opt); + } + + case NLOPT_LN_BOBYQA: + { + nlopt_result ret; + int freedx = 0; + if (!opt->dx) { + freedx = 1; + if (nlopt_set_default_initial_step(opt, x) != NLOPT_SUCCESS) + RETURN_ERR(NLOPT_OUT_OF_MEMORY, opt, "failed to allocate initial step"); + } + ret = bobyqa(ni, 2 * n + 1, x, lb, ub, opt->dx, &stop, minf, opt->f, opt->f_data); + if (freedx) { + free(opt->dx); + opt->dx = NULL; + } + return ret; + } + + case NLOPT_LN_NELDERMEAD: + case NLOPT_LN_SBPLX: + { + nlopt_result ret; + int freedx = 0; + if (!opt->dx) { + freedx = 1; + if (nlopt_set_default_initial_step(opt, x) != NLOPT_SUCCESS) + RETURN_ERR(NLOPT_OUT_OF_MEMORY, opt, "failed to allocate initial step"); + } + if (algorithm == NLOPT_LN_NELDERMEAD) + ret = nldrmd_minimize(ni, f, f_data, lb, ub, x, minf, opt->dx, &stop); + else + ret = sbplx_minimize(ni, f, f_data, lb, ub, x, minf, opt->dx, &stop); + if (freedx) { + free(opt->dx); + opt->dx = NULL; + } + return ret; + } + + case NLOPT_AUGLAG: + case NLOPT_AUGLAG_EQ: + case NLOPT_LN_AUGLAG: + case NLOPT_LN_AUGLAG_EQ: + case NLOPT_LD_AUGLAG: + case NLOPT_LD_AUGLAG_EQ: + { + nlopt_opt local_opt = opt->local_opt; + nlopt_result ret; + if ((algorithm == NLOPT_AUGLAG || algorithm == NLOPT_AUGLAG_EQ) + && !local_opt) + RETURN_ERR(NLOPT_INVALID_ARGS, opt, "local optimizer must be specified for AUGLAG"); + if (!local_opt) { /* default */ + local_opt = nlopt_create(algorithm == NLOPT_LN_AUGLAG || algorithm == NLOPT_LN_AUGLAG_EQ ? nlopt_local_search_alg_nonderiv : nlopt_local_search_alg_deriv, n); + if (!local_opt) + RETURN_ERR(NLOPT_FAILURE, opt, "failed to create local_opt"); + nlopt_set_ftol_rel(local_opt, opt->ftol_rel); + nlopt_set_ftol_abs(local_opt, opt->ftol_abs); + nlopt_set_xtol_rel(local_opt, opt->xtol_rel); + nlopt_set_xtol_abs(local_opt, opt->xtol_abs); + nlopt_set_maxeval(local_opt, nlopt_local_search_maxeval); + } + if (opt->dx) + nlopt_set_initial_step(local_opt, opt->dx); + opt->force_stop_child = local_opt; + ret = auglag_minimize(ni, f, f_data, + opt->m, opt->fc, + opt->p, opt->h, lb, ub, x, minf, &stop, local_opt, algorithm == NLOPT_AUGLAG_EQ || algorithm == NLOPT_LN_AUGLAG_EQ || algorithm == NLOPT_LD_AUGLAG_EQ); + opt->force_stop_child = NULL; + if (!opt->local_opt) + nlopt_destroy(local_opt); + return ret; + } + + case NLOPT_GN_ISRES: + if (!finite_domain(n, lb, ub)) + RETURN_ERR(NLOPT_INVALID_ARGS, opt, "finite domain required for global algorithm"); + return isres_minimize(ni, f, f_data, (int) (opt->m), opt->fc, (int) (opt->p), opt->h, lb, ub, x, minf, &stop, (int) POP(0)); + + case NLOPT_GN_ESCH: + if (!finite_domain(n, lb, ub)) + RETURN_ERR(NLOPT_INVALID_ARGS, opt, "finite domain required for global algorithm"); + return chevolutionarystrategy(n, f, f_data, lb, ub, x, minf, &stop, (unsigned) POP(0), (unsigned) (POP(0) * 1.5)); + + case NLOPT_LD_SLSQP: + return nlopt_slsqp(n, f, f_data, opt->m, opt->fc, opt->p, opt->h, lb, ub, x, minf, &stop); + + default: + return NLOPT_INVALID_ARGS; + } + + return NLOPT_SUCCESS; /* never reached */ } /*********************************************************************/ typedef struct { - nlopt_func f; - nlopt_precond pre; - void *f_data; + nlopt_func f; + nlopt_precond pre; + void *f_data; } f_max_data; /* wrapper for maximizing: just flip the sign of f and grad */ static double f_max(unsigned n, const double *x, double *grad, void *data) { - f_max_data *d = (f_max_data *) data; - double val = d->f(n, x, grad, d->f_data); - if (grad) { - unsigned i; - for (i = 0; i < n; ++i) - grad[i] = -grad[i]; - } - return -val; + f_max_data *d = (f_max_data *) data; + double val = d->f(n, x, grad, d->f_data); + if (grad) { + unsigned i; + for (i = 0; i < n; ++i) + grad[i] = -grad[i]; + } + return -val; } -static void pre_max(unsigned n, const double *x, const double *v, - double *vpre, void *data) +static void pre_max(unsigned n, const double *x, const double *v, double *vpre, void *data) { - f_max_data *d = (f_max_data *) data; - unsigned i; - d->pre(n, x, v, vpre, d->f_data); - for (i = 0; i < n; ++i) vpre[i] = -vpre[i]; + f_max_data *d = (f_max_data *) data; + unsigned i; + d->pre(n, x, v, vpre, d->f_data); + for (i = 0; i < n; ++i) + vpre[i] = -vpre[i]; } -nlopt_result -NLOPT_STDCALL nlopt_optimize(nlopt_opt opt, double *x, double *opt_f) +nlopt_result NLOPT_STDCALL nlopt_optimize(nlopt_opt opt, double *x, double *opt_f) { - nlopt_func f; void *f_data; nlopt_precond pre; - f_max_data fmd; - int maximize; - nlopt_result ret; - - nlopt_unset_errmsg(opt); - if (!opt || !opt_f || !opt->f) RETURN_ERR(NLOPT_INVALID_ARGS, opt, - "NULL args to nlopt_optimize"); - f = opt->f; f_data = opt->f_data; pre = opt->pre; - - /* for maximizing, just minimize the f_max wrapper, which - flips the sign of everything */ - if ((maximize = opt->maximize)) { - fmd.f = f; fmd.f_data = f_data; fmd.pre = pre; - opt->f = f_max; opt->f_data = &fmd; - if (opt->pre) opt->pre = pre_max; - opt->stopval = -opt->stopval; - opt->maximize = 0; - } - - { /* possibly eliminate lb == ub dimensions for some algorithms */ - nlopt_opt elim_opt = opt; - if (elimdim_wrapcheck(opt)) { - elim_opt = elimdim_create(opt); - if (!elim_opt) { - nlopt_set_errmsg(opt, "failure allocating elim_opt"); - ret = NLOPT_OUT_OF_MEMORY; - goto done; - } - elimdim_shrink(opt->n, x, opt->lb, opt->ub); - } - - ret = nlopt_optimize_(elim_opt, x, opt_f); - - if (elim_opt != opt) { - elimdim_destroy(elim_opt); - elimdim_expand(opt->n, x, opt->lb, opt->ub); - } - } - -done: - if (maximize) { /* restore original signs */ - opt->maximize = maximize; - opt->stopval = -opt->stopval; - opt->f = f; opt->f_data = f_data; opt->pre = pre; - *opt_f = -*opt_f; - } - - return ret; + nlopt_func f; + void *f_data; + nlopt_precond pre; + f_max_data fmd; + int maximize; + nlopt_result ret; + + nlopt_unset_errmsg(opt); + if (!opt || !opt_f || !opt->f) + RETURN_ERR(NLOPT_INVALID_ARGS, opt, "NULL args to nlopt_optimize"); + f = opt->f; + f_data = opt->f_data; + pre = opt->pre; + + /* for maximizing, just minimize the f_max wrapper, which + flips the sign of everything */ + if ((maximize = opt->maximize)) { + fmd.f = f; + fmd.f_data = f_data; + fmd.pre = pre; + opt->f = f_max; + opt->f_data = &fmd; + if (opt->pre) + opt->pre = pre_max; + opt->stopval = -opt->stopval; + opt->maximize = 0; + } + + { /* possibly eliminate lb == ub dimensions for some algorithms */ + nlopt_opt elim_opt = opt; + if (elimdim_wrapcheck(opt)) { + elim_opt = elimdim_create(opt); + if (!elim_opt) { + nlopt_set_errmsg(opt, "failure allocating elim_opt"); + ret = NLOPT_OUT_OF_MEMORY; + goto done; + } + elimdim_shrink(opt->n, x, opt->lb, opt->ub); + } + + ret = nlopt_optimize_(elim_opt, x, opt_f); + + if (elim_opt != opt) { + elimdim_destroy(elim_opt); + elimdim_expand(opt->n, x, opt->lb, opt->ub); + } + } + + done: + if (maximize) { /* restore original signs */ + opt->maximize = maximize; + opt->stopval = -opt->stopval; + opt->f = f; + opt->f_data = f_data; + opt->pre = pre; + *opt_f = -*opt_f; + } + + return ret; } /*********************************************************************/ -nlopt_result nlopt_optimize_limited(nlopt_opt opt, double *x, double *minf, - int maxeval, double maxtime) +nlopt_result nlopt_optimize_limited(nlopt_opt opt, double *x, double *minf, int maxeval, double maxtime) { - int save_maxeval; - double save_maxtime; - nlopt_result ret; + int save_maxeval; + double save_maxtime; + nlopt_result ret; - nlopt_unset_errmsg(opt); + nlopt_unset_errmsg(opt); - if (!opt) RETURN_ERR(NLOPT_INVALID_ARGS, opt, "NULL opt arg"); + if (!opt) + RETURN_ERR(NLOPT_INVALID_ARGS, opt, "NULL opt arg"); - save_maxeval = nlopt_get_maxeval(opt); - save_maxtime = nlopt_get_maxtime(opt); + save_maxeval = nlopt_get_maxeval(opt); + save_maxtime = nlopt_get_maxtime(opt); - /* override opt limits if maxeval and/or maxtime are more stringent */ - if (save_maxeval <= 0 || (maxeval > 0 && maxeval < save_maxeval)) - nlopt_set_maxeval(opt, maxeval); - if (save_maxtime <= 0 || (maxtime > 0 && maxtime < save_maxtime)) - nlopt_set_maxtime(opt, maxtime); + /* override opt limits if maxeval and/or maxtime are more stringent */ + if (save_maxeval <= 0 || (maxeval > 0 && maxeval < save_maxeval)) + nlopt_set_maxeval(opt, maxeval); + if (save_maxtime <= 0 || (maxtime > 0 && maxtime < save_maxtime)) + nlopt_set_maxtime(opt, maxtime); - ret = nlopt_optimize(opt, x, minf); + ret = nlopt_optimize(opt, x, minf); - nlopt_set_maxeval(opt, save_maxeval); - nlopt_set_maxtime(opt, save_maxtime); + nlopt_set_maxeval(opt, save_maxeval); + nlopt_set_maxtime(opt, save_maxtime); - return ret; + return ret; } /*********************************************************************/ diff --git a/src/api/options.c b/src/api/options.c index c60729b..0f9c2ac 100644 --- a/src/api/options.c +++ b/src/api/options.c @@ -35,322 +35,327 @@ void NLOPT_STDCALL nlopt_destroy(nlopt_opt opt) { - if (opt) { - unsigned i; - if (opt->munge_on_destroy) { - nlopt_munge munge = opt->munge_on_destroy; - munge(opt->f_data); - for (i = 0; i < opt->m; ++i) - munge(opt->fc[i].f_data); - for (i = 0; i < opt->p; ++i) - munge(opt->h[i].f_data); - } - for (i = 0; i < opt->m; ++i) - free(opt->fc[i].tol); - for (i = 0; i < opt->p; ++i) - free(opt->h[i].tol); - free(opt->lb); free(opt->ub); - free(opt->xtol_abs); - free(opt->fc); - free(opt->h); - nlopt_destroy(opt->local_opt); - free(opt->dx); - free(opt->work); - free(opt->errmsg); - free(opt); - } + if (opt) { + unsigned i; + if (opt->munge_on_destroy) { + nlopt_munge munge = opt->munge_on_destroy; + munge(opt->f_data); + for (i = 0; i < opt->m; ++i) + munge(opt->fc[i].f_data); + for (i = 0; i < opt->p; ++i) + munge(opt->h[i].f_data); + } + for (i = 0; i < opt->m; ++i) + free(opt->fc[i].tol); + for (i = 0; i < opt->p; ++i) + free(opt->h[i].tol); + free(opt->lb); + free(opt->ub); + free(opt->xtol_abs); + free(opt->fc); + free(opt->h); + nlopt_destroy(opt->local_opt); + free(opt->dx); + free(opt->work); + free(opt->errmsg); + free(opt); + } } nlopt_opt NLOPT_STDCALL nlopt_create(nlopt_algorithm algorithm, unsigned n) { - nlopt_opt opt; - - if (((int) algorithm) < 0 || algorithm >= NLOPT_NUM_ALGORITHMS) - return NULL; - - opt = (nlopt_opt) malloc(sizeof(struct nlopt_opt_s)); - if (opt) { - opt->algorithm = algorithm; - opt->n = n; - opt->f = NULL; opt->f_data = NULL; opt->pre = NULL; - opt->maximize = 0; - opt->munge_on_destroy = opt->munge_on_copy = NULL; - - opt->lb = opt->ub = NULL; - opt->m = opt->m_alloc = 0; - opt->fc = NULL; - opt->p = opt->p_alloc = 0; - opt->h = NULL; - - opt->stopval = -HUGE_VAL; - opt->ftol_rel = opt->ftol_abs = 0; - opt->xtol_rel = 0; opt->xtol_abs = NULL; - opt->maxeval = 0; - opt->numevals = 0; - opt->maxtime = 0; - opt->force_stop = 0; - opt->force_stop_child = NULL; - - opt->local_opt = NULL; - opt->stochastic_population = 0; - opt->vector_storage = 0; - opt->dx = NULL; - opt->work = NULL; - opt->errmsg = NULL; - - if (n > 0) { - opt->lb = (double *) calloc(n, sizeof(double)); - if (!opt->lb) goto oom; - 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); - } - } - - return opt; - -oom: - nlopt_destroy(opt); - return NULL; + nlopt_opt opt; + + if (((int) algorithm) < 0 || algorithm >= NLOPT_NUM_ALGORITHMS) + return NULL; + + opt = (nlopt_opt) malloc(sizeof(struct nlopt_opt_s)); + if (opt) { + opt->algorithm = algorithm; + opt->n = n; + opt->f = NULL; + opt->f_data = NULL; + opt->pre = NULL; + opt->maximize = 0; + opt->munge_on_destroy = opt->munge_on_copy = NULL; + + opt->lb = opt->ub = NULL; + opt->m = opt->m_alloc = 0; + opt->fc = NULL; + opt->p = opt->p_alloc = 0; + opt->h = NULL; + + opt->stopval = -HUGE_VAL; + opt->ftol_rel = opt->ftol_abs = 0; + opt->xtol_rel = 0; + opt->xtol_abs = NULL; + opt->maxeval = 0; + opt->numevals = 0; + opt->maxtime = 0; + opt->force_stop = 0; + opt->force_stop_child = NULL; + + opt->local_opt = NULL; + opt->stochastic_population = 0; + opt->vector_storage = 0; + opt->dx = NULL; + opt->work = NULL; + opt->errmsg = NULL; + + if (n > 0) { + opt->lb = (double *) calloc(n, sizeof(double)); + if (!opt->lb) + goto oom; + 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); + } + } + + return opt; + + oom: + nlopt_destroy(opt); + return NULL; } nlopt_opt NLOPT_STDCALL nlopt_copy(const nlopt_opt opt) { - nlopt_opt nopt = NULL; - unsigned i; - if (opt) { - nlopt_munge munge; - nopt = (nlopt_opt) malloc(sizeof(struct nlopt_opt_s)); - *nopt = *opt; - nopt->lb = nopt->ub = nopt->xtol_abs = NULL; - nopt->fc = nopt->h = NULL; - nopt->m_alloc = nopt->p_alloc = 0; - nopt->local_opt = NULL; - nopt->dx = NULL; - nopt->work = NULL; - nopt->errmsg = NULL; - nopt->force_stop_child = NULL; - - munge = nopt->munge_on_copy; - if (munge && nopt->f_data) - if (!(nopt->f_data = munge(nopt->f_data))) goto oom; - - if (opt->n > 0) { - nopt->lb = (double *) malloc(sizeof(double) * (opt->n)); - if (!opt->lb) goto oom; - 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; - - 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->m) { - nopt->m_alloc = opt->m; - nopt->fc = (nlopt_constraint *) malloc(sizeof(nlopt_constraint) - * (opt->m)); - if (!nopt->fc) goto oom; - memcpy(nopt->fc, opt->fc, sizeof(nlopt_constraint) * (opt->m)); - for (i = 0; i < opt->m; ++i) nopt->fc[i].tol = NULL; - if (munge) - for (i = 0; i < opt->m; ++i) - if (nopt->fc[i].f_data && - !(nopt->fc[i].f_data - = munge(nopt->fc[i].f_data))) - goto oom; - for (i = 0; i < opt->m; ++i) - if (opt->fc[i].tol) { - nopt->fc[i].tol = (double *) malloc(sizeof(double) - * nopt->fc[i].m); - if (!nopt->fc[i].tol) goto oom; - memcpy(nopt->fc[i].tol, opt->fc[i].tol, - sizeof(double) * nopt->fc[i].m); - } - } - - if (opt->p) { - nopt->p_alloc = opt->p; - nopt->h = (nlopt_constraint *) malloc(sizeof(nlopt_constraint) - * (opt->p)); - if (!nopt->h) goto oom; - memcpy(nopt->h, opt->h, sizeof(nlopt_constraint) * (opt->p)); - for (i = 0; i < opt->p; ++i) nopt->h[i].tol = NULL; - if (munge) - for (i = 0; i < opt->p; ++i) - if (nopt->h[i].f_data && - !(nopt->h[i].f_data - = munge(nopt->h[i].f_data))) - goto oom; - for (i = 0; i < opt->p; ++i) - if (opt->h[i].tol) { - nopt->h[i].tol = (double *) malloc(sizeof(double) - * nopt->h[i].m); - if (!nopt->h[i].tol) goto oom; - memcpy(nopt->h[i].tol, opt->h[i].tol, - sizeof(double) * nopt->h[i].m); - } - } - - if (opt->local_opt) { - nopt->local_opt = nlopt_copy(opt->local_opt); - if (!nopt->local_opt) goto oom; - } - - if (opt->dx) { - nopt->dx = (double *) malloc(sizeof(double) * (opt->n)); - if (!nopt->dx) goto oom; - memcpy(nopt->dx, opt->dx, sizeof(double) * (opt->n)); - } - } - return nopt; - -oom: - nopt->munge_on_destroy = NULL; /* better to leak mem than crash */ - nlopt_destroy(nopt); - return NULL; + nlopt_opt nopt = NULL; + unsigned i; + if (opt) { + nlopt_munge munge; + nopt = (nlopt_opt) malloc(sizeof(struct nlopt_opt_s)); + *nopt = *opt; + nopt->lb = nopt->ub = nopt->xtol_abs = NULL; + nopt->fc = nopt->h = NULL; + nopt->m_alloc = nopt->p_alloc = 0; + nopt->local_opt = NULL; + nopt->dx = NULL; + nopt->work = NULL; + nopt->errmsg = NULL; + nopt->force_stop_child = NULL; + + munge = nopt->munge_on_copy; + if (munge && nopt->f_data) + if (!(nopt->f_data = munge(nopt->f_data))) + goto oom; + + if (opt->n > 0) { + nopt->lb = (double *) malloc(sizeof(double) * (opt->n)); + if (!opt->lb) + goto oom; + 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; + + 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->m) { + nopt->m_alloc = opt->m; + nopt->fc = (nlopt_constraint *) malloc(sizeof(nlopt_constraint) + * (opt->m)); + if (!nopt->fc) + goto oom; + memcpy(nopt->fc, opt->fc, sizeof(nlopt_constraint) * (opt->m)); + for (i = 0; i < opt->m; ++i) + nopt->fc[i].tol = NULL; + if (munge) + for (i = 0; i < opt->m; ++i) + if (nopt->fc[i].f_data && !(nopt->fc[i].f_data = munge(nopt->fc[i].f_data))) + goto oom; + for (i = 0; i < opt->m; ++i) + if (opt->fc[i].tol) { + nopt->fc[i].tol = (double *) malloc(sizeof(double) + * nopt->fc[i].m); + if (!nopt->fc[i].tol) + goto oom; + memcpy(nopt->fc[i].tol, opt->fc[i].tol, sizeof(double) * nopt->fc[i].m); + } + } + + if (opt->p) { + nopt->p_alloc = opt->p; + nopt->h = (nlopt_constraint *) malloc(sizeof(nlopt_constraint) + * (opt->p)); + if (!nopt->h) + goto oom; + memcpy(nopt->h, opt->h, sizeof(nlopt_constraint) * (opt->p)); + for (i = 0; i < opt->p; ++i) + nopt->h[i].tol = NULL; + if (munge) + for (i = 0; i < opt->p; ++i) + if (nopt->h[i].f_data && !(nopt->h[i].f_data = munge(nopt->h[i].f_data))) + goto oom; + for (i = 0; i < opt->p; ++i) + if (opt->h[i].tol) { + nopt->h[i].tol = (double *) malloc(sizeof(double) + * nopt->h[i].m); + if (!nopt->h[i].tol) + goto oom; + memcpy(nopt->h[i].tol, opt->h[i].tol, sizeof(double) * nopt->h[i].m); + } + } + + if (opt->local_opt) { + nopt->local_opt = nlopt_copy(opt->local_opt); + if (!nopt->local_opt) + goto oom; + } + + if (opt->dx) { + nopt->dx = (double *) malloc(sizeof(double) * (opt->n)); + if (!nopt->dx) + goto oom; + memcpy(nopt->dx, opt->dx, sizeof(double) * (opt->n)); + } + } + return nopt; + + oom: + nopt->munge_on_destroy = NULL; /* better to leak mem than crash */ + nlopt_destroy(nopt); + return NULL; } /*************************************************************************/ -nlopt_result NLOPT_STDCALL nlopt_set_precond_min_objective(nlopt_opt opt, - nlopt_func f, - nlopt_precond pre, - void *f_data) +nlopt_result NLOPT_STDCALL nlopt_set_precond_min_objective(nlopt_opt opt, nlopt_func f, nlopt_precond pre, void *f_data) { - if (opt) { - nlopt_unset_errmsg(opt); - if (opt->munge_on_destroy) opt->munge_on_destroy(opt->f_data); - opt->f = f; opt->f_data = f_data; opt->pre = pre; - opt->maximize = 0; - if (nlopt_isinf(opt->stopval) && opt->stopval > 0) - opt->stopval = -HUGE_VAL; /* switch default from max to min */ - return NLOPT_SUCCESS; - } - return NLOPT_INVALID_ARGS; + if (opt) { + nlopt_unset_errmsg(opt); + if (opt->munge_on_destroy) + opt->munge_on_destroy(opt->f_data); + opt->f = f; + opt->f_data = f_data; + opt->pre = pre; + opt->maximize = 0; + if (nlopt_isinf(opt->stopval) && opt->stopval > 0) + opt->stopval = -HUGE_VAL; /* switch default from max to min */ + return NLOPT_SUCCESS; + } + return NLOPT_INVALID_ARGS; } -nlopt_result NLOPT_STDCALL nlopt_set_min_objective(nlopt_opt opt, - nlopt_func f, void *f_data) +nlopt_result NLOPT_STDCALL nlopt_set_min_objective(nlopt_opt opt, nlopt_func f, void *f_data) { - return nlopt_set_precond_min_objective(opt, f, NULL, f_data); + return nlopt_set_precond_min_objective(opt, f, NULL, f_data); } -nlopt_result NLOPT_STDCALL nlopt_set_precond_max_objective(nlopt_opt opt, - nlopt_func f, - nlopt_precond pre, - void *f_data) +nlopt_result NLOPT_STDCALL nlopt_set_precond_max_objective(nlopt_opt opt, nlopt_func f, nlopt_precond pre, void *f_data) { - if (opt) { - nlopt_unset_errmsg(opt); - if (opt->munge_on_destroy) opt->munge_on_destroy(opt->f_data); - opt->f = f; opt->f_data = f_data; opt->pre = pre; - opt->maximize = 1; - if (nlopt_isinf(opt->stopval) && opt->stopval < 0) - opt->stopval = +HUGE_VAL; /* switch default from min to max */ - return NLOPT_SUCCESS; - } - return NLOPT_INVALID_ARGS; + if (opt) { + nlopt_unset_errmsg(opt); + if (opt->munge_on_destroy) + opt->munge_on_destroy(opt->f_data); + opt->f = f; + opt->f_data = f_data; + opt->pre = pre; + opt->maximize = 1; + if (nlopt_isinf(opt->stopval) && opt->stopval < 0) + opt->stopval = +HUGE_VAL; /* switch default from min to max */ + return NLOPT_SUCCESS; + } + return NLOPT_INVALID_ARGS; } -nlopt_result NLOPT_STDCALL nlopt_set_max_objective(nlopt_opt opt, - nlopt_func f, void *f_data) +nlopt_result NLOPT_STDCALL nlopt_set_max_objective(nlopt_opt opt, nlopt_func f, void *f_data) { - return nlopt_set_precond_max_objective(opt, f, NULL, f_data); + return nlopt_set_precond_max_objective(opt, f, NULL, f_data); } /*************************************************************************/ -nlopt_result -NLOPT_STDCALL nlopt_set_lower_bounds(nlopt_opt opt, const double *lb) -{ - nlopt_unset_errmsg(opt); - if (opt && (opt->n == 0 || lb)) { - unsigned int i; - if (opt->n > 0) - memcpy(opt->lb, lb, sizeof(double) * (opt->n)); - for (i = 0; i < opt->n; ++i) - if (opt->lb[i] < opt->ub[i] && nlopt_istiny(opt->ub[i] - opt->lb[i])) - opt->lb[i] = opt->ub[i]; - return NLOPT_SUCCESS; - } - return NLOPT_INVALID_ARGS; -} - -nlopt_result -NLOPT_STDCALL nlopt_set_lower_bounds1(nlopt_opt opt, double lb) -{ - nlopt_unset_errmsg(opt); - if (opt) { - unsigned i; - for (i = 0; i < opt->n; ++i) { - opt->lb[i] = lb; - if (opt->lb[i] < opt->ub[i] && nlopt_istiny(opt->ub[i] - opt->lb[i])) - opt->lb[i] = opt->ub[i]; - } - return NLOPT_SUCCESS; - } - return NLOPT_INVALID_ARGS; -} - -nlopt_result -NLOPT_STDCALL nlopt_get_lower_bounds(const nlopt_opt opt, double *lb) -{ - nlopt_unset_errmsg(opt); - if (opt && (opt->n == 0 || lb)) { - memcpy(lb, opt->lb, sizeof(double) * (opt->n)); - return NLOPT_SUCCESS; - } - return NLOPT_INVALID_ARGS; -} - -nlopt_result -NLOPT_STDCALL nlopt_set_upper_bounds(nlopt_opt opt, const double *ub) -{ - nlopt_unset_errmsg(opt); - if (opt && (opt->n == 0 || ub)) { - unsigned int i; - if (opt->n > 0) - memcpy(opt->ub, ub, sizeof(double) * (opt->n)); - for (i = 0; i < opt->n; ++i) - if (opt->lb[i] < opt->ub[i] && nlopt_istiny(opt->ub[i] - opt->lb[i])) - opt->ub[i] = opt->lb[i]; - return NLOPT_SUCCESS; - } - return NLOPT_INVALID_ARGS; -} - -nlopt_result -NLOPT_STDCALL nlopt_set_upper_bounds1(nlopt_opt opt, double ub) -{ - nlopt_unset_errmsg(opt); - if (opt) { - unsigned i; - for (i = 0; i < opt->n; ++i) { - opt->ub[i] = ub; - if (opt->lb[i] < opt->ub[i] && nlopt_istiny(opt->ub[i] - opt->lb[i])) - opt->ub[i] = opt->lb[i]; - } - return NLOPT_SUCCESS; - } - return NLOPT_INVALID_ARGS; -} - -nlopt_result -NLOPT_STDCALL nlopt_get_upper_bounds(const nlopt_opt opt, double *ub) -{ - nlopt_unset_errmsg(opt); - if (opt && (opt->n == 0 || ub)) { - memcpy(ub, opt->ub, sizeof(double) * (opt->n)); - return NLOPT_SUCCESS; - } - return NLOPT_INVALID_ARGS; +nlopt_result NLOPT_STDCALL nlopt_set_lower_bounds(nlopt_opt opt, const double *lb) +{ + nlopt_unset_errmsg(opt); + if (opt && (opt->n == 0 || lb)) { + unsigned int i; + if (opt->n > 0) + memcpy(opt->lb, lb, sizeof(double) * (opt->n)); + for (i = 0; i < opt->n; ++i) + if (opt->lb[i] < opt->ub[i] && nlopt_istiny(opt->ub[i] - opt->lb[i])) + opt->lb[i] = opt->ub[i]; + return NLOPT_SUCCESS; + } + return NLOPT_INVALID_ARGS; +} + +nlopt_result NLOPT_STDCALL nlopt_set_lower_bounds1(nlopt_opt opt, double lb) +{ + nlopt_unset_errmsg(opt); + if (opt) { + unsigned i; + for (i = 0; i < opt->n; ++i) { + opt->lb[i] = lb; + if (opt->lb[i] < opt->ub[i] && nlopt_istiny(opt->ub[i] - opt->lb[i])) + opt->lb[i] = opt->ub[i]; + } + return NLOPT_SUCCESS; + } + return NLOPT_INVALID_ARGS; +} + +nlopt_result NLOPT_STDCALL nlopt_get_lower_bounds(const nlopt_opt opt, double *lb) +{ + nlopt_unset_errmsg(opt); + if (opt && (opt->n == 0 || lb)) { + memcpy(lb, opt->lb, sizeof(double) * (opt->n)); + return NLOPT_SUCCESS; + } + return NLOPT_INVALID_ARGS; +} + +nlopt_result NLOPT_STDCALL nlopt_set_upper_bounds(nlopt_opt opt, const double *ub) +{ + nlopt_unset_errmsg(opt); + if (opt && (opt->n == 0 || ub)) { + unsigned int i; + if (opt->n > 0) + memcpy(opt->ub, ub, sizeof(double) * (opt->n)); + for (i = 0; i < opt->n; ++i) + if (opt->lb[i] < opt->ub[i] && nlopt_istiny(opt->ub[i] - opt->lb[i])) + opt->ub[i] = opt->lb[i]; + return NLOPT_SUCCESS; + } + return NLOPT_INVALID_ARGS; +} + +nlopt_result NLOPT_STDCALL nlopt_set_upper_bounds1(nlopt_opt opt, double ub) +{ + nlopt_unset_errmsg(opt); + if (opt) { + unsigned i; + for (i = 0; i < opt->n; ++i) { + opt->ub[i] = ub; + if (opt->lb[i] < opt->ub[i] && nlopt_istiny(opt->ub[i] - opt->lb[i])) + opt->ub[i] = opt->lb[i]; + } + return NLOPT_SUCCESS; + } + return NLOPT_INVALID_ARGS; +} + +nlopt_result NLOPT_STDCALL nlopt_get_upper_bounds(const nlopt_opt opt, double *ub) +{ + nlopt_unset_errmsg(opt); + if (opt && (opt->n == 0 || ub)) { + memcpy(ub, opt->ub, sizeof(double) * (opt->n)); + return NLOPT_SUCCESS; + } + return NLOPT_INVALID_ARGS; } /*************************************************************************/ @@ -362,211 +367,185 @@ NLOPT_STDCALL nlopt_get_upper_bounds(const nlopt_opt opt, double *ub) (a) == NLOPT_LD_AUGLAG || \ (a) == NLOPT_LD_AUGLAG_EQ) -nlopt_result -NLOPT_STDCALL nlopt_remove_inequality_constraints(nlopt_opt opt) -{ - unsigned i; - nlopt_unset_errmsg(opt); - if (!opt) return NLOPT_INVALID_ARGS; - if (opt->munge_on_destroy) { - nlopt_munge munge = opt->munge_on_destroy; - for (i = 0; i < opt->m; ++i) - munge(opt->fc[i].f_data); - } - for (i = 0; i < opt->m; ++i) - free(opt->fc[i].tol); - free(opt->fc); - opt->fc = NULL; - opt->m = opt->m_alloc = 0; - return NLOPT_SUCCESS; +nlopt_result NLOPT_STDCALL nlopt_remove_inequality_constraints(nlopt_opt opt) +{ + unsigned i; + nlopt_unset_errmsg(opt); + if (!opt) + return NLOPT_INVALID_ARGS; + if (opt->munge_on_destroy) { + nlopt_munge munge = opt->munge_on_destroy; + for (i = 0; i < opt->m; ++i) + munge(opt->fc[i].f_data); + } + for (i = 0; i < opt->m; ++i) + free(opt->fc[i].tol); + free(opt->fc); + opt->fc = NULL; + opt->m = opt->m_alloc = 0; + return NLOPT_SUCCESS; } static nlopt_result add_constraint(nlopt_opt opt, - unsigned *m, unsigned *m_alloc, - nlopt_constraint **c, - unsigned fm, nlopt_func fc, nlopt_mfunc mfc, - nlopt_precond pre, - void *fc_data, - const double *tol) -{ - double *tolcopy; - unsigned i; - - if ((fc && mfc) || (fc && fm != 1) || (!fc && !mfc)) - return NLOPT_INVALID_ARGS; - if (tol) - for (i = 0; i < fm; ++i) if (tol[i] < 0) - return ERR(NLOPT_INVALID_ARGS, opt, "negative constraint tolerance"); - - tolcopy = (double *) malloc(sizeof(double) * fm); - if (fm && !tolcopy) return NLOPT_OUT_OF_MEMORY; - if (tol) - memcpy(tolcopy, tol, sizeof(double) * fm); - else - for (i = 0; i < fm; ++i) tolcopy[i] = 0; - - *m += 1; - if (*m > *m_alloc) { - /* allocate by repeated doubling so that - we end up with O(log m) mallocs rather than O(m). */ - *m_alloc = 2 * (*m); - *c = (nlopt_constraint *) realloc(*c, - sizeof(nlopt_constraint) - * (*m_alloc)); - if (!*c) { - *m_alloc = *m = 0; - free(tolcopy); - return NLOPT_OUT_OF_MEMORY; - } - } - - (*c)[*m - 1].m = fm; - (*c)[*m - 1].f = fc; - (*c)[*m - 1].pre = pre; - (*c)[*m - 1].mf = mfc; - (*c)[*m - 1].f_data = fc_data; - (*c)[*m - 1].tol = tolcopy; - return NLOPT_SUCCESS; -} - -static int inequality_ok(nlopt_algorithm algorithm) { - /* nonlinear constraints are only supported with some algorithms */ - return (algorithm == NLOPT_LD_MMA || algorithm == NLOPT_LD_CCSAQ - || algorithm == NLOPT_LD_SLSQP - || algorithm == NLOPT_LN_COBYLA - || AUGLAG_ALG(algorithm) - || algorithm == NLOPT_GN_ISRES - || algorithm == NLOPT_GN_ORIG_DIRECT - || algorithm == NLOPT_GN_ORIG_DIRECT_L - || algorithm == NLOPT_GN_AGS); -} - -nlopt_result -NLOPT_STDCALL nlopt_add_inequality_mconstraint(nlopt_opt opt, unsigned m, - nlopt_mfunc fc, void *fc_data, - const double *tol) -{ - nlopt_result ret; - nlopt_unset_errmsg(opt); - if (!m) { /* empty constraints are always ok */ - if (opt && opt->munge_on_destroy) opt->munge_on_destroy(fc_data); - return NLOPT_SUCCESS; - } - if (!opt) ret = NLOPT_INVALID_ARGS; - else if (!inequality_ok(opt->algorithm)) - ret = ERR(NLOPT_INVALID_ARGS, opt, "invalid algorithm for constraints"); - else ret = add_constraint(opt, &opt->m, &opt->m_alloc, &opt->fc, - m, NULL, fc, NULL, fc_data, tol); - if (ret < 0 && opt && opt->munge_on_destroy) - opt->munge_on_destroy(fc_data); - return ret; -} - -nlopt_result -NLOPT_STDCALL nlopt_add_precond_inequality_constraint(nlopt_opt opt, - nlopt_func fc, - nlopt_precond pre, - void *fc_data, - double tol) -{ - nlopt_result ret; - nlopt_unset_errmsg(opt); - if (!opt) ret = NLOPT_INVALID_ARGS; - else if (!inequality_ok(opt->algorithm)) - ret = ERR(NLOPT_INVALID_ARGS, opt, "invalid algorithm for constraints"); - else ret = add_constraint(opt, &opt->m, &opt->m_alloc, &opt->fc, - 1, fc, NULL, pre, fc_data, &tol); - if (ret < 0 && opt && opt->munge_on_destroy) - opt->munge_on_destroy(fc_data); - return ret; -} - -nlopt_result -NLOPT_STDCALL nlopt_add_inequality_constraint(nlopt_opt opt, - nlopt_func fc, void *fc_data, - double tol) -{ - return nlopt_add_precond_inequality_constraint(opt, fc, NULL, fc_data, - tol); -} - -nlopt_result -NLOPT_STDCALL nlopt_remove_equality_constraints(nlopt_opt opt) -{ - unsigned i; - nlopt_unset_errmsg(opt); - if (!opt) return NLOPT_INVALID_ARGS; - if (opt->munge_on_destroy) { - nlopt_munge munge = opt->munge_on_destroy; - for (i = 0; i < opt->p; ++i) - munge(opt->h[i].f_data); - } - for (i = 0; i < opt->p; ++i) - free(opt->h[i].tol); - free(opt->h); - opt->h = NULL; - opt->p = opt->p_alloc = 0; - return NLOPT_SUCCESS; -} - -static int equality_ok(nlopt_algorithm algorithm) { - /* equality constraints (h(x) = 0) only via some algorithms */ - return (AUGLAG_ALG(algorithm) - || algorithm == NLOPT_LD_SLSQP - || algorithm == NLOPT_GN_ISRES - || algorithm == NLOPT_LN_COBYLA); -} - -nlopt_result -NLOPT_STDCALL nlopt_add_equality_mconstraint(nlopt_opt opt, unsigned m, - nlopt_mfunc fc, void *fc_data, - const double *tol) -{ - nlopt_result ret; - nlopt_unset_errmsg(opt); - if (!m) { /* empty constraints are always ok */ - if (opt && opt->munge_on_destroy) opt->munge_on_destroy(fc_data); - return NLOPT_SUCCESS; - } - if (!opt) ret = NLOPT_INVALID_ARGS; - else if (!equality_ok(opt->algorithm)) - ret = ERR(NLOPT_INVALID_ARGS, opt, "invalid algorithm for constraints"); - else if (nlopt_count_constraints(opt->p, opt->h) + m > opt->n) - ret = ERR(NLOPT_INVALID_ARGS, opt, "too many equality constraints"); - else ret = add_constraint(opt, &opt->p, &opt->p_alloc, &opt->h, - m, NULL, fc, NULL, fc_data, tol); - if (ret < 0 && opt && opt->munge_on_destroy) - opt->munge_on_destroy(fc_data); - return ret; -} - -nlopt_result -NLOPT_STDCALL nlopt_add_precond_equality_constraint(nlopt_opt opt, - nlopt_func fc, - nlopt_precond pre, - void *fc_data, - double tol) -{ - nlopt_result ret; - nlopt_unset_errmsg(opt); - if (!opt) ret = NLOPT_INVALID_ARGS; - else if (!equality_ok(opt->algorithm)) - ret = ERR(NLOPT_INVALID_ARGS, opt, "invalid algorithm for constraints"); - else if (nlopt_count_constraints(opt->p, opt->h) + 1 > opt->n) - ret = ERR(NLOPT_INVALID_ARGS, opt, "too many equality constraints"); - else ret = add_constraint(opt, &opt->p, &opt->p_alloc, &opt->h, - 1, fc, NULL, pre, fc_data, &tol); - if (ret < 0 && opt && opt->munge_on_destroy) - opt->munge_on_destroy(fc_data); - return ret; -} - -nlopt_result -NLOPT_STDCALL nlopt_add_equality_constraint(nlopt_opt opt, - nlopt_func fc, void *fc_data, - double tol) -{ - return nlopt_add_precond_equality_constraint(opt, fc, NULL, fc_data, tol); + unsigned *m, unsigned *m_alloc, nlopt_constraint ** c, unsigned fm, nlopt_func fc, nlopt_mfunc mfc, nlopt_precond pre, void *fc_data, const double *tol) +{ + double *tolcopy; + unsigned i; + + if ((fc && mfc) || (fc && fm != 1) || (!fc && !mfc)) + return NLOPT_INVALID_ARGS; + if (tol) + for (i = 0; i < fm; ++i) + if (tol[i] < 0) + return ERR(NLOPT_INVALID_ARGS, opt, "negative constraint tolerance"); + + tolcopy = (double *) malloc(sizeof(double) * fm); + if (fm && !tolcopy) + return NLOPT_OUT_OF_MEMORY; + if (tol) + memcpy(tolcopy, tol, sizeof(double) * fm); + else + for (i = 0; i < fm; ++i) + tolcopy[i] = 0; + + *m += 1; + if (*m > *m_alloc) { + /* allocate by repeated doubling so that + we end up with O(log m) mallocs rather than O(m). */ + *m_alloc = 2 * (*m); + *c = (nlopt_constraint *) realloc(*c, sizeof(nlopt_constraint) + * (*m_alloc)); + if (!*c) { + *m_alloc = *m = 0; + free(tolcopy); + return NLOPT_OUT_OF_MEMORY; + } + } + + (*c)[*m - 1].m = fm; + (*c)[*m - 1].f = fc; + (*c)[*m - 1].pre = pre; + (*c)[*m - 1].mf = mfc; + (*c)[*m - 1].f_data = fc_data; + (*c)[*m - 1].tol = tolcopy; + return NLOPT_SUCCESS; +} + +static int inequality_ok(nlopt_algorithm algorithm) +{ + /* nonlinear constraints are only supported with some algorithms */ + return (algorithm == NLOPT_LD_MMA || algorithm == NLOPT_LD_CCSAQ || algorithm == NLOPT_LD_SLSQP || algorithm == NLOPT_LN_COBYLA || AUGLAG_ALG(algorithm) + || algorithm == NLOPT_GN_ISRES || algorithm == NLOPT_GN_ORIG_DIRECT || algorithm == NLOPT_GN_ORIG_DIRECT_L || algorithm == NLOPT_GN_AGS); +} + +nlopt_result NLOPT_STDCALL nlopt_add_inequality_mconstraint(nlopt_opt opt, unsigned m, nlopt_mfunc fc, void *fc_data, const double *tol) +{ + nlopt_result ret; + nlopt_unset_errmsg(opt); + if (!m) { /* empty constraints are always ok */ + if (opt && opt->munge_on_destroy) + opt->munge_on_destroy(fc_data); + return NLOPT_SUCCESS; + } + if (!opt) + ret = NLOPT_INVALID_ARGS; + else if (!inequality_ok(opt->algorithm)) + ret = ERR(NLOPT_INVALID_ARGS, opt, "invalid algorithm for constraints"); + else + ret = add_constraint(opt, &opt->m, &opt->m_alloc, &opt->fc, m, NULL, fc, NULL, fc_data, tol); + if (ret < 0 && opt && opt->munge_on_destroy) + opt->munge_on_destroy(fc_data); + return ret; +} + +nlopt_result NLOPT_STDCALL nlopt_add_precond_inequality_constraint(nlopt_opt opt, nlopt_func fc, nlopt_precond pre, void *fc_data, double tol) +{ + nlopt_result ret; + nlopt_unset_errmsg(opt); + if (!opt) + ret = NLOPT_INVALID_ARGS; + else if (!inequality_ok(opt->algorithm)) + ret = ERR(NLOPT_INVALID_ARGS, opt, "invalid algorithm for constraints"); + else + ret = add_constraint(opt, &opt->m, &opt->m_alloc, &opt->fc, 1, fc, NULL, pre, fc_data, &tol); + if (ret < 0 && opt && opt->munge_on_destroy) + opt->munge_on_destroy(fc_data); + return ret; +} + +nlopt_result NLOPT_STDCALL nlopt_add_inequality_constraint(nlopt_opt opt, nlopt_func fc, void *fc_data, double tol) +{ + return nlopt_add_precond_inequality_constraint(opt, fc, NULL, fc_data, tol); +} + +nlopt_result NLOPT_STDCALL nlopt_remove_equality_constraints(nlopt_opt opt) +{ + unsigned i; + nlopt_unset_errmsg(opt); + if (!opt) + return NLOPT_INVALID_ARGS; + if (opt->munge_on_destroy) { + nlopt_munge munge = opt->munge_on_destroy; + for (i = 0; i < opt->p; ++i) + munge(opt->h[i].f_data); + } + for (i = 0; i < opt->p; ++i) + free(opt->h[i].tol); + free(opt->h); + opt->h = NULL; + opt->p = opt->p_alloc = 0; + return NLOPT_SUCCESS; +} + +static int equality_ok(nlopt_algorithm algorithm) +{ + /* equality constraints (h(x) = 0) only via some algorithms */ + return (AUGLAG_ALG(algorithm) + || algorithm == NLOPT_LD_SLSQP || algorithm == NLOPT_GN_ISRES || algorithm == NLOPT_LN_COBYLA); +} + +nlopt_result NLOPT_STDCALL nlopt_add_equality_mconstraint(nlopt_opt opt, unsigned m, nlopt_mfunc fc, void *fc_data, const double *tol) +{ + nlopt_result ret; + nlopt_unset_errmsg(opt); + if (!m) { /* empty constraints are always ok */ + if (opt && opt->munge_on_destroy) + opt->munge_on_destroy(fc_data); + return NLOPT_SUCCESS; + } + if (!opt) + ret = NLOPT_INVALID_ARGS; + else if (!equality_ok(opt->algorithm)) + ret = ERR(NLOPT_INVALID_ARGS, opt, "invalid algorithm for constraints"); + else if (nlopt_count_constraints(opt->p, opt->h) + m > opt->n) + ret = ERR(NLOPT_INVALID_ARGS, opt, "too many equality constraints"); + else + ret = add_constraint(opt, &opt->p, &opt->p_alloc, &opt->h, m, NULL, fc, NULL, fc_data, tol); + if (ret < 0 && opt && opt->munge_on_destroy) + opt->munge_on_destroy(fc_data); + return ret; +} + +nlopt_result NLOPT_STDCALL nlopt_add_precond_equality_constraint(nlopt_opt opt, nlopt_func fc, nlopt_precond pre, void *fc_data, double tol) +{ + nlopt_result ret; + nlopt_unset_errmsg(opt); + if (!opt) + ret = NLOPT_INVALID_ARGS; + else if (!equality_ok(opt->algorithm)) + ret = ERR(NLOPT_INVALID_ARGS, opt, "invalid algorithm for constraints"); + else if (nlopt_count_constraints(opt->p, opt->h) + 1 > opt->n) + ret = ERR(NLOPT_INVALID_ARGS, opt, "too many equality constraints"); + else + ret = add_constraint(opt, &opt->p, &opt->p_alloc, &opt->h, 1, fc, NULL, pre, fc_data, &tol); + if (ret < 0 && opt && opt->munge_on_destroy) + opt->munge_on_destroy(fc_data); + return ret; +} + +nlopt_result NLOPT_STDCALL nlopt_add_equality_constraint(nlopt_opt opt, nlopt_func fc, void *fc_data, double tol) +{ + return nlopt_add_precond_equality_constraint(opt, fc, NULL, fc_data, tol); } /*************************************************************************/ @@ -592,224 +571,220 @@ NLOPT_STDCALL nlopt_add_equality_constraint(nlopt_opt opt, GETSET(stopval, double, stopval) -GETSET(ftol_rel, double, ftol_rel) -GETSET(ftol_abs, double, ftol_abs) -GETSET(xtol_rel, double, xtol_rel) - -nlopt_result -NLOPT_STDCALL nlopt_set_xtol_abs(nlopt_opt opt, const double *xtol_abs) +GETSET(ftol_rel, double, ftol_rel) GETSET(ftol_abs, double, ftol_abs) GETSET(xtol_rel, double, xtol_rel) + nlopt_result NLOPT_STDCALL nlopt_set_xtol_abs(nlopt_opt opt, const double *xtol_abs) { - if (opt) { - nlopt_unset_errmsg(opt); - memcpy(opt->xtol_abs, xtol_abs, opt->n * sizeof(double)); - return NLOPT_SUCCESS; - } - return NLOPT_INVALID_ARGS; + if (opt) { + nlopt_unset_errmsg(opt); + memcpy(opt->xtol_abs, xtol_abs, opt->n * sizeof(double)); + return NLOPT_SUCCESS; + } + return NLOPT_INVALID_ARGS; } -nlopt_result -NLOPT_STDCALL nlopt_set_xtol_abs1(nlopt_opt opt, double xtol_abs) +nlopt_result NLOPT_STDCALL nlopt_set_xtol_abs1(nlopt_opt opt, double xtol_abs) { - if (opt) { - unsigned i; - nlopt_unset_errmsg(opt); - for (i = 0; i < opt->n; ++i) - opt->xtol_abs[i] = xtol_abs; - return NLOPT_SUCCESS; - } - return NLOPT_INVALID_ARGS; + if (opt) { + unsigned i; + nlopt_unset_errmsg(opt); + for (i = 0; i < opt->n; ++i) + opt->xtol_abs[i] = xtol_abs; + return NLOPT_SUCCESS; + } + return NLOPT_INVALID_ARGS; } -nlopt_result -NLOPT_STDCALL nlopt_get_xtol_abs(const nlopt_opt opt, double *xtol_abs) +nlopt_result NLOPT_STDCALL nlopt_get_xtol_abs(const nlopt_opt opt, double *xtol_abs) { - memcpy(xtol_abs, opt->xtol_abs, opt->n * sizeof(double)); - return NLOPT_SUCCESS; + memcpy(xtol_abs, opt->xtol_abs, opt->n * sizeof(double)); + return NLOPT_SUCCESS; } GETSET(maxeval, int, maxeval) -GET(numevals, int, numevals) - -GETSET(maxtime, double, maxtime) + GET(numevals, int, numevals) + GETSET(maxtime, double, maxtime) /*************************************************************************/ - -nlopt_result -NLOPT_STDCALL nlopt_set_force_stop(nlopt_opt opt, int force_stop) +nlopt_result NLOPT_STDCALL nlopt_set_force_stop(nlopt_opt opt, int force_stop) { - if (opt) { - nlopt_unset_errmsg(opt); - opt->force_stop = force_stop; - if (opt->force_stop_child) - return nlopt_set_force_stop(opt->force_stop_child, force_stop); - return NLOPT_SUCCESS; - } - return NLOPT_INVALID_ARGS; + if (opt) { + nlopt_unset_errmsg(opt); + opt->force_stop = force_stop; + if (opt->force_stop_child) + return nlopt_set_force_stop(opt->force_stop_child, force_stop); + return NLOPT_SUCCESS; + } + return NLOPT_INVALID_ARGS; } GET(force_stop, int, force_stop) -nlopt_result NLOPT_STDCALL nlopt_force_stop(nlopt_opt opt) { - return nlopt_set_force_stop(opt, 1); +nlopt_result NLOPT_STDCALL nlopt_force_stop(nlopt_opt opt) +{ + return nlopt_set_force_stop(opt, 1); } /*************************************************************************/ GET(algorithm, nlopt_algorithm, algorithm) -GET(dimension, unsigned, n) + GET(dimension, unsigned, n) /*************************************************************************/ - -nlopt_result -NLOPT_STDCALL nlopt_set_local_optimizer(nlopt_opt opt, - const nlopt_opt local_opt) -{ - if (opt) { - nlopt_unset_errmsg(opt); - if (local_opt && local_opt->n != opt->n) - return ERR(NLOPT_INVALID_ARGS, opt, "dimension mismatch in local optimizer"); - nlopt_destroy(opt->local_opt); - opt->local_opt = nlopt_copy(local_opt); - if (local_opt) { - if (!opt->local_opt) return NLOPT_OUT_OF_MEMORY; - nlopt_set_lower_bounds(opt->local_opt, opt->lb); - nlopt_set_upper_bounds(opt->local_opt, opt->ub); - nlopt_remove_inequality_constraints(opt->local_opt); - nlopt_remove_equality_constraints(opt->local_opt); - nlopt_set_min_objective(opt->local_opt, NULL, NULL); - nlopt_set_munge(opt->local_opt, NULL, NULL); - opt->local_opt->force_stop = 0; - } - return NLOPT_SUCCESS; - } - return NLOPT_INVALID_ARGS; + nlopt_result NLOPT_STDCALL nlopt_set_local_optimizer(nlopt_opt opt, const nlopt_opt local_opt) +{ + if (opt) { + nlopt_unset_errmsg(opt); + if (local_opt && local_opt->n != opt->n) + return ERR(NLOPT_INVALID_ARGS, opt, "dimension mismatch in local optimizer"); + nlopt_destroy(opt->local_opt); + opt->local_opt = nlopt_copy(local_opt); + if (local_opt) { + if (!opt->local_opt) + return NLOPT_OUT_OF_MEMORY; + nlopt_set_lower_bounds(opt->local_opt, opt->lb); + nlopt_set_upper_bounds(opt->local_opt, opt->ub); + nlopt_remove_inequality_constraints(opt->local_opt); + nlopt_remove_equality_constraints(opt->local_opt); + nlopt_set_min_objective(opt->local_opt, NULL, NULL); + nlopt_set_munge(opt->local_opt, NULL, NULL); + opt->local_opt->force_stop = 0; + } + return NLOPT_SUCCESS; + } + return NLOPT_INVALID_ARGS; } /*************************************************************************/ GETSET(population, unsigned, stochastic_population) -GETSET(vector_storage, unsigned, vector_storage) + GETSET(vector_storage, unsigned, vector_storage) /*************************************************************************/ - nlopt_result NLOPT_STDCALL nlopt_set_initial_step1(nlopt_opt opt, double dx) { - unsigned i; - if (!opt) return NLOPT_INVALID_ARGS; - nlopt_unset_errmsg(opt); - if (dx == 0) return ERR(NLOPT_INVALID_ARGS, opt, "zero step size"); - if (!opt->dx && opt->n > 0) { - opt->dx = (double *) malloc(sizeof(double) * (opt->n)); - if (!opt->dx) return NLOPT_OUT_OF_MEMORY; - } - for (i = 0; i < opt->n; ++i) opt->dx[i] = dx; - return NLOPT_SUCCESS; -} - -nlopt_result -NLOPT_STDCALL nlopt_set_initial_step(nlopt_opt opt, const double *dx) -{ - unsigned i; - if (!opt) return NLOPT_INVALID_ARGS; - nlopt_unset_errmsg(opt); - if (!dx) { - free(opt->dx); opt->dx = NULL; - return NLOPT_SUCCESS; - } - for (i = 0; i < opt->n; ++i) - if (dx[i] == 0) return ERR(NLOPT_INVALID_ARGS, opt, "zero step size"); - if (!opt->dx && nlopt_set_initial_step1(opt, 1) == NLOPT_OUT_OF_MEMORY) - return NLOPT_OUT_OF_MEMORY; - memcpy(opt->dx, dx, sizeof(double) * (opt->n)); - return NLOPT_SUCCESS; -} - -nlopt_result -NLOPT_STDCALL nlopt_get_initial_step(const nlopt_opt opt, const double *x, - double *dx) -{ - if (!opt) return NLOPT_INVALID_ARGS; - nlopt_unset_errmsg(opt); - if (!opt->n) return NLOPT_SUCCESS; - if (!opt->dx) { - nlopt_opt o = (nlopt_opt) opt; /* discard const temporarily */ - nlopt_result ret = nlopt_set_default_initial_step(o, x); - if (ret != NLOPT_SUCCESS) return ret; - memcpy(dx, o->dx, sizeof(double) * (opt->n)); - free(o->dx); o->dx = NULL; /* don't save, since x-dependent */ - } - else - memcpy(dx, opt->dx, sizeof(double) * (opt->n)); - return NLOPT_SUCCESS; -} - -nlopt_result -NLOPT_STDCALL nlopt_set_default_initial_step(nlopt_opt opt, const double *x) -{ - const double *lb, *ub; - unsigned i; - - nlopt_unset_errmsg(opt); - if (!opt || !x) return NLOPT_INVALID_ARGS; - lb = opt->lb; ub = opt->ub; - - if (!opt->dx && nlopt_set_initial_step1(opt, 1) == NLOPT_OUT_OF_MEMORY) - return NLOPT_OUT_OF_MEMORY; - - /* crude heuristics for initial step size of nonderivative algorithms */ - for (i = 0; i < opt->n; ++i) { - double step = HUGE_VAL; - - if (!nlopt_isinf(ub[i]) && !nlopt_isinf(lb[i]) - && (ub[i] - lb[i]) * 0.25 < step && ub[i] > lb[i]) - step = (ub[i] - lb[i]) * 0.25; - if (!nlopt_isinf(ub[i]) - && ub[i] - x[i] < step && ub[i] > x[i]) - step = (ub[i] - x[i]) * 0.75; - if (!nlopt_isinf(lb[i]) - && x[i] - lb[i] < step && x[i] > lb[i]) - step = (x[i] - lb[i]) * 0.75; - - if (nlopt_isinf(step)) { - if (!nlopt_isinf(ub[i]) - && fabs(ub[i] - x[i]) < fabs(step)) - step = (ub[i] - x[i]) * 1.1; - if (!nlopt_isinf(lb[i]) - && fabs(x[i] - lb[i]) < fabs(step)) - step = (x[i] - lb[i]) * 1.1; - } - if (nlopt_isinf(step) || nlopt_istiny(step)) { - step = x[i]; - } - if (nlopt_isinf(step) || step == 0.0) - step = 1; - - opt->dx[i] = step; - } - return NLOPT_SUCCESS; + unsigned i; + if (!opt) + return NLOPT_INVALID_ARGS; + nlopt_unset_errmsg(opt); + if (dx == 0) + return ERR(NLOPT_INVALID_ARGS, opt, "zero step size"); + if (!opt->dx && opt->n > 0) { + opt->dx = (double *) malloc(sizeof(double) * (opt->n)); + if (!opt->dx) + return NLOPT_OUT_OF_MEMORY; + } + for (i = 0; i < opt->n; ++i) + opt->dx[i] = dx; + return NLOPT_SUCCESS; +} + +nlopt_result NLOPT_STDCALL nlopt_set_initial_step(nlopt_opt opt, const double *dx) +{ + unsigned i; + if (!opt) + return NLOPT_INVALID_ARGS; + nlopt_unset_errmsg(opt); + if (!dx) { + free(opt->dx); + opt->dx = NULL; + return NLOPT_SUCCESS; + } + for (i = 0; i < opt->n; ++i) + if (dx[i] == 0) + return ERR(NLOPT_INVALID_ARGS, opt, "zero step size"); + if (!opt->dx && nlopt_set_initial_step1(opt, 1) == NLOPT_OUT_OF_MEMORY) + return NLOPT_OUT_OF_MEMORY; + memcpy(opt->dx, dx, sizeof(double) * (opt->n)); + return NLOPT_SUCCESS; +} + +nlopt_result NLOPT_STDCALL nlopt_get_initial_step(const nlopt_opt opt, const double *x, double *dx) +{ + if (!opt) + return NLOPT_INVALID_ARGS; + nlopt_unset_errmsg(opt); + if (!opt->n) + return NLOPT_SUCCESS; + if (!opt->dx) { + nlopt_opt o = (nlopt_opt) opt; /* discard const temporarily */ + nlopt_result ret = nlopt_set_default_initial_step(o, x); + if (ret != NLOPT_SUCCESS) + return ret; + memcpy(dx, o->dx, sizeof(double) * (opt->n)); + free(o->dx); + o->dx = NULL; /* don't save, since x-dependent */ + } else + memcpy(dx, opt->dx, sizeof(double) * (opt->n)); + return NLOPT_SUCCESS; +} + +nlopt_result NLOPT_STDCALL nlopt_set_default_initial_step(nlopt_opt opt, const double *x) +{ + const double *lb, *ub; + unsigned i; + + nlopt_unset_errmsg(opt); + if (!opt || !x) + return NLOPT_INVALID_ARGS; + lb = opt->lb; + ub = opt->ub; + + if (!opt->dx && nlopt_set_initial_step1(opt, 1) == NLOPT_OUT_OF_MEMORY) + return NLOPT_OUT_OF_MEMORY; + + /* crude heuristics for initial step size of nonderivative algorithms */ + for (i = 0; i < opt->n; ++i) { + double step = HUGE_VAL; + + if (!nlopt_isinf(ub[i]) && !nlopt_isinf(lb[i]) + && (ub[i] - lb[i]) * 0.25 < step && ub[i] > lb[i]) + step = (ub[i] - lb[i]) * 0.25; + if (!nlopt_isinf(ub[i]) + && ub[i] - x[i] < step && ub[i] > x[i]) + step = (ub[i] - x[i]) * 0.75; + if (!nlopt_isinf(lb[i]) + && x[i] - lb[i] < step && x[i] > lb[i]) + step = (x[i] - lb[i]) * 0.75; + + if (nlopt_isinf(step)) { + if (!nlopt_isinf(ub[i]) + && fabs(ub[i] - x[i]) < fabs(step)) + step = (ub[i] - x[i]) * 1.1; + if (!nlopt_isinf(lb[i]) + && fabs(x[i] - lb[i]) < fabs(step)) + step = (x[i] - lb[i]) * 1.1; + } + if (nlopt_isinf(step) || nlopt_istiny(step)) { + step = x[i]; + } + if (nlopt_isinf(step) || step == 0.0) + step = 1; + + opt->dx[i] = step; + } + return NLOPT_SUCCESS; } /*************************************************************************/ -void NLOPT_STDCALL nlopt_set_munge(nlopt_opt opt, - nlopt_munge munge_on_destroy, - nlopt_munge munge_on_copy) { - if (opt) { - opt->munge_on_destroy = munge_on_destroy; - opt->munge_on_copy = munge_on_copy; - } -} - -void NLOPT_STDCALL nlopt_munge_data(nlopt_opt opt, - nlopt_munge2 munge, void *data) { - if (opt && munge) { - unsigned i; - opt->f_data = munge(opt->f_data, data); - for (i = 0; i < opt->m; ++i) - opt->fc[i].f_data = munge(opt->fc[i].f_data, data); - for (i = 0; i < opt->p; ++i) - opt->h[i].f_data = munge(opt->h[i].f_data, data); - } +void NLOPT_STDCALL nlopt_set_munge(nlopt_opt opt, nlopt_munge munge_on_destroy, nlopt_munge munge_on_copy) +{ + if (opt) { + opt->munge_on_destroy = munge_on_destroy; + opt->munge_on_copy = munge_on_copy; + } +} + +void NLOPT_STDCALL nlopt_munge_data(nlopt_opt opt, nlopt_munge2 munge, void *data) +{ + if (opt && munge) { + unsigned i; + opt->f_data = munge(opt->f_data, data); + for (i = 0; i < opt->m; ++i) + opt->fc[i].f_data = munge(opt->fc[i].f_data, data); + for (i = 0; i < opt->p; ++i) + opt->h[i].f_data = munge(opt->h[i].f_data, data); + } } /*************************************************************************/ diff --git a/src/util/nlopt-getopt.c b/src/util/nlopt-getopt.c index 7c00124..d167e02 100644 --- a/src/util/nlopt-getopt.c +++ b/src/util/nlopt-getopt.c @@ -2,11 +2,11 @@ #include #include "nlopt-getopt.h" -int opterr = 1, /* if error message should be printed */ - optind = 1, /* index into parent argv vector */ - optopt, /* character checked for validity */ - optreset; /* reset getopt */ -char *optarg; /* argument associated with option */ +int opterr = 1, /* if error message should be printed */ + optind = 1, /* index into parent argv vector */ + optopt, /* character checked for validity */ + optreset; /* reset getopt */ +char *optarg; /* argument associated with option */ #define BADCH (int)'?' #define BADARG (int)':' @@ -16,25 +16,25 @@ char *optarg; /* argument associated with option */ * getopt -- * Parse argc/argv argument vector. */ -int getopt(int nargc, char * const nargv[], const char *ostr) +int getopt(int nargc, char *const nargv[], const char *ostr) { - static char *place = EMSG; /* option letter processing */ - const char *oli; /* option letter list index */ - if (optreset || !*place) { /* update scanning pointer */ + static char *place = EMSG; /* option letter processing */ + const char *oli; /* option letter list index */ + if (optreset || !*place) { /* update scanning pointer */ optreset = 0; if (optind >= nargc || *(place = nargv[optind]) != '-') { place = EMSG; return (-1); } - if (place[1] && *++place == '-') { /* found "--" */ + if (place[1] && *++place == '-') { /* found "--" */ ++optind; place = EMSG; return (-1); } - } /* option letter okay? */ - if ((optopt = (int)*place++) == (int)':' || !(oli = strchr(ostr, optopt))) { + } /* option letter okay? */ + if ((optopt = (int) *place++) == (int) ':' || !(oli = strchr(ostr, optopt))) { /* if the user didn't specify '-' as an option, assume it means -1. */ - if (optopt == (int)'-') + if (optopt == (int) '-') return (-1); if (!*place) ++optind; @@ -42,26 +42,24 @@ int getopt(int nargc, char * const nargv[], const char *ostr) (void) printf("illegal option -- %c\n", optopt); return (BADCH); } - if (*++oli != ':') { /* don't need argument */ + if (*++oli != ':') { /* don't need argument */ optarg = NULL; if (!*place) ++optind; - } - else { /* need an argument */ - if (*place) /* no white space */ + } else { /* need an argument */ + if (*place) /* no white space */ optarg = place; - else if (nargc <= ++optind) { /* no arg */ + else if (nargc <= ++optind) { /* no arg */ place = EMSG; if (*ostr == ':') return (BADARG); if (opterr) (void) printf("option requires an argument -- %c\n", optopt); return (BADCH); - } - else /* white space */ + } else /* white space */ optarg = nargv[optind]; place = EMSG; ++optind; } - return (optopt); /* dump back option letter */ + return (optopt); /* dump back option letter */ } diff --git a/src/util/nlopt-getopt.h b/src/util/nlopt-getopt.h index 8a125f4..9af5298 100644 --- a/src/util/nlopt-getopt.h +++ b/src/util/nlopt-getopt.h @@ -35,17 +35,15 @@ #define NLOPT_GETOPT_H #ifdef __cplusplus -extern "C" -{ +extern "C" { #endif -extern int opterr, optind, optopt, optreset; -extern char *optarg; + extern int opterr, optind, optopt, optreset; + extern char *optarg; -extern int getopt(int nargc, char * const nargv[], const char *ostr); + extern int getopt(int nargc, char *const nargv[], const char *ostr); #ifdef __cplusplus } #endif - #endif diff --git a/src/util/nlopt-util.h b/src/util/nlopt-util.h index 437cb67..b7f8ab6 100644 --- a/src/util/nlopt-util.h +++ b/src/util/nlopt-util.h @@ -42,108 +42,96 @@ #endif #ifdef __cplusplus -extern "C" -{ -#endif /* __cplusplus */ +extern "C" { +#endif /* __cplusplus */ -int nlopt_isinf(double x); -int nlopt_isfinite(double x); -int nlopt_istiny(double x); -int nlopt_isnan(double x); + int nlopt_isinf(double x); + int nlopt_isfinite(double x); + int nlopt_istiny(double x); + int nlopt_isnan(double x); /* re-entrant qsort */ -extern void nlopt_qsort_r(void *base_, size_t nmemb, size_t size, void *thunk, - int (*compar)(void *, const void *, const void *)); + extern void nlopt_qsort_r(void *base_, size_t nmemb, size_t size, void *thunk, int (*compar) (void *, const void *, const void *)); /* seconds timer */ -extern double nlopt_seconds(void); -extern unsigned long nlopt_time_seed(void); + extern double nlopt_seconds(void); + extern unsigned long nlopt_time_seed(void); /* pseudorandom number generation by Mersenne twister algorithm */ -extern void nlopt_init_genrand(unsigned long s); -extern double nlopt_urand(double a, double b); -extern int nlopt_iurand(int n); -extern double nlopt_nrand(double mean, double stddev); + extern void nlopt_init_genrand(unsigned long s); + extern double nlopt_urand(double a, double b); + extern int nlopt_iurand(int n); + extern double nlopt_nrand(double mean, double stddev); /* Sobol' low-discrepancy-sequence generation */ -typedef struct nlopt_soboldata_s *nlopt_sobol; -extern nlopt_sobol nlopt_sobol_create(unsigned sdim); -extern void nlopt_sobol_destroy(nlopt_sobol s); -extern void nlopt_sobol_next01(nlopt_sobol s, double *x); -extern void nlopt_sobol_next(nlopt_sobol s, double *x, - const double *lb, const double *ub); -extern void nlopt_sobol_skip(nlopt_sobol s, unsigned n, double *x); + typedef struct nlopt_soboldata_s *nlopt_sobol; + extern nlopt_sobol nlopt_sobol_create(unsigned sdim); + extern void nlopt_sobol_destroy(nlopt_sobol s); + extern void nlopt_sobol_next01(nlopt_sobol s, double *x); + extern void nlopt_sobol_next(nlopt_sobol s, double *x, const double *lb, const double *ub); + extern void nlopt_sobol_skip(nlopt_sobol s, unsigned n, double *x); /* stopping criteria */ -typedef struct { - unsigned n; - double minf_max; - double ftol_rel; - double ftol_abs; - double xtol_rel; - const double *xtol_abs; - int *nevals_p, maxeval; - double maxtime, start; - int *force_stop; - char **stop_msg; /* pointer to msg string to update */ -} nlopt_stopping; -extern int nlopt_stop_f(const nlopt_stopping *stop, double f, double oldf); -extern int nlopt_stop_ftol(const nlopt_stopping *stop, double f, double oldf); -extern int nlopt_stop_x(const nlopt_stopping *stop, - const double *x, const double *oldx); -extern int nlopt_stop_dx(const nlopt_stopping *stop, - const double *x, const double *dx); -extern int nlopt_stop_xs(const nlopt_stopping *stop, - const double *xs, const double *oldxs, - const double *scale_min, const double *scale_max); -extern int nlopt_stop_evals(const nlopt_stopping *stop); -extern int nlopt_stop_time_(double start, double maxtime); -extern int nlopt_stop_time(const nlopt_stopping *stop); -extern int nlopt_stop_evalstime(const nlopt_stopping *stop); -extern int nlopt_stop_forced(const nlopt_stopping *stop); + typedef struct { + unsigned n; + double minf_max; + double ftol_rel; + double ftol_abs; + double xtol_rel; + const double *xtol_abs; + int *nevals_p, maxeval; + double maxtime, start; + int *force_stop; + char **stop_msg; /* pointer to msg string to update */ + } nlopt_stopping; + extern int nlopt_stop_f(const nlopt_stopping * stop, double f, double oldf); + extern int nlopt_stop_ftol(const nlopt_stopping * stop, double f, double oldf); + extern int nlopt_stop_x(const nlopt_stopping * stop, const double *x, const double *oldx); + extern int nlopt_stop_dx(const nlopt_stopping * stop, const double *x, const double *dx); + extern int nlopt_stop_xs(const nlopt_stopping * stop, const double *xs, const double *oldxs, const double *scale_min, const double *scale_max); + extern int nlopt_stop_evals(const nlopt_stopping * stop); + extern int nlopt_stop_time_(double start, double maxtime); + extern int nlopt_stop_time(const nlopt_stopping * stop); + extern int nlopt_stop_evalstime(const nlopt_stopping * stop); + extern int nlopt_stop_forced(const nlopt_stopping * stop); /* like vsprintf, but reallocs p to whatever size is needed */ -extern char *nlopt_vsprintf(char *p, const char *format, va_list ap); -extern void nlopt_stop_msg(const nlopt_stopping *s, const char *format, ...) + extern char *nlopt_vsprintf(char *p, const char *format, va_list ap); + extern void nlopt_stop_msg(const nlopt_stopping * s, const char *format, ...) #ifdef __GNUC__ -__attribute__ ((format (printf, 2, 3))) + __attribute__ ((format(printf, 2, 3))) #endif -; + ; /* for local optimizations, temporarily setting eval/time limits */ -extern nlopt_result nlopt_optimize_limited(nlopt_opt opt, - double *x, double *minf, - int maxevals, double maxtime); + extern nlopt_result nlopt_optimize_limited(nlopt_opt opt, double *x, double *minf, int maxevals, double maxtime); /* data structure for nonlinear inequality or equality constraint (f <= 0 or f = 0, respectively). tol (>= 0) is a tolerance that is used for stopping criteria -- the point is considered "feasible" for purposes of stopping if the constraint is violated by at most tol. */ -typedef struct { - unsigned m; /* dimensional of constraint: mf maps R^n -> R^m */ - nlopt_func f; /* one-dimensional constraint, requires m == 1 */ - nlopt_mfunc mf; - nlopt_precond pre; /* preconditioner for f (NULL if none or if mf) */ - void *f_data; - double *tol; -} nlopt_constraint; - -extern unsigned nlopt_count_constraints(unsigned p, const nlopt_constraint *c); -extern unsigned nlopt_max_constraint_dim(unsigned p, const nlopt_constraint *c); -extern void nlopt_eval_constraint(double *result, double *grad, - const nlopt_constraint *c, - unsigned n, const double *x); + typedef struct { + unsigned m; /* dimensional of constraint: mf maps R^n -> R^m */ + nlopt_func f; /* one-dimensional constraint, requires m == 1 */ + nlopt_mfunc mf; + nlopt_precond pre; /* preconditioner for f (NULL if none or if mf) */ + void *f_data; + double *tol; + } nlopt_constraint; + + extern unsigned nlopt_count_constraints(unsigned p, const nlopt_constraint * c); + extern unsigned nlopt_max_constraint_dim(unsigned p, const nlopt_constraint * c); + extern void nlopt_eval_constraint(double *result, double *grad, const nlopt_constraint * c, unsigned n, const double *x); /* rescale.c: */ -double *nlopt_compute_rescaling(unsigned n, const double *dx); -double *nlopt_new_rescaled(unsigned n, const double *s, const double *x); -void nlopt_rescale(unsigned n, const double *s, const double *x, double *xs); -void nlopt_unscale(unsigned n, const double *s, const double *x, double *xs); -void nlopt_reorder_bounds(unsigned n, double *lb, double *ub); + double *nlopt_compute_rescaling(unsigned n, const double *dx); + double *nlopt_new_rescaled(unsigned n, const double *s, const double *x); + void nlopt_rescale(unsigned n, const double *s, const double *x, double *xs); + void nlopt_unscale(unsigned n, const double *s, const double *x, double *xs); + void nlopt_reorder_bounds(unsigned n, double *lb, double *ub); #ifdef __cplusplus -} /* extern "C" */ -#endif /* __cplusplus */ - +} /* extern "C" */ +#endif /* __cplusplus */ #endif diff --git a/src/util/qsort_r.c b/src/util/qsort_r.c index 05098e9..2eb56d5 100644 --- a/src/util/qsort_r.c +++ b/src/util/qsort_r.c @@ -39,72 +39,67 @@ /* swap size bytes between a_ and b_ */ static void swap(void *a_, void *b_, size_t size) { - if (a_ == b_) return; - { - size_t i, nlong = size / sizeof(long); - long *a = (long *) a_, *b = (long *) b_; - for (i = 0; i < nlong; ++i) { - long c = a[i]; - a[i] = b[i]; - b[i] = c; - } - a_ = (void*) (a + nlong); - b_ = (void*) (b + nlong); - } - { - size_t i; - char *a = (char *) a_, *b = (char *) b_; - size = size % sizeof(long); - for (i = 0; i < size; ++i) { - char c = a[i]; - a[i] = b[i]; - b[i] = c; - } - } + if (a_ == b_) + return; + { + size_t i, nlong = size / sizeof(long); + long *a = (long *) a_, *b = (long *) b_; + for (i = 0; i < nlong; ++i) { + long c = a[i]; + a[i] = b[i]; + b[i] = c; + } + a_ = (void *) (a + nlong); + b_ = (void *) (b + nlong); + } + { + size_t i; + char *a = (char *) a_, *b = (char *) b_; + size = size % sizeof(long); + for (i = 0; i < size; ++i) { + char c = a[i]; + a[i] = b[i]; + b[i] = c; + } + } } -#endif /* HAVE_QSORT_R */ +#endif /* HAVE_QSORT_R */ -void nlopt_qsort_r(void *base_, size_t nmemb, size_t size, void *thunk, - int (*compar)(void *, const void *, const void *)) +void nlopt_qsort_r(void *base_, size_t nmemb, size_t size, void *thunk, int (*compar) (void *, const void *, const void *)) { #ifdef HAVE_QSORT_R_damn_it_use_my_own - /* Even if we could detect glibc vs. BSD by appropriate - macrology, there is no way to make the calls compatible - without writing a wrapper for the compar function...screw - this. */ - qsort_r(base_, nmemb, size, thunk, compar); + /* Even if we could detect glibc vs. BSD by appropriate + macrology, there is no way to make the calls compatible + without writing a wrapper for the compar function...screw + this. */ + qsort_r(base_, nmemb, size, thunk, compar); #else - char *base = (char *) base_; - if (nmemb < 10) { /* use O(nmemb^2) algorithm for small enough nmemb */ - size_t i, j; - for (i = 0; i+1 < nmemb; ++i) - for (j = i+1; j < nmemb; ++j) - if (compar(thunk, base+i*size, base+j*size) > 0) - swap(base+i*size, base+j*size, size); - } - else { - size_t i, pivot, npart; - /* pick median of first/middle/last elements as pivot */ - { - const char *a = base, *b = base + (nmemb/2)*size, - *c = base + (nmemb-1)*size; - pivot = compar(thunk,a,b) < 0 - ? (compar(thunk,b,c) < 0 ? nmemb/2 : - (compar(thunk,a,c) < 0 ? nmemb-1 : 0)) - : (compar(thunk,a,c) < 0 ? 0 : - (compar(thunk,b,c) < 0 ? nmemb-1 : nmemb/2)); - } - /* partition array */ - swap(base + pivot*size, base + (nmemb-1) * size, size); - pivot = (nmemb - 1) * size; - for (i = npart = 0; i < nmemb-1; ++i) - if (compar(thunk, base+i*size, base+pivot) <= 0) - swap(base+i*size, base+(npart++)*size, size); - swap(base+npart*size, base+pivot, size); - /* recursive sort of two partitions */ - nlopt_qsort_r(base, npart, size, thunk, compar); - npart++; /* don't need to sort pivot */ - nlopt_qsort_r(base+npart*size, nmemb-npart, size, thunk, compar); - } -#endif /* !HAVE_QSORT_R */ + char *base = (char *) base_; + if (nmemb < 10) { /* use O(nmemb^2) algorithm for small enough nmemb */ + size_t i, j; + for (i = 0; i + 1 < nmemb; ++i) + for (j = i + 1; j < nmemb; ++j) + if (compar(thunk, base + i * size, base + j * size) > 0) + swap(base + i * size, base + j * size, size); + } else { + size_t i, pivot, npart; + /* pick median of first/middle/last elements as pivot */ + { + const char *a = base, *b = base + (nmemb / 2) * size, *c = base + (nmemb - 1) * size; + pivot = compar(thunk, a, b) < 0 ? (compar(thunk, b, c) < 0 ? nmemb / 2 : (compar(thunk, a, c) < 0 ? nmemb - 1 : 0)) + : (compar(thunk, a, c) < 0 ? 0 : (compar(thunk, b, c) < 0 ? nmemb - 1 : nmemb / 2)); + } + /* partition array */ + swap(base + pivot * size, base + (nmemb - 1) * size, size); + pivot = (nmemb - 1) * size; + for (i = npart = 0; i < nmemb - 1; ++i) + if (compar(thunk, base + i * size, base + pivot) <= 0) + swap(base + i * size, base + (npart++) * size, size); + swap(base + npart * size, base + pivot, size); + /* recursive sort of two partitions */ + nlopt_qsort_r(base, npart, size, thunk, compar); + npart++; /* don't need to sort pivot */ + nlopt_qsort_r(base + npart * size, nmemb - npart, size, thunk, compar); + } +#endif /* !HAVE_QSORT_R */ } diff --git a/src/util/redblack.c b/src/util/redblack.c index 267733b..6765c50 100644 --- a/src/util/redblack.c +++ b/src/util/redblack.c @@ -29,402 +29,431 @@ /* it is convenient to use an explicit node for NULL nodes ... we need to be careful never to change this node indirectly via one of our pointers! */ -rb_node nil = {&nil, &nil, &nil, 0, BLACK}; +rb_node nil = { &nil, &nil, &nil, 0, BLACK }; + #define NIL (&nil) -void rb_tree_init(rb_tree *t, rb_compare compare) { - t->compare = compare; - t->root = NIL; - t->N = 0; +void rb_tree_init(rb_tree * t, rb_compare compare) +{ + t->compare = compare; + t->root = NIL; + t->N = 0; } -static void destroy(rb_node *n) +static void destroy(rb_node * n) { - if (n != NIL) { - destroy(n->l); destroy(n->r); - free(n); - } + if (n != NIL) { + destroy(n->l); + destroy(n->r); + free(n); + } } -void rb_tree_destroy(rb_tree *t) +void rb_tree_destroy(rb_tree * t) { - destroy(t->root); - t->root = NIL; + destroy(t->root); + t->root = NIL; } -void rb_tree_destroy_with_keys(rb_tree *t) +void rb_tree_destroy_with_keys(rb_tree * t) { - rb_node *n = rb_tree_min(t); - while (n) { - free(n->k); n->k = NULL; - n = rb_tree_succ(n); - } - rb_tree_destroy(t); + rb_node *n = rb_tree_min(t); + while (n) { + free(n->k); + n->k = NULL; + n = rb_tree_succ(n); + } + rb_tree_destroy(t); } -static void rotate_left(rb_node *p, rb_tree *t) +static void rotate_left(rb_node * p, rb_tree * t) { - rb_node *n = p->r; /* must be non-NIL */ - p->r = n->l; - n->l = p; - if (p->p != NIL) { - if (p == p->p->l) p->p->l = n; - else p->p->r = n; - } - else - t->root = n; - n->p = p->p; - p->p = n; - if (p->r != NIL) p->r->p = p; + rb_node *n = p->r; /* must be non-NIL */ + p->r = n->l; + n->l = p; + if (p->p != NIL) { + if (p == p->p->l) + p->p->l = n; + else + p->p->r = n; + } else + t->root = n; + n->p = p->p; + p->p = n; + if (p->r != NIL) + p->r->p = p; } -static void rotate_right(rb_node *p, rb_tree *t) +static void rotate_right(rb_node * p, rb_tree * t) { - rb_node *n = p->l; /* must be non-NIL */ - p->l = n->r; - n->r = p; - if (p->p != NIL) { - if (p == p->p->l) p->p->l = n; - else p->p->r = n; - } - else - t->root = n; - n->p = p->p; - p->p = n; - if (p->l != NIL) p->l->p = p; + rb_node *n = p->l; /* must be non-NIL */ + p->l = n->r; + n->r = p; + if (p->p != NIL) { + if (p == p->p->l) + p->p->l = n; + else + p->p->r = n; + } else + t->root = n; + n->p = p->p; + p->p = n; + if (p->l != NIL) + p->l->p = p; } -static void insert_node(rb_tree *t, rb_node *n) +static void insert_node(rb_tree * t, rb_node * n) { - rb_compare compare = t->compare; - rb_key k = n->k; - rb_node *p = t->root; - n->c = RED; - n->p = n->l = n->r = NIL; - t->N++; - if (p == NIL) { - t->root = n; - n->c = BLACK; - return; - } - /* insert (RED) node into tree */ - while (1) { - if (compare(k, p->k) <= 0) { /* k <= p->k */ - if (p->l != NIL) - p = p->l; - else { - p->l = n; - n->p = p; - break; - } - } - else { - if (p->r != NIL) - p = p->r; - else { - p->r = n; - n->p = p; - break; - } - } - } - fixtree: - if (n->p->c == RED) { /* red cannot have red child */ - rb_node *u = p == p->p->l ? p->p->r : p->p->l; - if (u != NIL && u->c == RED) { - p->c = u->c = BLACK; - n = p->p; - if ((p = n->p) != NIL) { - n->c = RED; - goto fixtree; - } - } - else { - if (n == p->r && p == p->p->l) { - rotate_left(p, t); - p = n; n = n->l; - } - else if (n == p->l && p == p->p->r) { - rotate_right(p, t); - p = n; n = n->r; - } - p->c = BLACK; - p->p->c = RED; - if (n == p->l && p == p->p->l) - rotate_right(p->p, t); - else if (n == p->r && p == p->p->r) - rotate_left(p->p, t); - } - - } + rb_compare compare = t->compare; + rb_key k = n->k; + rb_node *p = t->root; + n->c = RED; + n->p = n->l = n->r = NIL; + t->N++; + if (p == NIL) { + t->root = n; + n->c = BLACK; + return; + } + /* insert (RED) node into tree */ + while (1) { + if (compare(k, p->k) <= 0) { /* k <= p->k */ + if (p->l != NIL) + p = p->l; + else { + p->l = n; + n->p = p; + break; + } + } else { + if (p->r != NIL) + p = p->r; + else { + p->r = n; + n->p = p; + break; + } + } + } + fixtree: + if (n->p->c == RED) { /* red cannot have red child */ + rb_node *u = p == p->p->l ? p->p->r : p->p->l; + if (u != NIL && u->c == RED) { + p->c = u->c = BLACK; + n = p->p; + if ((p = n->p) != NIL) { + n->c = RED; + goto fixtree; + } + } else { + if (n == p->r && p == p->p->l) { + rotate_left(p, t); + p = n; + n = n->l; + } else if (n == p->l && p == p->p->r) { + rotate_right(p, t); + p = n; + n = n->r; + } + p->c = BLACK; + p->p->c = RED; + if (n == p->l && p == p->p->l) + rotate_right(p->p, t); + else if (n == p->r && p == p->p->r) + rotate_left(p->p, t); + } + + } } -rb_node *rb_tree_insert(rb_tree *t, rb_key k) +rb_node *rb_tree_insert(rb_tree * t, rb_key k) { - rb_node *n = (rb_node *) malloc(sizeof(rb_node)); - if (!n) return NULL; - n->k = k; - insert_node(t, n); - return n; + rb_node *n = (rb_node *) malloc(sizeof(rb_node)); + if (!n) + return NULL; + n->k = k; + insert_node(t, n); + return n; } -static int check_node(rb_node *n, int *nblack, rb_tree *t) +static int check_node(rb_node * n, int *nblack, rb_tree * t) { - int nbl, nbr; - rb_compare compare = t->compare; - if (n == NIL) { *nblack = 0; return 1; } - if (n->r != NIL && n->r->p != n) return 0; - if (n->r != NIL && compare(n->r->k, n->k) < 0) - return 0; - if (n->l != NIL && n->l->p != n) return 0; - if (n->l != NIL && compare(n->l->k, n->k) > 0) - return 0; - if (n->c == RED) { - if (n->r != NIL && n->r->c == RED) return 0; - if (n->l != NIL && n->l->c == RED) return 0; - } - if (!(check_node(n->r, &nbl, t) && check_node(n->l, &nbr, t))) - return 0; - if (nbl != nbr) return 0; - *nblack = nbl + (n->c == BLACK); - return 1; + int nbl, nbr; + rb_compare compare = t->compare; + if (n == NIL) { + *nblack = 0; + return 1; + } + if (n->r != NIL && n->r->p != n) + return 0; + if (n->r != NIL && compare(n->r->k, n->k) < 0) + return 0; + if (n->l != NIL && n->l->p != n) + return 0; + if (n->l != NIL && compare(n->l->k, n->k) > 0) + return 0; + if (n->c == RED) { + if (n->r != NIL && n->r->c == RED) + return 0; + if (n->l != NIL && n->l->c == RED) + return 0; + } + if (!(check_node(n->r, &nbl, t) && check_node(n->l, &nbr, t))) + return 0; + if (nbl != nbr) + return 0; + *nblack = nbl + (n->c == BLACK); + return 1; } -int rb_tree_check(rb_tree *t) + +int rb_tree_check(rb_tree * t) { - int nblack; - if (nil.c != BLACK) return 0; - if (nil.p != NIL || nil.r != NIL || nil.l != NIL) return 0; - if (t->root == NIL) return 1; - if (t->root->c != BLACK) return 0; - return check_node(t->root, &nblack, t); + int nblack; + if (nil.c != BLACK) + return 0; + if (nil.p != NIL || nil.r != NIL || nil.l != NIL) + return 0; + if (t->root == NIL) + return 1; + if (t->root->c != BLACK) + return 0; + return check_node(t->root, &nblack, t); } -rb_node *rb_tree_find(rb_tree *t, rb_key k) +rb_node *rb_tree_find(rb_tree * t, rb_key k) { - rb_compare compare = t->compare; - rb_node *p = t->root; - while (p != NIL) { - int comp = compare(k, p->k); - if (!comp) return p; - p = comp <= 0 ? p->l : p->r; - } - return NULL; + rb_compare compare = t->compare; + rb_node *p = t->root; + while (p != NIL) { + int comp = compare(k, p->k); + if (!comp) + return p; + p = comp <= 0 ? p->l : p->r; + } + return NULL; } /* find greatest point in subtree p that is <= k */ -static rb_node *find_le(rb_node *p, rb_key k, rb_tree *t) +static rb_node *find_le(rb_node * p, rb_key k, rb_tree * t) { - rb_compare compare = t->compare; - while (p != NIL) { - if (compare(p->k, k) <= 0) { /* p->k <= k */ - rb_node *r = find_le(p->r, k, t); - if (r) return r; - else return p; - } - else /* p->k > k */ - p = p->l; - } - return NULL; /* k < everything in subtree */ + rb_compare compare = t->compare; + while (p != NIL) { + if (compare(p->k, k) <= 0) { /* p->k <= k */ + rb_node *r = find_le(p->r, k, t); + if (r) + return r; + else + return p; + } else /* p->k > k */ + p = p->l; + } + return NULL; /* k < everything in subtree */ } /* find greatest point in t <= k */ -rb_node *rb_tree_find_le(rb_tree *t, rb_key k) +rb_node *rb_tree_find_le(rb_tree * t, rb_key k) { - return find_le(t->root, k, t); + return find_le(t->root, k, t); } /* find greatest point in subtree p that is < k */ -static rb_node *find_lt(rb_node *p, rb_key k, rb_tree *t) +static rb_node *find_lt(rb_node * p, rb_key k, rb_tree * t) { - rb_compare compare = t->compare; - while (p != NIL) { - if (compare(p->k, k) < 0) { /* p->k < k */ - rb_node *r = find_lt(p->r, k, t); - if (r) return r; - else return p; - } - else /* p->k >= k */ - p = p->l; - } - return NULL; /* k <= everything in subtree */ + rb_compare compare = t->compare; + while (p != NIL) { + if (compare(p->k, k) < 0) { /* p->k < k */ + rb_node *r = find_lt(p->r, k, t); + if (r) + return r; + else + return p; + } else /* p->k >= k */ + p = p->l; + } + return NULL; /* k <= everything in subtree */ } /* find greatest point in t < k */ -rb_node *rb_tree_find_lt(rb_tree *t, rb_key k) +rb_node *rb_tree_find_lt(rb_tree * t, rb_key k) { - return find_lt(t->root, k, t); + return find_lt(t->root, k, t); } /* find least point in subtree p that is > k */ -static rb_node *find_gt(rb_node *p, rb_key k, rb_tree *t) +static rb_node *find_gt(rb_node * p, rb_key k, rb_tree * t) { - rb_compare compare = t->compare; - while (p != NIL) { - if (compare(p->k, k) > 0) { /* p->k > k */ - rb_node *l = find_gt(p->l, k, t); - if (l) return l; - else return p; - } - else /* p->k <= k */ - p = p->r; - } - return NULL; /* k >= everything in subtree */ + rb_compare compare = t->compare; + while (p != NIL) { + if (compare(p->k, k) > 0) { /* p->k > k */ + rb_node *l = find_gt(p->l, k, t); + if (l) + return l; + else + return p; + } else /* p->k <= k */ + p = p->r; + } + return NULL; /* k >= everything in subtree */ } /* find least point in t > k */ -rb_node *rb_tree_find_gt(rb_tree *t, rb_key k) +rb_node *rb_tree_find_gt(rb_tree * t, rb_key k) { - return find_gt(t->root, k, t); + return find_gt(t->root, k, t); } -rb_node *rb_tree_min(rb_tree *t) +rb_node *rb_tree_min(rb_tree * t) { - rb_node *n = t->root; - while (n != NIL && n->l != NIL) - n = n->l; - return(n == NIL ? NULL : n); + rb_node *n = t->root; + while (n != NIL && n->l != NIL) + n = n->l; + return (n == NIL ? NULL : n); } -rb_node *rb_tree_max(rb_tree *t) +rb_node *rb_tree_max(rb_tree * t) { - rb_node *n = t->root; - while (n != NIL && n->r != NIL) - n = n->r; - return(n == NIL ? NULL : n); + rb_node *n = t->root; + while (n != NIL && n->r != NIL) + n = n->r; + return (n == NIL ? NULL : n); } -rb_node *rb_tree_succ(rb_node *n) +rb_node *rb_tree_succ(rb_node * n) { - if (!n) return NULL; - if (n->r == NIL) { - rb_node *prev; - do { - prev = n; - n = n->p; - } while (prev == n->r && n != NIL); - return n == NIL ? NULL : n; - } - else { - n = n->r; - while (n->l != NIL) - n = n->l; - return n; - } + if (!n) + return NULL; + if (n->r == NIL) { + rb_node *prev; + do { + prev = n; + n = n->p; + } while (prev == n->r && n != NIL); + return n == NIL ? NULL : n; + } else { + n = n->r; + while (n->l != NIL) + n = n->l; + return n; + } } -rb_node *rb_tree_pred(rb_node *n) +rb_node *rb_tree_pred(rb_node * n) { - if (!n) return NULL; - if (n->l == NIL) { - rb_node *prev; - do { - prev = n; - n = n->p; - } while (prev == n->l && n != NIL); - return n == NIL ? NULL : n; - } - else { - n = n->l; - while (n->r != NIL) - n = n->r; - return n; - } + if (!n) + return NULL; + if (n->l == NIL) { + rb_node *prev; + do { + prev = n; + n = n->p; + } while (prev == n->l && n != NIL); + return n == NIL ? NULL : n; + } else { + n = n->l; + while (n->r != NIL) + n = n->r; + return n; + } } -rb_node *rb_tree_remove(rb_tree *t, rb_node *n) +rb_node *rb_tree_remove(rb_tree * t, rb_node * n) { - rb_key k = n->k; - rb_node *m, *mp; - if (n->l != NIL && n->r != NIL) { - rb_node *lmax = n->l; - while (lmax->r != NIL) lmax = lmax->r; - n->k = lmax->k; - n = lmax; - } - m = n->l != NIL ? n->l : n->r; - if (n->p != NIL) { - if (n->p->r == n) n->p->r = m; - else n->p->l = m; - } - else - t->root = m; - mp = n->p; - if (m != NIL) m->p = mp; - if (n->c == BLACK) { - if (m->c == RED) - m->c = BLACK; - else { - deleteblack: - if (mp != NIL) { - rb_node *s = m == mp->l ? mp->r : mp->l; - if (s->c == RED) { - mp->c = RED; - s->c = BLACK; - if (m == mp->l) rotate_left(mp, t); - else rotate_right(mp, t); - s = m == mp->l ? mp->r : mp->l; - } - if (mp->c == BLACK && s->c == BLACK - && s->l->c == BLACK && s->r->c == BLACK) { - if (s != NIL) s->c = RED; - m = mp; mp = m->p; - goto deleteblack; - } - else if (mp->c == RED && s->c == BLACK && - s->l->c == BLACK && s->r->c == BLACK) { - if (s != NIL) s->c = RED; - mp->c = BLACK; - } - else { - if (m == mp->l && s->c == BLACK && - s->l->c == RED && s->r->c == BLACK) { - s->c = RED; - s->l->c = BLACK; - rotate_right(s, t); - s = m == mp->l ? mp->r : mp->l; - } - else if (m == mp->r && s->c == BLACK && - s->r->c == RED && s->l->c == BLACK) { - s->c = RED; - s->r->c = BLACK; - rotate_left(s, t); - s = m == mp->l ? mp->r : mp->l; - } - s->c = mp->c; - mp->c = BLACK; - if (m == mp->l) { - s->r->c = BLACK; - rotate_left(mp, t); - } - else { - s->l->c = BLACK; - rotate_right(mp, t); - } - } - } - } - } - t->N--; - n->k = k; /* n may have changed during remove */ - return n; /* the node that was deleted may be different from initial n */ + rb_key k = n->k; + rb_node *m, *mp; + if (n->l != NIL && n->r != NIL) { + rb_node *lmax = n->l; + while (lmax->r != NIL) + lmax = lmax->r; + n->k = lmax->k; + n = lmax; + } + m = n->l != NIL ? n->l : n->r; + if (n->p != NIL) { + if (n->p->r == n) + n->p->r = m; + else + n->p->l = m; + } else + t->root = m; + mp = n->p; + if (m != NIL) + m->p = mp; + if (n->c == BLACK) { + if (m->c == RED) + m->c = BLACK; + else { + deleteblack: + if (mp != NIL) { + rb_node *s = m == mp->l ? mp->r : mp->l; + if (s->c == RED) { + mp->c = RED; + s->c = BLACK; + if (m == mp->l) + rotate_left(mp, t); + else + rotate_right(mp, t); + s = m == mp->l ? mp->r : mp->l; + } + if (mp->c == BLACK && s->c == BLACK && s->l->c == BLACK && s->r->c == BLACK) { + if (s != NIL) + s->c = RED; + m = mp; + mp = m->p; + goto deleteblack; + } else if (mp->c == RED && s->c == BLACK && s->l->c == BLACK && s->r->c == BLACK) { + if (s != NIL) + s->c = RED; + mp->c = BLACK; + } else { + if (m == mp->l && s->c == BLACK && s->l->c == RED && s->r->c == BLACK) { + s->c = RED; + s->l->c = BLACK; + rotate_right(s, t); + s = m == mp->l ? mp->r : mp->l; + } else if (m == mp->r && s->c == BLACK && s->r->c == RED && s->l->c == BLACK) { + s->c = RED; + s->r->c = BLACK; + rotate_left(s, t); + s = m == mp->l ? mp->r : mp->l; + } + s->c = mp->c; + mp->c = BLACK; + if (m == mp->l) { + s->r->c = BLACK; + rotate_left(mp, t); + } else { + s->l->c = BLACK; + rotate_right(mp, t); + } + } + } + } + } + t->N--; + n->k = k; /* n may have changed during remove */ + return n; /* the node that was deleted may be different from initial n */ } -rb_node *rb_tree_resort(rb_tree *t, rb_node *n) +rb_node *rb_tree_resort(rb_tree * t, rb_node * n) { - n = rb_tree_remove(t, n); - insert_node(t, n); - return n; + n = rb_tree_remove(t, n); + insert_node(t, n); + return n; } /* shift all key pointers by kshift ... this is useful when the keys are pointers into another array, that has been resized with realloc */ -static void shift_keys(rb_node *n, ptrdiff_t kshift) /* assumes n != NIL */ -{ - n->k += kshift; - if (n->l != NIL) shift_keys(n->l, kshift); - if (n->r != NIL) shift_keys(n->r, kshift); +static void shift_keys(rb_node * n, ptrdiff_t kshift) +{ /* assumes n != NIL */ + n->k += kshift; + if (n->l != NIL) + shift_keys(n->l, kshift); + if (n->r != NIL) + shift_keys(n->r, kshift); } -void rb_tree_shift_keys(rb_tree *t, ptrdiff_t kshift) + +void rb_tree_shift_keys(rb_tree * t, ptrdiff_t kshift) { - if (t->root != NIL) shift_keys(t->root, kshift); + if (t->root != NIL) + shift_keys(t->root, kshift); } diff --git a/src/util/redblack.h b/src/util/redblack.h index 01d585c..f5a5fc6 100644 --- a/src/util/redblack.h +++ b/src/util/redblack.h @@ -23,55 +23,53 @@ #ifndef REDBLACK_H #define REDBLACK_H -#include /* for ptrdiff_t */ +#include /* for ptrdiff_t */ #ifdef __cplusplus -extern "C" -{ -#endif /* __cplusplus */ +extern "C" { +#endif /* __cplusplus */ -typedef double *rb_key; /* key type ... double* is convenient for us, - but of course this could be cast to anything - desired (although void* would look more generic) */ + typedef double *rb_key; /* key type ... double* is convenient for us, + but of course this could be cast to anything + desired (although void* would look more generic) */ -typedef enum { RED, BLACK } rb_color; -typedef struct rb_node_s { - struct rb_node_s *p, *r, *l; /* parent, right, left */ - rb_key k; /* key (and data) */ - rb_color c; -} rb_node; + typedef enum { RED, BLACK } rb_color; + typedef struct rb_node_s { + struct rb_node_s *p, *r, *l; /* parent, right, left */ + rb_key k; /* key (and data) */ + rb_color c; + } rb_node; -typedef int (*rb_compare)(rb_key k1, rb_key k2); + typedef int (*rb_compare) (rb_key k1, rb_key k2); -typedef struct { - rb_compare compare; - rb_node *root; - int N; /* number of nodes */ -} rb_tree; + typedef struct { + rb_compare compare; + rb_node *root; + int N; /* number of nodes */ + } rb_tree; -extern void rb_tree_init(rb_tree *t, rb_compare compare); -extern void rb_tree_destroy(rb_tree *t); -extern void rb_tree_destroy_with_keys(rb_tree *t); -extern rb_node *rb_tree_insert(rb_tree *t, rb_key k); -extern int rb_tree_check(rb_tree *t); -extern rb_node *rb_tree_find(rb_tree *t, rb_key k); -extern rb_node *rb_tree_find_le(rb_tree *t, rb_key k); -extern rb_node *rb_tree_find_lt(rb_tree *t, rb_key k); -extern rb_node *rb_tree_find_gt(rb_tree *t, rb_key k); -extern rb_node *rb_tree_resort(rb_tree *t, rb_node *n); -extern rb_node *rb_tree_min(rb_tree *t); -extern rb_node *rb_tree_max(rb_tree *t); -extern rb_node *rb_tree_succ(rb_node *n); -extern rb_node *rb_tree_pred(rb_node *n); -extern void rb_tree_shift_keys(rb_tree *t, ptrdiff_t kshift); + extern void rb_tree_init(rb_tree * t, rb_compare compare); + extern void rb_tree_destroy(rb_tree * t); + extern void rb_tree_destroy_with_keys(rb_tree * t); + extern rb_node *rb_tree_insert(rb_tree * t, rb_key k); + extern int rb_tree_check(rb_tree * t); + extern rb_node *rb_tree_find(rb_tree * t, rb_key k); + extern rb_node *rb_tree_find_le(rb_tree * t, rb_key k); + extern rb_node *rb_tree_find_lt(rb_tree * t, rb_key k); + extern rb_node *rb_tree_find_gt(rb_tree * t, rb_key k); + extern rb_node *rb_tree_resort(rb_tree * t, rb_node * n); + extern rb_node *rb_tree_min(rb_tree * t); + extern rb_node *rb_tree_max(rb_tree * t); + extern rb_node *rb_tree_succ(rb_node * n); + extern rb_node *rb_tree_pred(rb_node * n); + extern void rb_tree_shift_keys(rb_tree * t, ptrdiff_t kshift); /* To change a key, use rb_tree_find+resort. Removing a node currently wastes memory unless you change the allocation scheme in redblack.c */ -extern rb_node *rb_tree_remove(rb_tree *t, rb_node *n); + extern rb_node *rb_tree_remove(rb_tree * t, rb_node * n); #ifdef __cplusplus -} /* extern "C" */ -#endif /* __cplusplus */ - +} /* extern "C" */ +#endif /* __cplusplus */ #endif diff --git a/src/util/redblack_test.c b/src/util/redblack_test.c index beed5b2..9ac8b7c 100644 --- a/src/util/redblack_test.c +++ b/src/util/redblack_test.c @@ -35,187 +35,187 @@ static int comp(rb_key k1, rb_key k2) { - if (*k1 < *k2) return -1; - if (*k1 > *k2) return +1; - return 0; + if (*k1 < *k2) + return -1; + if (*k1 > *k2) + return +1; + return 0; } int main(int argc, char **argv) { - int N, M; - int *k; - double kd; - rb_tree t; - rb_node *n; - int i, j; - - if (argc < 2) { - fprintf(stderr, "Usage: redblack_test Ntest [rand seed]\n"); - return 1; - } - - N = atoi(argv[1]); - k = (int *) malloc(N * sizeof(int)); - rb_tree_init(&t, comp); - - srand((unsigned) (argc > 2 ? atoi(argv[2]) : time(NULL))); - for (i = 0; i < N; ++i) { - double *newk = (double *) malloc(sizeof(double)); - *newk = (k[i] = rand() % N); - if (!rb_tree_insert(&t, newk)) { - fprintf(stderr, "error in rb_tree_insert\n"); - return 1; - } - if (!rb_tree_check(&t)) { - fprintf(stderr, "rb_tree_check_failed after insert!\n"); - return 1; - } - } - - if (t.N != N) { - fprintf(stderr, "incorrect N (%d) in tree (vs. %d)\n", t.N, N); - return 1; - } - - for (i = 0; i < N; ++i) { - kd = k[i]; - if (!rb_tree_find(&t, &kd)) { - fprintf(stderr, "rb_tree_find lost %d!\n", k[i]); - return 1; - } - } - - n = rb_tree_min(&t); - for (i = 0; i < N; ++i) { - if (!n) { - fprintf(stderr, "not enough successors %d\n!", i); - return 1; - } - printf("%d: %g\n", i, n->k[0]); - n = rb_tree_succ(n); - } - if (n) { - fprintf(stderr, "too many successors!\n"); - return 1; - } - - n = rb_tree_max(&t); - for (i = 0; i < N; ++i) { - if (!n) { - fprintf(stderr, "not enough predecessors %d\n!", i); - return 1; - } - printf("%d: %g\n", i, n->k[0]); - n = rb_tree_pred(n); - } - if (n) { - fprintf(stderr, "too many predecessors!\n"); - return 1; - } - - for (M = N; M > 0; --M) { - int knew = rand() % N; /* random new key */ - j = rand() % M; /* random original key to replace */ - for (i = 0; i < N; ++i) - if (k[i] >= 0) - if (j-- == 0) - break; - if (i >= N) abort(); - kd = k[i]; - if (!(n = rb_tree_find(&t, &kd))) { - fprintf(stderr, "rb_tree_find lost %d!\n", k[i]); - return 1; - } - n->k[0] = knew; - if (!rb_tree_resort(&t, n)) { - fprintf(stderr, "error in rb_tree_resort\n"); - return 1; - } - if (!rb_tree_check(&t)) { - fprintf(stderr, "rb_tree_check_failed after change %d!\n", - N - M + 1); - return 1; - } - k[i] = -1 - knew; - } - - if (t.N != N) { - fprintf(stderr, "incorrect N (%d) in tree (vs. %d)\n", t.N, N); - return 1; - } - - for (i = 0; i < N; ++i) - k[i] = -1 - k[i]; /* undo negation above */ - - for (i = 0; i < N; ++i) { - rb_node *le, *gt; - double lek, gtk; - kd = 0.01 * (rand() % (N * 150) - N*25); - le = rb_tree_find_le(&t, &kd); - gt = rb_tree_find_gt(&t, &kd); - n = rb_tree_min(&t); - lek = le ? le->k[0] : -HUGE_VAL; - gtk = gt ? gt->k[0] : +HUGE_VAL; - printf("%g <= %g < %g\n", lek, kd, gtk); - if (n->k[0] > kd) { - if (le) { - fprintf(stderr, "found invalid le %g for %g\n", lek, kd); - return 1; - } - if (gt != n) { - fprintf(stderr, "gt is not first node for k=%g\n", kd); - return 1; - } - } - else { - rb_node *succ = n; - do { - n = succ; - succ = rb_tree_succ(n); - } while (succ && succ->k[0] <= kd); - if (n != le) { - fprintf(stderr, - "rb_tree_find_le gave wrong result for k=%g\n",kd); - return 1; - } - if (succ != gt) { - fprintf(stderr, - "rb_tree_find_gt gave wrong result for k=%g\n",kd); - return 1; - } - } - } - - for (M = N; M > 0; --M) { - j = rand() % M; - for (i = 0; i < N; ++i) - if (k[i] >= 0) - if (j-- == 0) - break; - if (i >= N) abort(); - kd = k[i]; - if (!(n = rb_tree_find(&t, &kd))) { - fprintf(stderr, "rb_tree_find lost %d!\n", k[i]); - return 1; - } - n = rb_tree_remove(&t, n); - free(n->k); - free(n); - if (!rb_tree_check(&t)) { - fprintf(stderr, "rb_tree_check_failed after remove!\n"); - return 1; - } - k[i] = -1 - k[i]; - } - - if (t.N != 0) { - fprintf(stderr, "nonzero N (%d) in tree at end\n", t.N); - return 1; - } - - rb_tree_destroy(&t); - free(k); - - printf("SUCCESS.\n"); - return 0; + int N, M; + int *k; + double kd; + rb_tree t; + rb_node *n; + int i, j; + + if (argc < 2) { + fprintf(stderr, "Usage: redblack_test Ntest [rand seed]\n"); + return 1; + } + + N = atoi(argv[1]); + k = (int *) malloc(N * sizeof(int)); + rb_tree_init(&t, comp); + + srand((unsigned) (argc > 2 ? atoi(argv[2]) : time(NULL))); + for (i = 0; i < N; ++i) { + double *newk = (double *) malloc(sizeof(double)); + *newk = (k[i] = rand() % N); + if (!rb_tree_insert(&t, newk)) { + fprintf(stderr, "error in rb_tree_insert\n"); + return 1; + } + if (!rb_tree_check(&t)) { + fprintf(stderr, "rb_tree_check_failed after insert!\n"); + return 1; + } + } + + if (t.N != N) { + fprintf(stderr, "incorrect N (%d) in tree (vs. %d)\n", t.N, N); + return 1; + } + + for (i = 0; i < N; ++i) { + kd = k[i]; + if (!rb_tree_find(&t, &kd)) { + fprintf(stderr, "rb_tree_find lost %d!\n", k[i]); + return 1; + } + } + + n = rb_tree_min(&t); + for (i = 0; i < N; ++i) { + if (!n) { + fprintf(stderr, "not enough successors %d\n!", i); + return 1; + } + printf("%d: %g\n", i, n->k[0]); + n = rb_tree_succ(n); + } + if (n) { + fprintf(stderr, "too many successors!\n"); + return 1; + } + + n = rb_tree_max(&t); + for (i = 0; i < N; ++i) { + if (!n) { + fprintf(stderr, "not enough predecessors %d\n!", i); + return 1; + } + printf("%d: %g\n", i, n->k[0]); + n = rb_tree_pred(n); + } + if (n) { + fprintf(stderr, "too many predecessors!\n"); + return 1; + } + + for (M = N; M > 0; --M) { + int knew = rand() % N; /* random new key */ + j = rand() % M; /* random original key to replace */ + for (i = 0; i < N; ++i) + if (k[i] >= 0) + if (j-- == 0) + break; + if (i >= N) + abort(); + kd = k[i]; + if (!(n = rb_tree_find(&t, &kd))) { + fprintf(stderr, "rb_tree_find lost %d!\n", k[i]); + return 1; + } + n->k[0] = knew; + if (!rb_tree_resort(&t, n)) { + fprintf(stderr, "error in rb_tree_resort\n"); + return 1; + } + if (!rb_tree_check(&t)) { + fprintf(stderr, "rb_tree_check_failed after change %d!\n", N - M + 1); + return 1; + } + k[i] = -1 - knew; + } + + if (t.N != N) { + fprintf(stderr, "incorrect N (%d) in tree (vs. %d)\n", t.N, N); + return 1; + } + + for (i = 0; i < N; ++i) + k[i] = -1 - k[i]; /* undo negation above */ + + for (i = 0; i < N; ++i) { + rb_node *le, *gt; + double lek, gtk; + kd = 0.01 * (rand() % (N * 150) - N * 25); + le = rb_tree_find_le(&t, &kd); + gt = rb_tree_find_gt(&t, &kd); + n = rb_tree_min(&t); + lek = le ? le->k[0] : -HUGE_VAL; + gtk = gt ? gt->k[0] : +HUGE_VAL; + printf("%g <= %g < %g\n", lek, kd, gtk); + if (n->k[0] > kd) { + if (le) { + fprintf(stderr, "found invalid le %g for %g\n", lek, kd); + return 1; + } + if (gt != n) { + fprintf(stderr, "gt is not first node for k=%g\n", kd); + return 1; + } + } else { + rb_node *succ = n; + do { + n = succ; + succ = rb_tree_succ(n); + } while (succ && succ->k[0] <= kd); + if (n != le) { + fprintf(stderr, "rb_tree_find_le gave wrong result for k=%g\n", kd); + return 1; + } + if (succ != gt) { + fprintf(stderr, "rb_tree_find_gt gave wrong result for k=%g\n", kd); + return 1; + } + } + } + + for (M = N; M > 0; --M) { + j = rand() % M; + for (i = 0; i < N; ++i) + if (k[i] >= 0) + if (j-- == 0) + break; + if (i >= N) + abort(); + kd = k[i]; + if (!(n = rb_tree_find(&t, &kd))) { + fprintf(stderr, "rb_tree_find lost %d!\n", k[i]); + return 1; + } + n = rb_tree_remove(&t, n); + free(n->k); + free(n); + if (!rb_tree_check(&t)) { + fprintf(stderr, "rb_tree_check_failed after remove!\n"); + return 1; + } + k[i] = -1 - k[i]; + } + + if (t.N != 0) { + fprintf(stderr, "nonzero N (%d) in tree at end\n", t.N); + return 1; + } + + rb_tree_destroy(&t); + free(k); + + printf("SUCCESS.\n"); + return 0; } diff --git a/src/util/rescale.c b/src/util/rescale.c index ecdbfb9..3c1f8d0 100644 --- a/src/util/rescale.c +++ b/src/util/rescale.c @@ -28,43 +28,57 @@ array of nonzero initial steps in each dimension. */ double *nlopt_compute_rescaling(unsigned n, const double *dx) { - double *s = (double *) malloc(sizeof(double) * n); - unsigned i; + double *s = (double *) malloc(sizeof(double) * n); + unsigned i; - if (!s) return NULL; - for (i = 0; i < n; ++i) s[i] = 1.0; /* default: no rescaling */ - if (n == 1) return s; + if (!s) + return NULL; + for (i = 0; i < n; ++i) + s[i] = 1.0; /* default: no rescaling */ + if (n == 1) + return s; - for (i = 1; i < n && dx[i] == dx[i-1]; ++i) ; - if (i < n) { /* unequal initial steps, rescale to make equal to dx[0] */ - for (i = 1; i < n; ++i) - s[i] = dx[i] / dx[0]; - } - return s; + for (i = 1; i < n && dx[i] == dx[i - 1]; ++i); + if (i < n) { /* unequal initial steps, rescale to make equal to dx[0] */ + for (i = 1; i < n; ++i) + s[i] = dx[i] / dx[0]; + } + return s; } void nlopt_rescale(unsigned n, const double *s, const double *x, double *xs) { - unsigned i; - if (!s) { for (i = 0; i < n;++i) xs[i] = x[i]; } - else { for (i = 0; i < n;++i) xs[i] = x[i] / s[i]; } + unsigned i; + if (!s) { + for (i = 0; i < n; ++i) + xs[i] = x[i]; + } else { + for (i = 0; i < n; ++i) + xs[i] = x[i] / s[i]; + } } void nlopt_unscale(unsigned n, const double *s, const double *x, double *xs) { - unsigned i; - if (!s) { for (i = 0; i < n;++i) xs[i] = x[i]; } - else { for (i = 0; i < n;++i) xs[i] = x[i] * s[i]; } + unsigned i; + if (!s) { + for (i = 0; i < n; ++i) + xs[i] = x[i]; + } else { + for (i = 0; i < n; ++i) + xs[i] = x[i] * s[i]; + } } /* return a new array of length n equal to the original array x divided by the scale factors s, or NULL on a memory error */ double *nlopt_new_rescaled(unsigned n, const double *s, const double *x) { - double *xs = (double *) malloc(sizeof(double) * n); - if (!xs) return NULL; - nlopt_rescale(n, s, x, xs); - return xs; + double *xs = (double *) malloc(sizeof(double) * n); + if (!xs) + return NULL; + nlopt_rescale(n, s, x, xs); + return xs; } /* since rescaling can flip the signs of the x components and the bounds, @@ -72,11 +86,11 @@ double *nlopt_new_rescaled(unsigned n, const double *s, const double *x) remain in the correct order */ void nlopt_reorder_bounds(unsigned n, double *lb, double *ub) { - unsigned i; - for (i = 0; i < n; ++i) - if (lb[i] > ub[i]) { - double t = lb[i]; - lb[i] = ub[i]; - ub[i] = t; - } + unsigned i; + for (i = 0; i < n; ++i) + if (lb[i] > ub[i]) { + double t = lb[i]; + lb[i] = ub[i]; + ub[i] = t; + } } diff --git a/src/util/soboldata.h b/src/util/soboldata.h index 19efa5b..cddf551 100644 --- a/src/util/soboldata.h +++ b/src/util/soboldata.h @@ -37,844 +37,876 @@ /* successive primitive binary-coefficient polynomials p(z) = a_0 + a_1 z + a_2 z^2 + ... a_31 z^31, where a_i is the i-th bit of sobol_a[j] for the j-th polynomial. */ -static const uint32_t sobol_a[MAXDIM-1] = { - 3,7,11,13,19,25,37,59,47,61,55,41,67,97,91, - 109,103,115,131,193,137,145,143,241,157,185,167,229,171,213, - 191,253,203,211,239,247,285,369,299,301,333,351,355,357,361, - 391,397,425,451,463,487,501,529,539,545,557,563,601,607,617, - 623,631,637,647,661,675,677,687,695,701,719,721,731,757,761, - 787,789,799,803,817,827,847,859,865,875,877,883,895,901,911, - 949,953,967,971,973,981,985,995,1001,1019,1033,1051,1063, - 1069,1125,1135,1153,1163,1221,1239,1255,1267,1279,1293,1305, - 1315,1329,1341,1347,1367,1387,1413,1423,1431,1441,1479,1509, - 1527,1531,1555,1557,1573,1591,1603,1615,1627,1657,1663,1673, - 1717,1729,1747,1759,1789,1815,1821,1825,1849,1863,1869,1877, - 1881,1891,1917,1933,1939,1969,2011,2035,2041,2053,2071,2091, - 2093,2119,2147,2149,2161,2171,2189,2197,2207,2217,2225,2255, - 2257,2273,2279,2283,2293,2317,2323,2341,2345,2363,2365,2373, - 2377,2385,2395,2419,2421,2431,2435,2447,2475,2477,2489,2503, - 2521,2533,2551,2561,2567,2579,2581,2601,2633,2657,2669, - 2681,2687,2693,2705,2717,2727,2731,2739, - 2741,2773,2783,2793,2799,2801,2811,2819,2825,2833,2867,2879, - 2881,2891,2905,2911,2917,2927,2941,2951,2955,2963,2965,2991, - 2999,3005,3017,3035,3037,3047,3053,3083,3085,3097,3103,3159, - 3169,3179,3187,3205,3209,3223,3227,3229,3251,3263,3271,3277, - 3283,3285,3299,3305,3319,3331,3343,3357,3367,3373,3393,3399, - 3413,3417,3427,3439,3441,3475,3487,3497,3515,3517,3529,3543, - 3547,3553,3559,3573,3589,3613,3617,3623,3627,3635,3641,3655, - 3659,3669,3679,3697,3707,3709,3713,3731,3743,3747,3771,3791, - 3805,3827,3833,3851,3865,3889,3895,3933,3947,3949,3957,3971, - 3985,3991,3995,4007,4013,4021,4045,4051,4069,4073,4179,4201, - 4219,4221,4249,4305,4331,4359,4383,4387,4411,4431,4439,4449, - 4459,4485,4531,4569,4575,4621,4663,4669,4711,4723,4735,4793, - 4801,4811,4879,4893,4897,4921,4927,4941,4977,5017,5027,5033, - 5127,5169,5175,5199,5213,5223,5237,5287,5293,5331,5391,5405, - 5453,5523,5573,5591,5597,5611,5641,5703,5717,5721,5797,5821, - 5909,5913, - 5955,5957,6005,6025,6061,6067,6079,6081, - 6231,6237,6289,6295,6329,6383,6427,6453,6465,6501,6523,6539, - 6577,6589,6601,6607,6631,6683,6699,6707,6761,6795,6865,6881, - 6901,6923,6931,6943,6999,7057,7079,7103,7105,7123,7173,7185, - 7191,7207,7245,7303,7327,7333,7355,7365,7369,7375,7411,7431, - 7459,7491,7505,7515,7541,7557,7561,7701,7705,7727,7749,7761, - 7783,7795,7823,7907,7953,7963,7975,8049,8089,8123,8125,8137, - 8219,8231,8245,8275,8293,8303,8331,8333,8351,8357,8367,8379, - 8381,8387,8393,8417,8435,8461,8469,8489,8495,8507,8515,8551, - 8555,8569,8585,8599,8605,8639,8641,8647,8653,8671,8675,8689, - 8699,8729,8741,8759,8765,8771,8795,8797,8825,8831,8841,8855, - 8859,8883,8895,8909,8943,8951,8955,8965,8999,9003,9031,9045, - 9049,9071,9073,9085,9095,9101,9109,9123,9129,9137,9143,9147, - 9185,9197,9209,9227,9235,9247,9253,9257,9277,9297,9303,9313, - 9325,9343,9347,9371,9373,9397,9407,9409,9415,9419,9443,9481, - 9495,9501,9505,9517,9529,9555,9557,9571,9585,9591,9607,9611, - 9621,9625, - 9631,9647,9661,9669,9679,9687,9707,9731, - 9733,9745,9773,9791,9803,9811,9817,9833,9847,9851,9863,9875, - 9881,9905,9911,9917,9923,9963,9973,10003,10025,10043,10063, - 10071,10077,10091,10099,10105,10115,10129,10145,10169,10183, - 10187,10207,10223,10225,10247,10265,10271,10275,10289,10299, - 10301,10309,10343,10357,10373,10411,10413,10431,10445,10453, - 10463,10467,10473,10491,10505,10511,10513,10523,10539,10549, - 10559,10561,10571,10581,10615,10621,10625,10643,10655,10671, - 10679,10685,10691,10711,10739,10741,10755,10767,10781,10785, - 10803,10805,10829,10857,10863,10865,10875,10877,10917,10921, - 10929,10949,10967,10971,10987,10995,11009,11029,11043,11045, - 11055,11063,11075,11081,11117,11135,11141,11159,11163,11181, - 11187,11225,11237,11261,11279,11297,11307,11309,11327,11329, - 11341,11377,11403,11405,11413,11427,11439,11453,11461,11473, - 11479,11489,11495,11499,11533,11545,11561,11567,11575,11579, - 11589,11611,11623,11637,11657,11663,11687,11691,11701,11747, - 11761,11773,11783,11795,11797,11817,11849,11855,11867,11869, - 11873,11883,11919, - 11921,11927,11933,11947,11955,11961, - 11999,12027,12029,12037,12041,12049,12055,12095,12097,12107, - 12109,12121,12127,12133,12137,12181,12197,12207,12209,12239, - 12253,12263,12269,12277,12287,12295,12309,12313,12335,12361, - 12367,12391,12409,12415,12433,12449,12469,12479,12481,12499, - 12505,12517,12527,12549,12559,12597,12615,12621,12639,12643, - 12657,12667,12707,12713,12727,12741,12745,12763,12769,12779, - 12781,12787,12799,12809,12815,12829,12839,12857,12875,12883, - 12889,12901,12929,12947,12953,12959,12969,12983,12987,12995, - 13015,13019,13031,13063,13077,13103,13137,13149,13173,13207, - 13211,13227,13241,13249,13255,13269,13283,13285,13303,13307, - 13321,13339,13351,13377,13389,13407,13417,13431,13435,13447, - 13459,13465,13477,13501,13513,13531,13543,13561,13581,13599, - 13605,13617,13623,13637,13647,13661,13677,13683,13695,13725, - 13729,13753,13773,13781,13785,13795,13801,13807,13825,13835, - 13855,13861,13871,13883,13897,13905,13915,13939,13941,13969, - 13979,13981,13997,14027,14035,14037,14051,14063,14085,14095, - 14107,14113,14125,14137,14145, - 14151,14163,14193,14199,14219,14229, - 14233,14243,14277,14287,14289,14295,14301,14305,14323,14339, - 14341,14359,14365,14375,14387,14411,14425,14441,14449,14499, - 14513,14523,14537,14543,14561,14579,14585,14593,14599,14603, - 14611,14641,14671,14695,14701,14723,14725,14743,14753,14759, - 14765,14795,14797,14803,14831,14839,14845,14855,14889,14895, - 14909,14929,14941,14945,14951,14963,14965,14985,15033,15039, - 15053,15059,15061,15071,15077,15081,15099,15121,15147,15149, - 15157,15167,15187,15193,15203,15205,15215,15217,15223,15243, - 15257,15269,15273,15287,15291,15313,15335,15347,15359,15373, - 15379,15381,15391,15395,15397,15419,15439,15453,15469,15491, - 15503,15517,15527,15531,15545,15559,15593,15611,15613,15619, - 15639,15643,15649,15661,15667,15669,15681,15693,15717,15721, - 15741,15745,15765,15793,15799,15811,15825,15835,15847,15851, - 15865,15877,15881,15887,15899,15915,15935,15937,15955,15973, - 15977,16011,16035,16061,16069,16087,16093,16097,16121,16141, - 16153,16159,16165,16183,16189,16195,16197,16201,16209,16215, - 16225,16259,16265,16273,16299, - 16309,16355,16375,16381, +static const uint32_t sobol_a[MAXDIM - 1] = { + 3, 7, 11, 13, 19, 25, 37, 59, 47, 61, 55, 41, 67, 97, 91, + 109, 103, 115, 131, 193, 137, 145, 143, 241, 157, 185, 167, 229, 171, 213, + 191, 253, 203, 211, 239, 247, 285, 369, 299, 301, 333, 351, 355, 357, 361, + 391, 397, 425, 451, 463, 487, 501, 529, 539, 545, 557, 563, 601, 607, 617, + 623, 631, 637, 647, 661, 675, 677, 687, 695, 701, 719, 721, 731, 757, 761, + 787, 789, 799, 803, 817, 827, 847, 859, 865, 875, 877, 883, 895, 901, 911, + 949, 953, 967, 971, 973, 981, 985, 995, 1001, 1019, 1033, 1051, 1063, + 1069, 1125, 1135, 1153, 1163, 1221, 1239, 1255, 1267, 1279, 1293, 1305, + 1315, 1329, 1341, 1347, 1367, 1387, 1413, 1423, 1431, 1441, 1479, 1509, + 1527, 1531, 1555, 1557, 1573, 1591, 1603, 1615, 1627, 1657, 1663, 1673, + 1717, 1729, 1747, 1759, 1789, 1815, 1821, 1825, 1849, 1863, 1869, 1877, + 1881, 1891, 1917, 1933, 1939, 1969, 2011, 2035, 2041, 2053, 2071, 2091, + 2093, 2119, 2147, 2149, 2161, 2171, 2189, 2197, 2207, 2217, 2225, 2255, + 2257, 2273, 2279, 2283, 2293, 2317, 2323, 2341, 2345, 2363, 2365, 2373, + 2377, 2385, 2395, 2419, 2421, 2431, 2435, 2447, 2475, 2477, 2489, 2503, + 2521, 2533, 2551, 2561, 2567, 2579, 2581, 2601, 2633, 2657, 2669, + 2681, 2687, 2693, 2705, 2717, 2727, 2731, 2739, + 2741, 2773, 2783, 2793, 2799, 2801, 2811, 2819, 2825, 2833, 2867, 2879, + 2881, 2891, 2905, 2911, 2917, 2927, 2941, 2951, 2955, 2963, 2965, 2991, + 2999, 3005, 3017, 3035, 3037, 3047, 3053, 3083, 3085, 3097, 3103, 3159, + 3169, 3179, 3187, 3205, 3209, 3223, 3227, 3229, 3251, 3263, 3271, 3277, + 3283, 3285, 3299, 3305, 3319, 3331, 3343, 3357, 3367, 3373, 3393, 3399, + 3413, 3417, 3427, 3439, 3441, 3475, 3487, 3497, 3515, 3517, 3529, 3543, + 3547, 3553, 3559, 3573, 3589, 3613, 3617, 3623, 3627, 3635, 3641, 3655, + 3659, 3669, 3679, 3697, 3707, 3709, 3713, 3731, 3743, 3747, 3771, 3791, + 3805, 3827, 3833, 3851, 3865, 3889, 3895, 3933, 3947, 3949, 3957, 3971, + 3985, 3991, 3995, 4007, 4013, 4021, 4045, 4051, 4069, 4073, 4179, 4201, + 4219, 4221, 4249, 4305, 4331, 4359, 4383, 4387, 4411, 4431, 4439, 4449, + 4459, 4485, 4531, 4569, 4575, 4621, 4663, 4669, 4711, 4723, 4735, 4793, + 4801, 4811, 4879, 4893, 4897, 4921, 4927, 4941, 4977, 5017, 5027, 5033, + 5127, 5169, 5175, 5199, 5213, 5223, 5237, 5287, 5293, 5331, 5391, 5405, + 5453, 5523, 5573, 5591, 5597, 5611, 5641, 5703, 5717, 5721, 5797, 5821, + 5909, 5913, + 5955, 5957, 6005, 6025, 6061, 6067, 6079, 6081, + 6231, 6237, 6289, 6295, 6329, 6383, 6427, 6453, 6465, 6501, 6523, 6539, + 6577, 6589, 6601, 6607, 6631, 6683, 6699, 6707, 6761, 6795, 6865, 6881, + 6901, 6923, 6931, 6943, 6999, 7057, 7079, 7103, 7105, 7123, 7173, 7185, + 7191, 7207, 7245, 7303, 7327, 7333, 7355, 7365, 7369, 7375, 7411, 7431, + 7459, 7491, 7505, 7515, 7541, 7557, 7561, 7701, 7705, 7727, 7749, 7761, + 7783, 7795, 7823, 7907, 7953, 7963, 7975, 8049, 8089, 8123, 8125, 8137, + 8219, 8231, 8245, 8275, 8293, 8303, 8331, 8333, 8351, 8357, 8367, 8379, + 8381, 8387, 8393, 8417, 8435, 8461, 8469, 8489, 8495, 8507, 8515, 8551, + 8555, 8569, 8585, 8599, 8605, 8639, 8641, 8647, 8653, 8671, 8675, 8689, + 8699, 8729, 8741, 8759, 8765, 8771, 8795, 8797, 8825, 8831, 8841, 8855, + 8859, 8883, 8895, 8909, 8943, 8951, 8955, 8965, 8999, 9003, 9031, 9045, + 9049, 9071, 9073, 9085, 9095, 9101, 9109, 9123, 9129, 9137, 9143, 9147, + 9185, 9197, 9209, 9227, 9235, 9247, 9253, 9257, 9277, 9297, 9303, 9313, + 9325, 9343, 9347, 9371, 9373, 9397, 9407, 9409, 9415, 9419, 9443, 9481, + 9495, 9501, 9505, 9517, 9529, 9555, 9557, 9571, 9585, 9591, 9607, 9611, + 9621, 9625, + 9631, 9647, 9661, 9669, 9679, 9687, 9707, 9731, + 9733, 9745, 9773, 9791, 9803, 9811, 9817, 9833, 9847, 9851, 9863, 9875, + 9881, 9905, 9911, 9917, 9923, 9963, 9973, 10003, 10025, 10043, 10063, + 10071, 10077, 10091, 10099, 10105, 10115, 10129, 10145, 10169, 10183, + 10187, 10207, 10223, 10225, 10247, 10265, 10271, 10275, 10289, 10299, + 10301, 10309, 10343, 10357, 10373, 10411, 10413, 10431, 10445, 10453, + 10463, 10467, 10473, 10491, 10505, 10511, 10513, 10523, 10539, 10549, + 10559, 10561, 10571, 10581, 10615, 10621, 10625, 10643, 10655, 10671, + 10679, 10685, 10691, 10711, 10739, 10741, 10755, 10767, 10781, 10785, + 10803, 10805, 10829, 10857, 10863, 10865, 10875, 10877, 10917, 10921, + 10929, 10949, 10967, 10971, 10987, 10995, 11009, 11029, 11043, 11045, + 11055, 11063, 11075, 11081, 11117, 11135, 11141, 11159, 11163, 11181, + 11187, 11225, 11237, 11261, 11279, 11297, 11307, 11309, 11327, 11329, + 11341, 11377, 11403, 11405, 11413, 11427, 11439, 11453, 11461, 11473, + 11479, 11489, 11495, 11499, 11533, 11545, 11561, 11567, 11575, 11579, + 11589, 11611, 11623, 11637, 11657, 11663, 11687, 11691, 11701, 11747, + 11761, 11773, 11783, 11795, 11797, 11817, 11849, 11855, 11867, 11869, + 11873, 11883, 11919, + 11921, 11927, 11933, 11947, 11955, 11961, + 11999, 12027, 12029, 12037, 12041, 12049, 12055, 12095, 12097, 12107, + 12109, 12121, 12127, 12133, 12137, 12181, 12197, 12207, 12209, 12239, + 12253, 12263, 12269, 12277, 12287, 12295, 12309, 12313, 12335, 12361, + 12367, 12391, 12409, 12415, 12433, 12449, 12469, 12479, 12481, 12499, + 12505, 12517, 12527, 12549, 12559, 12597, 12615, 12621, 12639, 12643, + 12657, 12667, 12707, 12713, 12727, 12741, 12745, 12763, 12769, 12779, + 12781, 12787, 12799, 12809, 12815, 12829, 12839, 12857, 12875, 12883, + 12889, 12901, 12929, 12947, 12953, 12959, 12969, 12983, 12987, 12995, + 13015, 13019, 13031, 13063, 13077, 13103, 13137, 13149, 13173, 13207, + 13211, 13227, 13241, 13249, 13255, 13269, 13283, 13285, 13303, 13307, + 13321, 13339, 13351, 13377, 13389, 13407, 13417, 13431, 13435, 13447, + 13459, 13465, 13477, 13501, 13513, 13531, 13543, 13561, 13581, 13599, + 13605, 13617, 13623, 13637, 13647, 13661, 13677, 13683, 13695, 13725, + 13729, 13753, 13773, 13781, 13785, 13795, 13801, 13807, 13825, 13835, + 13855, 13861, 13871, 13883, 13897, 13905, 13915, 13939, 13941, 13969, + 13979, 13981, 13997, 14027, 14035, 14037, 14051, 14063, 14085, 14095, + 14107, 14113, 14125, 14137, 14145, + 14151, 14163, 14193, 14199, 14219, 14229, + 14233, 14243, 14277, 14287, 14289, 14295, 14301, 14305, 14323, 14339, + 14341, 14359, 14365, 14375, 14387, 14411, 14425, 14441, 14449, 14499, + 14513, 14523, 14537, 14543, 14561, 14579, 14585, 14593, 14599, 14603, + 14611, 14641, 14671, 14695, 14701, 14723, 14725, 14743, 14753, 14759, + 14765, 14795, 14797, 14803, 14831, 14839, 14845, 14855, 14889, 14895, + 14909, 14929, 14941, 14945, 14951, 14963, 14965, 14985, 15033, 15039, + 15053, 15059, 15061, 15071, 15077, 15081, 15099, 15121, 15147, 15149, + 15157, 15167, 15187, 15193, 15203, 15205, 15215, 15217, 15223, 15243, + 15257, 15269, 15273, 15287, 15291, 15313, 15335, 15347, 15359, 15373, + 15379, 15381, 15391, 15395, 15397, 15419, 15439, 15453, 15469, 15491, + 15503, 15517, 15527, 15531, 15545, 15559, 15593, 15611, 15613, 15619, + 15639, 15643, 15649, 15661, 15667, 15669, 15681, 15693, 15717, 15721, + 15741, 15745, 15765, 15793, 15799, 15811, 15825, 15835, 15847, 15851, + 15865, 15877, 15881, 15887, 15899, 15915, 15935, 15937, 15955, 15973, + 15977, 16011, 16035, 16061, 16069, 16087, 16093, 16097, 16121, 16141, + 16153, 16159, 16165, 16183, 16189, 16195, 16197, 16201, 16209, 16215, + 16225, 16259, 16265, 16273, 16299, + 16309, 16355, 16375, 16381, }; /* starting direction #'s m[i] = sobol_minit[i][j] for i=0..d of the * degree-d primitive polynomial sobol_a[j]. */ -static const uint32_t sobol_minit[MAXDEG+1][MAXDIM-1] = { - /* [0][*] */ - { 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 }, - /* [1][*] */ - { 0, - 1,3,1,3,1,3,3,1,3,1,3,1,3,1,1,3,1,3,1,3, - 1,3,3,1,1,1,3,1,3,1,3,3,1,3,1,1,1,3,1,3,1,1,1,3,3,1,3,3,1,1, - 3,3,1,3,3,3,1,3,1,3,1,1,3,3,1,1,1,1,3,1,1,3,1,1,1,3,3,1,3,3, - 1,3,3,3,1,3,3,3,1,3,3,1,3,3,3,1,3,1,3,1,1,3,3,1,3,3,1,1,1,3, - 3,1,3,3,1,3,1,1,3,3,3,1,1,1,3,1,1,3,1,1,3,3,1,3,1,3,3,3,3,1, - 1,1,3,3,1,1,3,1,1,1,1,1,1,3,1,3,1,1,1,3,1,3,1,3,3,3,1,1,3,3, - 1,3,1,3,1,1,3,1,3,1,3,1,3,1,1,1,3,3,1,3,3,1,3,1,1,1,3,1,3,1, - 1,3,1,1,3,3,1,1,3,3,3,1,3,3,3,1,3,1,3,1,1,1,3,1,1,1,3,1,1,1, - 1,1,3,3,3,1,1,1,1,3,3,3,1,3,3,1,1,1,1,3,1,1,3,1,3,3,1,1,3,3, - 1,1,1,1,3,1,3,3,1,3,3,1,1,1,3,3,3,1,3,3,1,3,3,1,3,1,3,3,3,1, - 3,1,1,3,1,3,1,1,1,3,3,3,1,1,3,1,3,1,1,1,1,1,1,3,1,1,3,1,3,3, - 1,1,1,1,3,1,3,1,3,1,1,1,1,3,3,1,1,1,1,1,3,3,3,1,1,3,3,3,3,3, - 1,3,3,1,3,3,3,3,1,1,1,1,1,1,3,1,1,3,1,1,1,3,1,1,1,3,3,3,1,3, - 1,1,3,3,3,1,3,3,1,3,1,3,3,1,3,3,3,1,1, - 3,3,1,3,1,3,1,1,1,3,3,3,3,1,3,1,1,3,1, - 3,1,1,1,3,1,3,1,3,1,3,3,3,3,3,3,3,3,1,3,3,3,3,3,1,3,1,3,3,3, - 1,3,1,3,1,3,3,1,3,3,3,3,3,3,3,3,3,1,1,1,1,1,1,3,3,1,1,3,3,1, - 1,1,3,3,1,1,3,3,3,3,1,1,3,1,3,3,1,3,3,1,1,1,3,3,3,1,1,3,3,3, - 3,3,1,1,1,3,1,3,3,1,3,3,3,3,1,1,3,1,1,3,1,3,1,3,1,3,3,1,1,3, - 3,1,3,3,1,3,3,1,1,3,1,3,3,1,1,3,1,3,1,3,1,1,3,3,1,1,1,3,3,1, - 3,1,1,3,3,1,1,3,1,3,1,1,1,1,1,3,1,1,1,1,3,1,3,1,1,3,3,1,1,3, - 1,3,1,3,3,3,1,3,3,3,1,1,3,3,3,1,1,1,1,3,1,3,1,3,1,1,3,3,1,1, - 1,3,3,1,3,1,3,1,1,1,1,1,1,3,1,3,3,1,3,3,3,1,3,1,1,3,3,1,1,3, - 3,1,1,1,3,1,3,3,1,1,3,1,1,3,1,3,1,1,1,3,3,3,3,1,1,3,3,1,1,1, - 1,3,1,1,3,3,3,1,1,3,3,1,3,3,1,1,3,3,3,3,3,3,3,1,3,3,1,3,1,3, - 1,1,3,3,1,1,1,3,1,3,3,1,3,3,1,3,1,1,3,3,3,1,1,1,3,1,1,1,3,3, - 3,1,3,3,1,3,1,1,3,3,3,1,3,3,1,1,1,3,1,3,3,3,3,3,3,3,3,1,3,3, - 1,3,1,1,3,3,3,1,3,3,3,3,3,1,3,3,3,1,1,1, - 3,3,1,3,3,1,3,1,3,1,3,1,3,3,3,3,3,3, - 1,1,3,1,3,1,1,1,1,1,3,1,1,1,3,1,3,1,1,3,3,3,1,3,1,3,1,1,3,1, - 3,3,1,3,1,3,3,1,3,3,1,3,3,3,3,3,3,1,3,1,1,3,3,3,1,1,3,3,3,3, - 3,3,3,1,3,3,3,3,1,3,1,3,3,3,1,3,1,3,1,1,1,3,3,1,3,1,1,3,3,1, - 3,1,1,1,1,3,1,3,1,1,3,1,3,1,3,3,3,3,3,3,1,3,3,3,3,1,3,3,1,3, - 3,3,3,3,1,1,1,1,3,3,3,1,3,3,1,1,3,3,1,1,3,3,1,3,1,1,3,1,3,3, - 3,3,3,1,3,1,1,3,3,3,3,1,3,1,1,3,3,3,3,3,3,1,1,3,1,3,1,1,3,1, - 1,1,1,3,3,1,1,3,1,1,1,3,1,3,1,1,3,3,1,3,1,1,3,3,3,3,3,1,3,1, - 1,1,3,1,1,1,3,1,1,3,1,3,3,3,3,3,1,1,1,3,3,3,3,1,3,3,3,3,1,1, - 3,3,3,1,3,1,1,3,3,1,3,3,1,1,1,1,1,3,1,1,3,3,1,1,1,3,1,1,3,3, - 1,3,3,3,3,3,3,3,3,1,1,3,3,1,1,3,1,3,3,3,3,3,1}, - /* [2][*] */ - { 0,0, - 7,5,1,3,3,7,5,5,7,7,1,3,3,7,5,1,1,5,3,7, - 1,7,5,1,3,7,7,1,1,1,5,7,7,5,1,3,3,7,5,5,5,3,3,3,1,1,5,1,1,5, - 3,3,3,3,1,3,7,5,7,3,7,1,3,3,5,1,3,5,5,7,7,7,1,1,3,3,1,1,5,1, - 5,7,5,1,7,5,3,3,1,5,7,1,7,5,1,7,3,1,7,1,7,3,3,5,7,3,3,5,1,3, - 3,1,3,5,1,3,3,3,7,1,1,7,3,1,3,7,5,5,7,5,5,3,1,3,3,3,1,3,3,7, - 3,3,1,7,5,1,7,7,5,7,5,1,3,1,7,3,7,3,5,7,3,1,3,3,3,1,5,7,3,3, - 7,7,7,5,3,1,7,1,3,7,5,3,3,3,7,1,1,3,1,5,7,1,3,5,3,5,3,3,7,5, - 5,3,3,1,3,7,7,7,1,5,7,1,3,1,1,7,1,3,1,7,1,5,3,5,3,1,1,5,5,3, - 3,5,7,1,5,3,7,7,3,5,3,3,1,7,3,1,3,5,7,1,3,7,1,5,1,3,1,5,3,1, - 7,1,5,5,5,3,7,1,1,7,3,1,1,7,5,7,5,7,7,3,7,1,3,7,7,3,5,1,1,7, - 1,5,5,5,1,5,1,7,5,5,7,1,1,7,1,7,7,1,1,3,3,3,7,7,5,3,7,3,1,3, - 7,5,3,3,5,7,1,1,5,5,7,7,1,1,1,1,5,5,5,7,5,7,1,1,3,5,1,3,3,7, - 3,7,5,3,5,3,1,7,1,7,7,1,1,7,7,7,5,5,1,1,7,5,5,7,5,1,1,5,5,5, - 5,5,5,1,3,1,5,7,3,3,5,7,3,7,1,7,7,1,3, - 5,1,5,5,3,7,3,7,7,5,7,5,7,1,1,5,3,5,1, - 5,3,7,1,5,7,7,3,5,1,3,5,1,5,3,3,3,7,3,5,1,3,7,7,3,7,5,3,3,1, - 7,5,1,1,3,7,1,7,1,7,3,7,3,5,7,3,5,3,1,1,1,5,7,7,3,3,1,1,1,5, - 5,7,3,1,1,3,3,7,3,3,5,1,3,7,3,3,7,3,5,7,5,7,7,3,3,5,1,3,5,3, - 1,3,5,1,1,3,7,7,1,5,1,3,7,3,7,3,5,1,7,1,1,3,5,3,7,1,5,5,1,1, - 3,1,3,3,7,1,7,3,1,7,3,1,7,3,5,3,5,7,3,3,3,5,1,7,7,1,3,1,3,7, - 7,1,3,7,3,1,5,3,1,1,1,5,3,3,7,1,5,3,5,1,3,1,3,1,5,7,7,1,1,5, - 3,1,5,1,1,7,7,3,5,5,1,7,1,5,1,1,3,1,5,7,5,7,7,1,5,1,1,3,5,1, - 5,5,3,1,3,1,5,5,3,3,3,3,1,1,3,1,3,5,5,7,5,5,7,5,7,1,3,7,7,3, - 5,5,7,5,5,3,3,3,1,7,1,5,5,5,3,3,5,1,3,1,3,3,3,7,1,7,7,3,7,1, - 1,5,7,1,7,1,7,7,1,3,7,5,1,3,5,5,5,1,1,7,1,7,1,7,7,3,1,1,5,1, - 5,1,5,3,5,5,5,5,5,3,3,7,3,3,5,5,3,7,1,5,7,5,1,5,5,3,5,5,7,5, - 3,5,5,5,1,5,5,5,5,1,3,5,3,1,7,5,5,7,1,5,3,3,1,5,3,7,1,7,5,1, - 1,3,1,1,7,1,5,5,3,7,3,7,5,3,1,1,3,1,3,5, - 5,7,5,3,7,7,7,3,7,3,7,1,3,1,7,7,1,7, - 3,7,3,7,3,7,3,5,1,1,7,3,1,5,5,7,1,5,5,5,7,1,5,5,1,5,5,3,1,3, - 1,7,3,1,3,5,7,7,7,1,1,7,3,1,5,5,5,1,1,1,1,1,5,3,5,1,3,5,3,1, - 1,1,1,3,7,3,7,5,7,1,5,5,7,5,3,3,7,5,3,1,1,3,1,3,1,1,3,7,1,7, - 1,1,5,1,7,5,3,7,3,5,3,1,1,5,5,1,7,7,3,7,3,7,1,5,1,5,3,7,3,5, - 7,7,7,3,3,1,1,5,5,3,7,1,1,1,3,5,3,1,1,3,3,7,5,1,1,3,7,1,5,7, - 3,7,5,5,7,3,5,3,1,5,3,1,1,7,5,1,7,3,7,5,1,7,1,7,7,1,1,7,1,5, - 5,1,1,7,5,7,1,5,3,5,3,3,7,1,5,1,1,5,5,3,3,7,5,5,1,1,1,3,1,5, - 7,7,1,7,5,7,3,7,3,1,3,7,3,1,5,5,3,5,1,3,5,5,5,1,1,7,7,1,5,5, - 1,3,5,1,5,3,5,3,3,7,5,7,3,7,3,1,3,7,7,3,3,1,1,3,3,3,3,3,5,5, - 3,3,3,1,3,5,7,7,1,5,7,3,7,1,1,3,5,7,5,3,3,3}, - /* [3][*] */ - { 0,0,0,0, - 1,7,9,13,11,1,3,7,9,5,13,13,11,3,15,5,3, - 15,7,9,13,9,1,11,7,5,15,1,15,11,5,11,1,7,9,7,7,1,15,15,15,13, - 3,3,15,5,9,7,13,3,7,5,11,9,1,9,1,5,7,13,9,9,1,7,3,5,1,11,11, - 13,7,7,9,9,1,1,3,9,15,1,5,13,1,9,9,9,9,9,13,11,3,5,11,11,13, - 5,3,15,1,11,11,7,13,15,11,13,9,11,15,15,13,3,15,7,9,11,13,11, - 9,9,5,13,9,1,13,7,7,7,7,7,5,9,7,13,11,9,11,15,3,13,11,1,11,3, - 3,9,11,1,7,1,15,15,3,1,9,1,7,13,11,3,13,11,7,3,3,5,13,11,5, - 11,1,3,9,7,15,7,5,13,7,9,13,15,13,9,7,15,7,9,5,11,11,13,13,9, - 3,5,13,9,11,15,11,7,1,7,13,3,13,3,13,9,15,7,13,13,3,13,15,15, - 11,9,13,9,15,1,1,15,11,11,7,1,11,13,9,13,3,5,11,13,9,9,13,1, - 11,15,13,3,13,7,15,1,15,3,3,11,7,13,7,7,9,7,5,15,9,5,5,7,15, - 13,15,5,15,5,3,1,11,7,1,5,7,9,3,11,1,15,1,3,15,11,13,5,13,1, - 7,1,15,7,5,1,1,15,13,11,11,13,5,11,7,9,7,1,5,3,9,5,5,11,5,1, - 7,1,11,7,9,13,15,13,3,1,11,13,15,1,1,11,9,13,3,13,11,15,13,9, - 9,9,5,5,5,5,1,15,5,9, - 11,7,15,5,3,13,5,3,11,5,1,11,13,9,11, - 3,7,13,15,1,7,11,1,13,1,15,1,9,7,3,9,11,1,9,13,13,3,11,7,9,1, - 7,15,9,1,5,13,5,11,3,9,15,11,13,5,1,7,7,5,13,7,7,9,5,11,11,1, - 1,15,3,13,9,13,9,9,11,5,5,13,15,3,9,15,3,11,11,15,15,3,11,15, - 15,3,1,3,1,3,3,1,3,13,1,11,5,15,7,15,9,1,7,1,9,11,15,1,13,9, - 13,11,7,3,7,3,13,7,9,7,7,3,3,9,9,7,5,11,13,13,7,7,15,9,5,5,3, - 3,13,3,9,3,1,11,1,3,11,15,11,11,11,9,13,7,9,15,9,11,1,3,3,9, - 7,15,13,13,7,15,9,13,9,15,13,15,9,13,1,11,7,11,3,13,5,1,7,15, - 3,13,7,13,13,11,3,5,3,13,11,9,9,3,11,11,7,9,13,11,7,15,13,7, - 5,3,1,5,15,15,3,11,1,7,3,15,11,5,5,3,5,5,1,15,5,1,5,3,7,5,11, - 3,13,9,13,15,5,3,5,9,5,3,11,1,13,9,15,3,5,11,9,1,3,15,9,9,9, - 11,7,5,13,1,15,3,13,9,13,5,1,5,1,13,13,7,7,1,9,5,11,9,11,13, - 3,15,15,13,15,7,5,7,9,7,9,9,9,11,9,3,11,15,13,13,5,9,15,1,1, - 9,5,13,3,13,15,3,1,3,11,13,1,15,9,9,3,1,9,1,9,1,13,11,15,7, - 11,15,13,15,1,9,9,7, - 3,5,11,7,3,9,5,15,7,5,3,13,7,1,1,9, - 15,15,15,11,3,5,15,13,7,15,15,11,11,9,5,15,9,7,3,13,1,1,5,1, - 3,1,7,1,1,5,1,11,11,9,9,5,13,7,7,7,1,1,9,9,11,11,15,7,5,5,3, - 11,1,3,7,13,7,7,7,3,15,15,11,9,3,9,3,15,13,5,3,3,3,5,9,15,9, - 9,1,5,9,9,15,5,15,7,9,1,9,9,5,11,5,15,15,11,7,7,7,1,1,11,11, - 13,15,3,13,5,1,7,1,11,3,13,15,3,5,3,5,7,3,9,9,5,1,7,11,9,3,5, - 11,13,13,13,9,15,5,7,1,15,11,9,15,15,13,13,13,1,11,9,15,9,5, - 15,5,7,3,11,3,15,7,13,11,7,3,7,13,5,13,15,5,13,9,1,15,11,5,5, - 1,11,3,3,7,1,9,7,15,9,9,3,11,15,7,1,3,1,1,1,9,1,5,15,15,7,5, - 5,7,9,7,15,13,13,11,1,9,11,1,13,1,7,15,15,5,5,1,11,3,9,11,9, - 9,9,1,9,3,5,15,1,1,9,7,3,3,1,9,9,11,9,9,13,13,3,13,11,13,5,1, - 5,5,9,9,3,13,13,9,15,9,11,7,11,9,13,9,1,15,9,7,7,1,7,9,9,15, - 1,11,1,13,13,15,9,13,7,15,3,9,3,1,13,7,5,9,3,1,7,1,1,13,3,3, - 11,1,7,13,15,15,5,7,13,13,15,11,13,1,13,13,3,9,15,15,11,15,9, - 15,1,13,15,1,1,5, - 11,5,1,11,11,5,3,9,1,3,5,13,9,7,7,1, - 9,9,15,7,5,5,15,13,9,7,13,3,13,11,13,7,9,13,13,13,15,9,5,5,3, - 3,3,1,3,15}, - /* [4][*] */ - { 0,0,0,0,0,0, - 9,3,27,15,29,21,23,19,11,25,7,13,17,1, - 25,29,3,31,11,5,23,27,19,21,5,1,17,13,7,15,9,31,25,3,5,23,7, - 3,17,23,3,3,21,25,25,23,11,19,3,11,31,7,9,5,17,23,17,17,25, - 13,11,31,27,19,17,23,7,5,11,19,19,7,13,21,21,7,9,11,1,5,21, - 11,13,25,9,7,7,27,15,25,15,21,17,19,19,21,5,11,3,5,29,31,29, - 5,5,1,31,27,11,13,1,3,7,11,7,3,23,13,31,17,1,27,11,25,1,23, - 29,17,25,7,25,27,17,13,17,23,5,17,5,13,11,21,5,11,5,9,31,19, - 17,9,9,27,21,15,15,1,1,29,5,31,11,17,23,19,21,25,15,11,5,5,1, - 19,19,19,7,13,21,17,17,25,23,19,23,15,13,5,19,25,9,7,3,21,17, - 25,1,27,25,27,25,9,13,3,17,25,23,9,25,9,13,17,17,3,15,7,7,29, - 3,19,29,29,19,29,13,15,25,27,1,3,9,9,13,31,29,31,5,15,29,1, - 19,5,9,19,5,15,3,5,7,15,17,17,23,11,9,23,19,3,17,1,27,9,9,17, - 13,25,29,23,29,11,31,25,21,29,19,27,31,3,5,3,3,13,21,9,29,3, - 17,11,11,9,21,19,7,17,31,25,1,27,5,15,27,29,29,29,25,27,25,3, - 21,17,25,13,15,17,13,23,9,3,11,7,9,9,7,17,7,1, - 27,1,9,5,31,21,25,25,21,11,1,23,19,27, - 15,3,5,23,9,25,7,29,11,9,13,5,11,1,3,31,27,3,17,27,11,13,15, - 29,15,1,15,23,25,13,21,15,3,29,29,5,25,17,11,7,15,5,21,7,31, - 13,11,23,5,7,23,27,21,29,15,7,27,27,19,7,15,27,27,19,19,9,15, - 1,3,29,29,5,27,31,9,1,7,3,19,19,29,9,3,21,31,29,25,1,3,9,27, - 5,27,25,21,11,29,31,27,21,29,17,9,17,13,11,25,15,21,11,19,31, - 3,19,5,3,3,9,13,13,3,29,7,5,9,23,13,21,23,21,31,11,7,7,3,23, - 1,23,5,9,17,21,1,17,29,7,5,17,13,25,17,9,19,9,5,7,21,19,13,9, - 7,3,9,3,15,31,29,29,25,13,9,21,9,31,7,15,5,31,7,15,27,25,19, - 9,9,25,25,23,1,9,7,11,15,19,15,27,17,11,11,31,13,25,25,9,7, - 13,29,19,5,19,31,25,13,25,15,5,9,29,31,9,29,27,25,27,11,17,5, - 17,3,23,15,9,9,17,17,31,11,19,25,13,23,15,25,21,31,19,3,11, - 25,7,15,19,7,5,3,13,13,1,23,5,25,11,25,15,13,21,11,23,29,5, - 17,27,9,19,15,5,29,23,19,1,27,3,23,21,19,27,11,17,13,27,11, - 31,23,5,9,21,31,29,11,21,17,15,7,15,7,9,21,27,25, - 29,11,3,21,13,23,19,27,17,29,25,17,9, - 1,19,23,5,23,1,17,17,13,27,23,7,7,11,13,17,13,11,21,13,23,1, - 27,13,9,7,1,27,29,5,13,25,21,3,31,15,13,3,19,13,1,27,15,17,1, - 3,13,13,13,31,29,27,7,7,21,29,15,17,17,21,19,17,3,15,5,27,27, - 3,31,31,7,21,3,13,11,17,27,25,1,9,7,29,27,21,23,13,25,29,15, - 17,29,9,15,3,21,15,17,17,31,9,9,23,19,25,3,1,11,27,29,1,31, - 29,25,29,1,23,29,25,13,3,31,25,5,5,11,3,21,9,23,7,11,23,11,1, - 1,3,23,25,23,1,23,3,27,9,27,3,23,25,19,29,29,13,27,5,9,29,29, - 13,17,3,23,19,7,13,3,19,23,5,29,29,13,13,5,19,5,17,9,11,11, - 29,27,23,19,17,25,13,1,13,3,11,1,17,29,1,13,17,9,17,21,1,11, - 1,1,25,5,7,29,29,19,19,1,29,13,3,1,31,15,13,3,1,11,19,5,29, - 13,29,23,3,1,31,13,19,17,5,5,1,29,23,3,19,25,19,27,9,27,13, - 15,29,23,13,25,25,17,19,17,15,27,3,25,17,27,3,27,31,23,13,31, - 11,15,7,21,19,27,19,21,29,7,31,13,9,9,7,21,13,11,9,11,29,19, - 11,19,21,5,29,13,7,19,19,27,23,31,1,27,21,7,3,7,11, - 23,13,29,11,31,19,1,5,5,11,5,3,27,5, - 7,11,31,1,27,31,31,23,5,21,27,9,25,3,15,19,1,19,9,5,25,21,15, - 25,29,15,21,11,19,15,3,7,13,11,25,17,1,5,31,13,29,23,9,5,29, - 7,17,27,7,17,31,9,31,9,9,7,21,3,3,3,9,11,21,11,31,9,25,5,1, - 31,13,29,9,29,1,11,19,7,27,13,31,7,31,7,25,23,21,29,11,11,13, - 11,27,1,23,31,21,23,21,19,31,5,31,25,25,19,17,11,25,7,13,1, - 29,17,23,15,7,29,17,13,3,17}, - /* [5][*] */ - { 0,0,0,0,0,0,0,0,0,0,0,0, - 37,33,7,5,11,39,63,59,17,15,23,29,3,21, - 13,31,25,9,49,33,19,29,11,19,27,15,25,63,55,17,63,49,19,41, - 59,3,57,33,49,53,57,57,39,21,7,53,9,55,15,59,19,49,31,3,39,5, - 5,41,9,19,9,57,25,1,15,51,11,19,61,53,29,19,11,9,21,19,43,13, - 13,41,25,31,9,11,19,5,53,37,7,51,45,7,7,61,23,45,7,59,41,1, - 29,61,37,27,47,15,31,35,31,17,51,13,25,45,5,5,33,39,5,47,29, - 35,47,63,45,37,47,59,21,59,33,51,9,27,13,25,43,3,17,21,59,61, - 27,47,57,11,17,39,1,63,21,59,17,13,31,3,31,7,9,27,37,23,31,9, - 45,43,31,63,21,39,51,27,7,53,11,1,59,39,23,49,23,7,55,59,3, - 19,35,13,9,13,15,23,9,7,43,55,3,19,9,27,33,27,49,23,47,19,7, - 11,55,27,35,5,5,55,35,37,9,33,29,47,25,11,47,53,61,59,3,53, - 47,5,19,59,5,47,23,45,53,3,49,61,47,39,29,17,57,5,17,31,23, - 41,39,5,27,7,29,29,33,31,41,31,29,17,29,29,9,9,31,27,53,35,5, - 61,1,49,13,57,29,5,21,43,25,57,49,37,27,11,61,37,49,5,63,63, - 3,45,37,63,21,21,19,27,59,21,45,23,13,15,3,43,63,39,19, - 63,31,41,41,15,43,63,53,1,63,31,7,17, - 11,61,31,51,37,29,59,25,63,59,47,15,27,19,29,45,35,55,39,19, - 43,21,19,13,17,51,37,5,33,35,49,25,45,1,63,47,9,63,15,25,25, - 15,41,13,3,19,51,49,37,25,49,13,53,47,23,35,29,33,21,35,23,3, - 43,31,63,9,1,61,43,3,11,55,11,35,1,63,35,49,19,45,9,57,51,1, - 47,41,9,11,37,19,55,23,55,55,13,7,47,37,11,43,17,3,25,19,55, - 59,37,33,43,1,5,21,5,63,49,61,21,51,15,19,43,47,17,9,53,45, - 11,51,25,11,25,47,47,1,43,29,17,31,15,59,27,63,11,41,51,29,7, - 27,63,31,43,3,29,39,3,59,59,1,53,63,23,63,47,51,23,61,39,47, - 21,39,15,3,9,57,61,39,37,21,51,1,23,43,27,25,11,13,21,43,7, - 11,33,55,1,37,35,27,61,39,5,19,61,61,57,59,21,59,61,57,25,55, - 27,31,41,33,63,19,57,35,13,63,35,17,11,11,49,41,55,5,45,17, - 35,5,31,31,37,17,45,51,1,39,49,55,19,41,13,5,51,5,49,1,21,13, - 17,59,51,11,3,61,1,33,37,33,61,25,27,59,7,49,13,63,3,33,3,15, - 9,13,35,39,11,59,59,1,57,11,5,57,13,31,13,11,55,45,9,55,55, - 19,25,41,23,45,29,63,59,27,39,21,37,7, - 61,49,35,39,9,29,7,25,23,57,5,19,15,33,49,37,25,17,45,29,15, - 25,3,3,49,11,39,15,19,57,39,15,11,3,57,31,55,61,19,5,41,35, - 59,61,39,41,53,53,63,31,9,59,13,35,55,41,49,5,41,25,27,43,5, - 5,43,5,5,17,5,15,27,29,17,9,3,55,31,1,45,45,13,57,17,3,61,15, - 49,15,47,9,37,45,9,51,61,21,33,11,21,63,63,47,57,61,49,9,59, - 19,29,21,23,55,23,43,41,57,9,39,27,41,35,61,29,57,63,21,31, - 59,35,49,3,49,47,49,33,21,19,21,35,11,17,37,23,59,13,37,35, - 55,57,1,29,45,11,1,15,9,33,19,53,43,39,23,7,13,13,1,19,41,55, - 1,13,15,59,55,15,3,57,37,31,17,1,3,21,29,25,55,9,37,33,53,41, - 51,19,57,13,63,43,19,7,13,37,33,19,15,63,51,11,49,23,57,47, - 51,15,53,41,1,15,37,61,11,35,29,33,23,55,11,59,19,61,61,45, - 13,49,13,63,5,61,5,31,17,61,63,13,27,57,1,21,5,11,39,57,51, - 53,39,25,41,39,37,23,31,25,33,17,57,29,27,23,47,41,29,19,47, - 41,25,5,51,43,39,29,7,31,45,51,49,55,17,43,49,45,9,29,3,5,47, - 9,15,19, - 51,45,57,63,9,21,59,3,9,13,45,23,15, - 31,21,15,51,35,9,11,61,23,53,29,51,45,31,29,5,35,29,53,35,17, - 59,55,27,51,59,27,47,15,29,37,7,49,55,5,19,45,29,19,57,33,53, - 45,21,9,3,35,29,43,31,39,3,45,1,41,29,5,59,41,33,35,27,19,13, - 25,27,43,33,35,17,17,23,7,35,15,61,61,53,5,15,23,11,13,43,55, - 47,25,43,15,57,45,1,49,63,57,15,31,31,7,53,27,15,47,23,7,29, - 53,47,9,53,3,25,55,45,63,21,17,23,31,27,27,43,63,55,63,45,51, - 15,27,5,37,43,11,27,5,27,59,21,7,39,27,63,35,47,55,17,17,17, - 3,19,21,13,49,61,39,15}, - /* [6][*] */ - { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, - 13,33,115,41,79,17,29,119,75,73,105,7, - 59,65,21,3,113,61,89,45,107,21,71,79,19,71,61,41,57,121,87, - 119,55,85,121,119,11,23,61,11,35,33,43,107,113,101,29,87,119, - 97,29,17,89,5,127,89,119,117,103,105,41,83,25,41,55,69,117, - 49,127,29,1,99,53,83,15,31,73,115,35,21,89,5,1,91,53,35,95, - 83,19,85,55,51,101,33,41,55,45,95,61,27,37,89,75,57,61,15, - 117,15,21,27,25,27,123,39,109,93,51,21,91,109,107,45,15,93, - 127,3,53,81,79,107,79,87,35,109,73,35,83,107,1,51,7,59,33, - 115,43,111,45,121,105,125,87,101,41,95,75,1,57,117,21,27,67, - 29,53,117,63,1,77,89,115,49,127,15,79,81,29,65,103,33,73,79, - 29,21,113,31,33,107,95,111,59,99,117,63,63,99,39,9,35,63,125, - 99,45,93,33,93,9,105,75,51,115,11,37,17,41,21,43,73,19,93,7, - 95,81,93,79,81,55,9,51,63,45,89,73,19,115,39,47,81,39,5,5,45, - 53,65,49,17,105,13,107,5,5,19,73,59,43,83,97,115,27,1,69,103, - 3,99,103,63,67,25,121,97,77,13,83,103,41,11,27,81,37,33,125, - 71,41,41,59,41,87,123, - 43,101,63,45,39,21,97,15,97,111,21,49, - 13,17,79,91,65,105,75,1,45,67,83,107,125,87,15,81,95,105,65, - 45,59,103,23,103,99,67,99,47,117,71,89,35,53,73,9,115,49,37, - 1,35,9,45,81,19,127,17,17,105,89,49,101,7,37,33,11,95,95,17, - 111,105,41,115,5,69,101,27,27,101,103,53,9,21,43,79,91,65, - 117,87,125,55,45,63,85,83,97,45,83,87,113,93,95,5,17,77,77, - 127,123,45,81,85,121,119,27,85,41,49,15,107,21,51,119,11,87, - 101,115,63,63,37,121,109,7,43,69,19,77,49,71,59,35,7,13,55, - 101,127,103,85,109,29,61,67,21,111,67,23,57,75,71,101,123,41, - 107,101,107,125,27,47,119,41,19,127,33,31,109,7,91,91,39,125, - 105,47,125,123,91,9,103,45,23,117,9,125,73,11,37,61,79,21,5, - 47,117,67,53,85,33,81,121,47,61,51,127,29,65,45,41,95,57,73, - 33,117,61,111,59,123,65,47,105,23,29,107,37,81,67,29,115,119, - 75,73,99,103,7,57,45,61,95,49,101,101,35,47,119,39,67,31,103, - 7,61,127,87,3,35,29,73,95,103,71,75,51,87,57,97,11,105,87,41, - 73,109,69,35,121,39,111,1,77, - 39,47,53,91,3,17,51,83,39,125,85,111, - 21,69,85,29,55,11,117,1,47,17,65,63,47,117,17,115,51,25,33, - 123,123,83,51,113,95,121,51,91,109,43,55,35,55,87,33,37,5,3, - 45,21,105,127,35,17,35,37,97,97,21,77,123,17,89,53,105,75,25, - 125,13,47,21,125,23,55,63,61,5,17,93,57,121,69,73,93,121,105, - 75,91,67,95,75,9,69,97,99,93,11,53,19,73,5,33,79,107,65,69, - 79,125,25,93,55,61,17,117,69,97,87,111,37,93,59,79,95,53,115, - 53,85,85,65,59,23,75,21,67,27,99,79,27,3,95,27,69,19,75,47, - 59,41,85,77,99,55,49,93,93,119,51,125,63,13,15,45,61,19,105, - 115,17,83,7,7,11,61,37,63,89,95,119,113,67,123,91,33,37,99, - 43,11,33,65,81,79,81,107,63,63,55,89,91,25,93,101,27,55,75, - 121,79,43,125,73,27,109,35,21,71,113,89,59,95,41,45,113,119, - 113,39,59,73,15,13,59,67,121,27,7,105,15,59,59,35,91,89,23, - 125,97,53,41,91,111,29,31,3,103,61,71,35,7,119,29,45,49,111, - 41,109,59,125,13,27,19,79,9,75,83,81,33,91,109,33,29,107,111, - 101,107,109,65,59,43,37, - 1,9,15,109,37,111,113,119,79,73,65, - 71,93,17,101,87,97,43,23,75,109,41,49,53,31,97,105,109,119, - 51,9,53,113,97,73,89,79,49,61,105,13,99,53,71,7,87,21,101,5, - 71,31,123,121,121,73,79,115,13,39,101,19,37,51,83,97,55,81, - 91,127,105,89,63,47,49,75,37,77,15,49,107,23,23,35,19,69,17, - 59,63,73,29,125,61,65,95,101,81,57,69,83,37,11,37,95,1,73,27, - 29,57,7,65,83,99,69,19,103,43,95,25,19,103,41,125,97,71,105, - 83,83,61,39,9,45,117,63,31,5,117,67,125,41,117,43,77,97,15, - 29,5,59,25,63,87,39,39,77,85,37,81,73,89,29,125,109,21,23, - 119,105,43,93,97,15,125,29,51,69,37,45,31,75,109,119,53,5, - 101,125,121,35,29,7,63,17,63,13,69,15,105,51,127,105,9,57,95, - 59,109,35,49,23,33,107,55,33,57,79,73,69,59,107,55,11,63,95, - 103,23,125,91,31,91,51,65,61,75,69,107,65,101,59,35,15}, - /* [7][*] */ - { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, - 7,23,39,217,141,27,53,181,169,35,15, - 207,45,247,185,117,41,81,223,151,81,189,61,95,185,23,73,113, - 239,85,9,201,83,53,183,203,91,149,101,13,111,239,3,205,253, - 247,121,189,169,179,197,175,217,249,195,95,63,19,7,5,75,217, - 245,111,189,165,169,141,221,249,159,253,207,249,219,23,49, - 127,237,5,25,177,37,103,65,167,81,87,119,45,79,143,57,79,187, - 143,183,75,97,211,149,175,37,135,189,225,241,63,33,43,13,73, - 213,57,239,183,117,21,29,115,43,205,223,15,3,159,51,101,127, - 99,239,171,113,171,119,189,245,201,27,185,229,105,153,189,33, - 35,137,77,97,17,181,55,197,201,155,37,197,137,223,25,179,91, - 23,235,53,253,49,181,249,53,173,97,247,67,115,103,159,239,69, - 173,217,95,221,247,97,91,123,223,213,129,181,87,239,85,89, - 249,141,39,57,249,71,101,159,33,137,189,71,253,205,171,13, - 249,109,131,199,189,179,31,99,113,41,173,23,189,197,3,135,9, - 95,195,27,183,1,123,73,53,99,197,59,27,101,55,193,31,61,119, - 11,7,255,233,53,157,193,97,83,65,81,239,167,69,71,109, - 97,137,71,193,189,115,79,205,37,227, - 53,33,91,229,245,105,77,229,161,103,93,13,161,229,223,69,15, - 25,23,233,93,25,217,247,61,75,27,9,223,213,55,197,145,89,199, - 41,201,5,149,35,119,183,53,11,13,3,179,229,43,55,187,233,47, - 133,91,47,71,93,105,145,45,255,221,115,175,19,129,5,209,197, - 57,177,115,187,119,77,211,111,33,113,23,87,137,41,7,83,43, - 121,145,5,219,27,11,111,207,55,97,63,229,53,33,149,23,187, - 153,91,193,183,59,211,93,139,59,179,163,209,77,39,111,79,229, - 85,237,199,137,147,25,73,121,129,83,87,93,205,167,53,107,229, - 213,95,219,109,175,13,209,97,61,147,19,13,123,73,35,141,81, - 19,171,255,111,107,233,113,133,89,9,231,95,69,33,1,253,219, - 253,247,129,11,251,221,153,35,103,239,7,27,235,181,5,207,53, - 149,155,225,165,137,155,201,97,245,203,47,39,35,105,239,49, - 15,253,7,237,213,55,87,199,27,175,49,41,229,85,3,149,179,129, - 185,249,197,15,97,197,139,203,63,33,251,217,199,199,99,249, - 33,229,177,13,209,147,97,31,125,177,137, - 187,11,91,223,29,169,231,59,31,163,41, - 57,87,247,25,127,101,207,187,73,61,105,27,91,171,243,33,3,1, - 21,229,93,71,61,37,183,65,211,53,11,151,165,47,5,129,79,101, - 147,169,181,19,95,77,139,197,219,97,239,183,143,9,13,209,23, - 215,53,137,203,19,151,171,133,219,231,3,15,253,225,33,111, - 183,213,169,119,111,15,201,123,121,225,113,113,225,161,165,1, - 139,55,3,93,217,193,97,29,69,231,161,93,69,143,137,9,87,183, - 113,183,73,215,137,89,251,163,41,227,145,57,81,57,11,135,145, - 161,175,159,25,55,167,157,211,97,247,249,23,129,159,71,197, - 127,141,219,5,233,131,217,101,131,33,157,173,69,207,239,81, - 205,11,41,169,65,193,77,201,173,1,221,157,1,15,113,147,137, - 205,225,73,45,49,149,113,253,99,17,119,105,117,129,243,75, - 203,53,29,247,35,247,171,31,199,213,29,251,7,251,187,91,11, - 149,13,205,37,249,137,139,9,7,113,183,205,187,39,3,79,155, - 227,89,185,51,127,63,83,41,133,183,181,127,19,255,219,59,251, - 3,187,57,217,115,217,229,181,185,149,83,115,11, - 123,19,109,165,103,123,219,129,155, - 207,177,9,49,181,231,33,233,67,155,41,9,95,123,65,117,249,85, - 169,129,241,173,251,225,147,165,69,81,239,95,23,83,227,249, - 143,171,193,9,21,57,73,97,57,29,239,151,159,191,47,51,1,223, - 251,251,151,41,119,127,131,33,209,123,53,241,25,31,183,107, - 25,115,39,11,213,239,219,109,185,35,133,123,185,27,55,245,61, - 75,205,213,169,163,63,55,49,83,195,51,31,41,15,203,41,63,127, - 161,5,143,7,199,251,95,75,101,15,43,237,197,117,167,155,21, - 83,205,255,49,101,213,237,135,135,21,73,93,115,7,85,223,237, - 79,89,5,57,239,67,65,201,155,71,85,195,89,181,119,135,147, - 237,173,41,155,67,113,111,21,183,23,103,207,253,69,219,205, - 195,43,197,229,139,177,129,69,97,201,163,189,11,99,91,253, - 239,91,145,19,179,231,121,7,225,237,125,191,119,59,175,237, - 131,79,43,45,205,199,251,153,207,37,179,113,255,107,217,61,7, - 181,247,31,13,113,145,107,233,233,43,79,23,169,137,129,183, - 53,91,55,103,223,87,177,157,79,213,139, - 183,231,205,143,129,243,205,93,59, - 15,89,9,11,47,133,227,75,9,91,19,171,163,79,7,103,5,119,155, - 75,11,71,95,17,13,243,207,187}, - /* [8][*] */ - { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, - 235,307,495,417,57,151,19,119,375,451, - 55,449,501,53,185,317,17,21,487,13,347,393,15,391,307,189, - 381,71,163,99,467,167,433,337,257,179,47,385,23,117,369,425, - 207,433,301,147,333,85,221,423,49,3,43,229,227,201,383,281, - 229,207,21,343,251,397,173,507,421,443,399,53,345,77,385,317, - 155,187,269,501,19,169,235,415,61,247,183,5,257,401,451,95, - 455,49,489,75,459,377,87,463,155,233,115,429,211,419,143,487, - 195,209,461,193,157,193,363,181,271,445,381,231,135,327,403, - 171,197,181,343,113,313,393,311,415,267,247,425,233,289,55, - 39,247,327,141,5,189,183,27,337,341,327,87,429,357,265,251, - 437,201,29,339,257,377,17,53,327,47,375,393,369,403,125,429, - 257,157,217,85,267,117,337,447,219,501,41,41,193,509,131,207, - 505,421,149,111,177,167,223,291,91,29,305,151,177,337,183, - 361,435,307,507,77,181,507,315,145,423,71,103,493,271,469, - 339,237,437,483,31,219,61,131,391,233,219,69,57,459,225,421, - 7,461,111,451,277,185,193,125,251,199,73,71,7,409,417,149, - 193,53,437,29,467,229,31,35,75,105, - 503,75,317,401,367,131,365,441,433,93,377,405,465,259,283, - 443,143,445,3,461,329,309,77,323,155,347,45,381,315,463,207, - 321,157,109,479,313,345,167,439,307,235,473,79,101,245,19, - 381,251,35,25,107,187,115,113,321,115,445,61,77,293,405,13, - 53,17,171,299,41,79,3,485,331,13,257,59,201,497,81,451,199, - 171,81,253,365,75,451,149,483,81,453,469,485,305,163,401,15, - 91,3,129,35,239,355,211,387,101,299,67,375,405,357,267,363, - 79,83,437,457,39,97,473,289,179,57,23,49,79,71,341,287,95, - 229,271,475,49,241,261,495,353,381,13,291,37,251,105,399,81, - 89,265,507,205,145,331,129,119,503,249,1,289,463,163,443,63, - 123,361,261,49,429,137,355,175,507,59,277,391,25,185,381,197, - 39,5,429,119,247,177,329,465,421,271,467,151,45,429,137,471, - 11,17,409,347,199,463,177,11,51,361,95,497,163,351,127,395, - 511,327,353,49,105,151,321,331,329,509,107,109,303,467,287, - 161,45,385,289,363,331,265,407,37,433,315,343,63,51,185,71, - 27,267, - 503,239,293,245,281,297,75,461,371, - 129,189,189,339,287,111,111,379,93,27,185,347,337,247,507, - 161,231,43,499,73,327,263,331,249,493,37,25,115,3,167,197, - 127,357,497,103,125,191,165,55,101,95,79,351,341,43,125,135, - 173,289,373,133,421,241,281,213,177,363,151,227,145,363,239, - 431,81,397,241,67,291,255,405,421,399,75,399,105,329,41,425, - 7,283,375,475,427,277,209,411,3,137,195,289,509,121,55,147, - 275,251,19,129,285,415,487,491,193,219,403,23,97,65,285,75, - 21,373,261,339,239,495,415,333,107,435,297,213,149,463,199, - 323,45,19,301,121,499,187,229,63,425,99,281,35,125,349,87, - 101,59,195,511,355,73,263,243,101,165,141,11,389,219,187,449, - 447,393,477,305,221,51,355,209,499,479,265,377,145,411,173, - 11,433,483,135,385,341,89,209,391,33,395,319,451,119,341,227, - 375,61,331,493,411,293,47,203,375,167,395,155,5,237,361,489, - 127,21,345,101,371,233,431,109,119,277,125,263,73,135,123,83, - 123,405,69,75,287,401,23,283,393,41,379,431,11,475,505,19, - 365,265,271, - 499,489,443,165,91,83,291,319,199, - 107,245,389,143,137,89,125,281,381,215,131,299,249,375,455, - 43,73,281,217,297,229,431,357,81,357,171,451,481,13,387,491, - 489,439,385,487,177,393,33,71,375,443,129,407,395,127,65,333, - 309,119,197,435,497,373,71,379,509,387,159,265,477,463,449, - 47,353,249,335,505,89,141,55,235,187,87,363,93,363,101,67, - 215,321,331,305,261,411,491,479,65,307,469,415,131,315,487, - 83,455,19,113,163,503,99,499,251,239,81,167,391,255,317,363, - 359,395,419,307,251,267,171,461,183,465,165,163,293,477,223, - 403,389,97,335,357,297,19,469,501,249,85,213,311,265,379,297, - 283,393,449,463,289,159,289,499,407,129,137,221,43,89,403, - 271,75,83,445,453,389,149,143,423,499,317,445,157,137,453, - 163,87,23,391,119,427,323,173,89,259,377,511,249,31,363,229, - 353,329,493,427,57,205,389,91,83,13,219,439,45,35,371,441,17, - 267,501,53,25,333,17,201,475,257,417,345,381,377,55,403,77, - 389,347,363,211,413,419,5,167,219,201,285,425,11,77,269,489, - 281,403,79, - 425,125,81,331,437,271,397,299,475, - 271,249,413,233,261,495,171,69,27,409,21,421,367,81,483,255, - 15,219,365,497,181,75,431,99,325,407,229,281,63,83,493,5,113, - 15,271,37,87,451,299,83,451,311,441,47,455,47,253,13,109,369, - 347,11,409,275,63,441,15}, - /* [9][*] */ - { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, - 519,307,931,1023,517,771,151,1023, - 539,725,45,927,707,29,125,371,275,279,817,389,453,989,1015, - 29,169,743,99,923,981,181,693,309,227,111,219,897,377,425, - 609,227,19,221,143,581,147,919,127,725,793,289,411,835,921, - 957,443,349,813,5,105,457,393,539,101,197,697,27,343,515,69, - 485,383,855,693,133,87,743,747,475,87,469,763,721,345,479, - 965,527,121,271,353,467,177,245,627,113,357,7,691,725,355, - 889,635,737,429,545,925,357,873,187,351,677,999,921,477,233, - 765,495,81,953,479,89,173,473,131,961,411,291,967,65,511,13, - 805,945,369,827,295,163,835,259,207,331,29,315,999,133,967, - 41,117,677,471,717,881,755,351,723,259,879,455,721,289,149, - 199,805,987,851,423,597,129,11,733,549,153,285,451,559,377, - 109,357,143,693,615,677,701,475,767,85,229,509,547,151,389, - 711,785,657,319,509,99,1007,775,359,697,677,85,497,105,615, - 891,71,449,835,609,377,693,665,627,215,911,503,729,131,19, - 895,199,161,239,633,1013,537,255,23,149,679,1021,595,199,557, - 659,251,829,727,439,495,647,223, - 949,625,87,481,85,799,917,769,949, - 739,115,499,945,547,225,1015,469,737,495,353,103,17,665,639, - 525,75,447,185,43,729,577,863,735,317,99,17,477,893,537,519, - 1017,375,297,325,999,353,343,729,135,489,859,267,141,831,141, - 893,249,807,53,613,131,547,977,131,999,175,31,341,739,467, - 675,241,645,247,391,583,183,973,433,367,131,467,571,309,385, - 977,111,917,935,473,345,411,313,97,149,959,841,839,669,431, - 51,41,301,247,1015,377,329,945,269,67,979,581,643,823,557,91, - 405,117,801,509,347,893,303,227,783,555,867,99,703,111,797, - 873,541,919,513,343,319,517,135,871,917,285,663,301,15,763, - 89,323,757,317,807,309,1013,345,499,279,711,915,411,281,193, - 739,365,315,375,809,469,487,621,857,975,537,939,585,129,625, - 447,129,1017,133,83,3,415,661,53,115,903,49,79,55,385,261, - 345,297,199,385,617,25,515,275,849,401,471,377,661,535,505, - 939,465,225,929,219,955,659,441,117,527,427,515,287,191,33, - 389,197,825,63,417,949,35,571,9,131,609,439,95,19,569,893, - 451,397,971,801, - 125,471,187,257,67,949,621,453,411, - 621,955,309,783,893,597,377,753,145,637,941,593,317,555,375, - 575,175,403,571,555,109,377,931,499,649,653,329,279,271,647, - 721,665,429,957,803,767,425,477,995,105,495,575,687,385,227, - 923,563,723,481,717,111,633,113,369,955,253,321,409,909,367, - 33,967,453,863,449,539,781,911,113,7,219,725,1015,971,1021, - 525,785,873,191,893,297,507,215,21,153,645,913,755,371,881, - 113,903,225,49,587,201,927,429,599,513,97,319,331,833,325, - 887,139,927,399,163,307,803,169,1019,869,537,907,479,335,697, - 479,353,769,787,1023,855,493,883,521,735,297,1011,991,879, - 855,591,415,917,375,453,553,189,841,339,211,601,57,765,745, - 621,209,875,639,7,595,971,263,1009,201,23,77,621,33,535,963, - 661,523,263,917,103,623,231,47,301,549,337,675,189,357,1005, - 789,189,319,721,1005,525,675,539,191,813,917,51,167,415,579, - 755,605,721,837,529,31,327,799,961,279,409,847,649,241,285, - 545,407,161,591,73,313,811,17,663,269,261,37,783,127,917,231, - 577,975,793, - 921,343,751,139,221,79,817,393,545, - 11,781,71,1,699,767,917,9,107,341,587,903,965,599,507,843, - 739,579,397,397,325,775,565,925,75,55,979,931,93,957,857,753, - 965,795,67,5,87,909,97,995,271,875,671,613,33,351,69,811,669, - 729,401,647,241,435,447,721,271,745,53,775,99,343,451,427, - 593,339,845,243,345,17,573,421,517,971,499,435,769,75,203, - 793,985,343,955,735,523,659,703,303,421,951,405,631,825,735, - 433,841,485,49,749,107,669,211,497,143,99,57,277,969,107,397, - 563,551,447,381,187,57,405,731,769,923,955,915,737,595,341, - 253,823,197,321,315,181,885,497,159,571,981,899,785,947,217, - 217,135,753,623,565,717,903,581,955,621,361,869,87,943,907, - 853,353,335,197,771,433,743,195,91,1023,63,301,647,205,485, - 927,1003,987,359,577,147,141,1017,701,273,89,589,487,859,343, - 91,847,341,173,287,1003,289,639,983,685,697,35,701,645,911, - 501,705,873,763,745,657,559,699,315,347,429,197,165,955,859, - 167,303,833,531,473,635,641,195,589,821,205,3,635,371,891, - 249,123, - 77,623,993,401,525,427,71,655,951, - 357,851,899,535,493,323,1003,343,515,859,1017,5,423,315,1011, - 703,41,777,163,95,831,79,975,235,633,723,297,589,317,679,981, - 195,399,1003,121,501,155}, - /* [10][*] */ - { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, - 7,2011,1001,49,825,415,1441,383,1581, - 623,1621,1319,1387,619,839,217,75,1955,505,281,1629,1379,53, - 1111,1399,301,209,49,155,1647,631,129,1569,335,67,1955,1611, - 2021,1305,121,37,877,835,1457,669,1405,935,1735,665,551,789, - 1543,1267,1027,1,1911,163,1929,67,1975,1681,1413,191,1711, - 1307,401,725,1229,1403,1609,2035,917,921,1789,41,2003,187,67, - 1635,717,1449,277,1903,1179,363,1211,1231,647,1261,1029,1485, - 1309,1149,317,1335,171,243,271,1055,1601,1129,1653,205,1463, - 1681,1621,197,951,573,1697,1265,1321,1805,1235,1853,1307,945, - 1197,1411,833,273,1517,1747,1095,1345,869,57,1383,221,1713, - 335,1751,1141,839,523,1861,1105,389,1177,1877,805,93,1591, - 423,1835,99,1781,1515,1909,1011,303,385,1635,357,973,1781, - 1707,1363,1053,649,1469,623,1429,1241,1151,1055,503,921,3, - 349,1149,293,45,303,877,1565,1583,1001,663,1535,395,1141, - 1481,1797,643,1507,465,2027,1695,367,937,719,545,1991,83,819, - 239,1791,1461,1647,1501,1161,1629,139,1595,1921,1267,1415, - 509,347,777,1083,363,269,1015, - 1809,1105,1429,1471,2019,381,2025, - 1223,827,1733,887,1321,803,1951,1297,1995,833,1107,1135,1181, - 1251,983,1389,1565,273,137,71,735,1005,933,67,1471,551,457, - 1667,1729,919,285,1629,1815,653,1919,1039,531,393,1411,359, - 221,699,1485,471,1357,1715,595,1677,153,1903,1281,215,781, - 543,293,1807,965,1695,443,1985,321,879,1227,1915,839,1945, - 1993,1165,51,557,723,1491,817,1237,947,1215,1911,1225,1965, - 1889,1503,1177,73,1767,303,177,1897,1401,321,921,217,1779, - 327,1889,333,615,1665,1825,1639,237,1205,361,129,1655,983, - 1089,1171,401,677,643,749,303,1407,1873,1579,1491,1393,1247, - 789,763,49,5,1607,1891,735,1557,1909,1765,1777,1127,813,695, - 97,731,1503,1751,333,769,865,693,377,1919,957,1359,1627,1039, - 1783,1065,1665,1917,1947,991,1997,841,459,221,327,1595,1881, - 1269,1007,129,1413,475,1105,791,1983,1359,503,691,659,691, - 343,1375,1919,263,1373,603,1383,297,781,145,285,767,1739, - 1715,715,317,1333,85,831,1615,81,1667,1467,1457,1453,1825, - 109,387,1207,2039,213,1351,1329,1173, - 57,1769,951,183,23,451,1155,1551, - 2037,811,635,1671,1451,863,1499,1673,363,1029,1077,1525,277, - 1023,655,665,1869,1255,965,277,1601,329,1603,1901,395,65, - 1307,2029,21,1321,543,1569,1185,1905,1701,413,2041,1697,725, - 1417,1847,411,211,915,1891,17,1877,1699,687,1089,1973,1809, - 851,1495,1257,63,1323,1307,609,881,1543,177,617,1505,1747, - 1537,925,183,77,1723,1877,1703,397,459,521,257,1177,389,1947, - 1553,1583,1831,261,485,289,1281,1543,1591,1123,573,821,1065, - 1933,1373,2005,905,207,173,1573,1597,573,1883,1795,1499,1743, - 553,335,333,1645,791,871,1157,969,557,141,223,1129,1685,423, - 1069,391,99,95,1847,531,1859,1833,1833,341,237,1997,1799,409, - 431,1917,363,335,1039,1085,1657,1975,1527,1111,659,389,899, - 595,1439,1861,1979,1569,1087,1009,165,1895,1481,1583,29,1193, - 1673,1075,301,1081,1377,1747,1497,1103,1789,887,739,1577,313, - 1367,1299,1801,1131,1837,73,1865,1065,843,635,55,1655,913, - 1037,223,1871,1161,461,479,511,1721,1107,389,151,35,375,1099, - 937,1185,1701,769,639,1633, - 1609,379,1613,2031,685,289,975,671, - 1599,1447,871,647,99,139,1427,959,89,117,841,891,1959,223, - 1697,1145,499,1435,1809,1413,1445,1675,171,1073,1349,1545, - 2039,1027,1563,859,215,1673,1919,1633,779,411,1845,1477,1489, - 447,1545,351,1989,495,183,1639,1385,1805,1097,1249,1431,1571, - 591,697,1509,709,31,1563,165,513,1425,1299,1081,145,1841, - 1211,941,609,845,1169,1865,1593,347,293,1277,157,211,93,1679, - 1799,527,41,473,563,187,1525,575,1579,857,703,1211,647,709, - 981,285,697,163,981,153,1515,47,1553,599,225,1147,381,135, - 821,1965,609,1033,983,503,1117,327,453,2005,1257,343,1649, - 1199,599,1877,569,695,1587,1475,187,973,233,511,51,1083,665, - 1321,531,1875,1939,859,1507,1979,1203,1965,737,921,1565,1943, - 819,223,365,167,1705,413,1577,745,1573,655,1633,1003,91,1123, - 477,1741,1663,35,715,37,1513,815,941,1379,263,1831,1735,1111, - 1449,353,1941,1655,1349,877,285,1723,125,1753,985,723,175, - 439,791,1051,1261,717,1555,1757,1777,577,1583,1957,873,331, - 1163,313,1,1963,963,1905,821, - 1677,185,709,545,1723,215,1885, - 1249,583,1803,839,885,485,413,1767,425,129,1035,329,1263, - 1881,1779,1565,359,367,453,707,1419,831,1889,887,1871,1869, - 747,223,1547,1799,433,1441,553,2021,1303,1505,1735,1619,1065, - 1161,2047,347,867,881,1447,329,781,1065,219,589,645,1257, - 1833,749,1841,1733,1179,1191,1025,1639,1955,1423,1685,1711, - 493,549,783,1653,397,895,233,759,1505,677,1449,1573,1297, - 1821,1691,791,289,1187,867,1535,575,183}, - /* [11][*] */ - { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, - 3915,97,3047,937,2897,953,127,1201, - 3819,193,2053,3061,3759,1553,2007,2493,603,3343,3751,1059, - 783,1789,1589,283,1093,3919,2747,277,2605,2169,2905,721,4069, - 233,261,1137,3993,3619,2881,1275,3865,1299,3757,1193,733,993, - 1153,2945,3163,3179,437,271,3493,3971,1005,2615,2253,1131, - 585,2775,2171,2383,2937,2447,1745,663,1515,3767,2709,1767, - 3185,3017,2815,1829,87,3341,793,2627,2169,1875,3745,367,3783, - 783,827,3253,2639,2955,3539,1579,2109,379,2939,3019,1999, - 2253,2911,3733,481,1767,1055,4019,4085,105,1829,2097,2379, - 1567,2713,737,3423,3941,2659,3961,1755,3613,1937,1559,2287, - 2743,67,2859,325,2601,1149,3259,2403,3947,2011,175,3389,3915, - 1315,2447,141,359,3609,3933,729,2051,1755,2149,2107,1741, - 1051,3681,471,1055,845,257,1559,1061,2803,2219,1315,1369, - 3211,4027,105,11,1077,2857,337,3553,3503,3917,2665,3823,3403, - 3711,2085,1103,1641,701,4095,2883,1435,653,2363,1597,767,869, - 1825,1117,1297,501,505,149,873,2673,551,1499,2793,3277,2143, - 3663,533,3991,575,1877,1009,3929,473,3009,2595,3249,675,3593, - 2453,1567,973,595,1335,1715,589,85, - 2265,3069,461,1659,2627,1307,1731,1501,1699,3545,3803,2157, - 453,2813,2047,2999,3841,2361,1079,573,69,1363,1597,3427,2899, - 2771,1327,1117,1523,3521,2393,2537,1979,3179,683,2453,453, - 1227,779,671,3483,2135,3139,3381,3945,57,1541,3405,3381,2371, - 2879,1985,987,3017,3031,3839,1401,3749,2977,681,1175,1519, - 3355,907,117,771,3741,3337,1743,1227,3335,2755,1909,3603, - 2397,653,87,2025,2617,3257,287,3051,3809,897,2215,63,2043, - 1757,3671,297,3131,1305,293,3865,3173,3397,2269,3673,717, - 3041,3341,3595,3819,2871,3973,1129,513,871,1485,3977,2473, - 1171,1143,3063,3547,2183,3993,133,2529,2699,233,2355,231, - 3241,611,1309,3829,1839,1495,301,1169,1613,2673,243,3601, - 3669,2813,2671,2679,3463,2477,1795,617,2317,1855,1057,1703, - 1761,2515,801,1205,1311,473,3963,697,1221,251,381,3887,1761, - 3093,3721,2079,4085,379,3601,3845,433,1781,29,1897,1599,2163, - 75,3475,3957,1641,3911,2959,2833,1279,1099,403,799,2183,2699, - 1711,2037,727,289,1785,1575,3633,2367,1261,3953,1735,171, +static const uint32_t sobol_minit[MAXDEG + 1][MAXDIM - 1] = { + /* [0][*] */ + {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1}, + /* [1][*] */ + {0, + 1, 3, 1, 3, 1, 3, 3, 1, 3, 1, 3, 1, 3, 1, 1, 3, 1, 3, 1, 3, + 1, 3, 3, 1, 1, 1, 3, 1, 3, 1, 3, 3, 1, 3, 1, 1, 1, 3, 1, 3, 1, 1, 1, 3, 3, 1, 3, 3, 1, 1, + 3, 3, 1, 3, 3, 3, 1, 3, 1, 3, 1, 1, 3, 3, 1, 1, 1, 1, 3, 1, 1, 3, 1, 1, 1, 3, 3, 1, 3, 3, + 1, 3, 3, 3, 1, 3, 3, 3, 1, 3, 3, 1, 3, 3, 3, 1, 3, 1, 3, 1, 1, 3, 3, 1, 3, 3, 1, 1, 1, 3, + 3, 1, 3, 3, 1, 3, 1, 1, 3, 3, 3, 1, 1, 1, 3, 1, 1, 3, 1, 1, 3, 3, 1, 3, 1, 3, 3, 3, 3, 1, + 1, 1, 3, 3, 1, 1, 3, 1, 1, 1, 1, 1, 1, 3, 1, 3, 1, 1, 1, 3, 1, 3, 1, 3, 3, 3, 1, 1, 3, 3, + 1, 3, 1, 3, 1, 1, 3, 1, 3, 1, 3, 1, 3, 1, 1, 1, 3, 3, 1, 3, 3, 1, 3, 1, 1, 1, 3, 1, 3, 1, + 1, 3, 1, 1, 3, 3, 1, 1, 3, 3, 3, 1, 3, 3, 3, 1, 3, 1, 3, 1, 1, 1, 3, 1, 1, 1, 3, 1, 1, 1, + 1, 1, 3, 3, 3, 1, 1, 1, 1, 3, 3, 3, 1, 3, 3, 1, 1, 1, 1, 3, 1, 1, 3, 1, 3, 3, 1, 1, 3, 3, + 1, 1, 1, 1, 3, 1, 3, 3, 1, 3, 3, 1, 1, 1, 3, 3, 3, 1, 3, 3, 1, 3, 3, 1, 3, 1, 3, 3, 3, 1, + 3, 1, 1, 3, 1, 3, 1, 1, 1, 3, 3, 3, 1, 1, 3, 1, 3, 1, 1, 1, 1, 1, 1, 3, 1, 1, 3, 1, 3, 3, + 1, 1, 1, 1, 3, 1, 3, 1, 3, 1, 1, 1, 1, 3, 3, 1, 1, 1, 1, 1, 3, 3, 3, 1, 1, 3, 3, 3, 3, 3, + 1, 3, 3, 1, 3, 3, 3, 3, 1, 1, 1, 1, 1, 1, 3, 1, 1, 3, 1, 1, 1, 3, 1, 1, 1, 3, 3, 3, 1, 3, + 1, 1, 3, 3, 3, 1, 3, 3, 1, 3, 1, 3, 3, 1, 3, 3, 3, 1, 1, + 3, 3, 1, 3, 1, 3, 1, 1, 1, 3, 3, 3, 3, 1, 3, 1, 1, 3, 1, + 3, 1, 1, 1, 3, 1, 3, 1, 3, 1, 3, 3, 3, 3, 3, 3, 3, 3, 1, 3, 3, 3, 3, 3, 1, 3, 1, 3, 3, 3, + 1, 3, 1, 3, 1, 3, 3, 1, 3, 3, 3, 3, 3, 3, 3, 3, 3, 1, 1, 1, 1, 1, 1, 3, 3, 1, 1, 3, 3, 1, + 1, 1, 3, 3, 1, 1, 3, 3, 3, 3, 1, 1, 3, 1, 3, 3, 1, 3, 3, 1, 1, 1, 3, 3, 3, 1, 1, 3, 3, 3, + 3, 3, 1, 1, 1, 3, 1, 3, 3, 1, 3, 3, 3, 3, 1, 1, 3, 1, 1, 3, 1, 3, 1, 3, 1, 3, 3, 1, 1, 3, + 3, 1, 3, 3, 1, 3, 3, 1, 1, 3, 1, 3, 3, 1, 1, 3, 1, 3, 1, 3, 1, 1, 3, 3, 1, 1, 1, 3, 3, 1, + 3, 1, 1, 3, 3, 1, 1, 3, 1, 3, 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 3, 1, 3, 1, 1, 3, 3, 1, 1, 3, + 1, 3, 1, 3, 3, 3, 1, 3, 3, 3, 1, 1, 3, 3, 3, 1, 1, 1, 1, 3, 1, 3, 1, 3, 1, 1, 3, 3, 1, 1, + 1, 3, 3, 1, 3, 1, 3, 1, 1, 1, 1, 1, 1, 3, 1, 3, 3, 1, 3, 3, 3, 1, 3, 1, 1, 3, 3, 1, 1, 3, + 3, 1, 1, 1, 3, 1, 3, 3, 1, 1, 3, 1, 1, 3, 1, 3, 1, 1, 1, 3, 3, 3, 3, 1, 1, 3, 3, 1, 1, 1, + 1, 3, 1, 1, 3, 3, 3, 1, 1, 3, 3, 1, 3, 3, 1, 1, 3, 3, 3, 3, 3, 3, 3, 1, 3, 3, 1, 3, 1, 3, + 1, 1, 3, 3, 1, 1, 1, 3, 1, 3, 3, 1, 3, 3, 1, 3, 1, 1, 3, 3, 3, 1, 1, 1, 3, 1, 1, 1, 3, 3, + 3, 1, 3, 3, 1, 3, 1, 1, 3, 3, 3, 1, 3, 3, 1, 1, 1, 3, 1, 3, 3, 3, 3, 3, 3, 3, 3, 1, 3, 3, + 1, 3, 1, 1, 3, 3, 3, 1, 3, 3, 3, 3, 3, 1, 3, 3, 3, 1, 1, 1, + 3, 3, 1, 3, 3, 1, 3, 1, 3, 1, 3, 1, 3, 3, 3, 3, 3, 3, + 1, 1, 3, 1, 3, 1, 1, 1, 1, 1, 3, 1, 1, 1, 3, 1, 3, 1, 1, 3, 3, 3, 1, 3, 1, 3, 1, 1, 3, 1, + 3, 3, 1, 3, 1, 3, 3, 1, 3, 3, 1, 3, 3, 3, 3, 3, 3, 1, 3, 1, 1, 3, 3, 3, 1, 1, 3, 3, 3, 3, + 3, 3, 3, 1, 3, 3, 3, 3, 1, 3, 1, 3, 3, 3, 1, 3, 1, 3, 1, 1, 1, 3, 3, 1, 3, 1, 1, 3, 3, 1, + 3, 1, 1, 1, 1, 3, 1, 3, 1, 1, 3, 1, 3, 1, 3, 3, 3, 3, 3, 3, 1, 3, 3, 3, 3, 1, 3, 3, 1, 3, + 3, 3, 3, 3, 1, 1, 1, 1, 3, 3, 3, 1, 3, 3, 1, 1, 3, 3, 1, 1, 3, 3, 1, 3, 1, 1, 3, 1, 3, 3, + 3, 3, 3, 1, 3, 1, 1, 3, 3, 3, 3, 1, 3, 1, 1, 3, 3, 3, 3, 3, 3, 1, 1, 3, 1, 3, 1, 1, 3, 1, + 1, 1, 1, 3, 3, 1, 1, 3, 1, 1, 1, 3, 1, 3, 1, 1, 3, 3, 1, 3, 1, 1, 3, 3, 3, 3, 3, 1, 3, 1, + 1, 1, 3, 1, 1, 1, 3, 1, 1, 3, 1, 3, 3, 3, 3, 3, 1, 1, 1, 3, 3, 3, 3, 1, 3, 3, 3, 3, 1, 1, + 3, 3, 3, 1, 3, 1, 1, 3, 3, 1, 3, 3, 1, 1, 1, 1, 1, 3, 1, 1, 3, 3, 1, 1, 1, 3, 1, 1, 3, 3, + 1, 3, 3, 3, 3, 3, 3, 3, 3, 1, 1, 3, 3, 1, 1, 3, 1, 3, 3, 3, 3, 3, 1}, + /* [2][*] */ + {0, 0, + 7, 5, 1, 3, 3, 7, 5, 5, 7, 7, 1, 3, 3, 7, 5, 1, 1, 5, 3, 7, + 1, 7, 5, 1, 3, 7, 7, 1, 1, 1, 5, 7, 7, 5, 1, 3, 3, 7, 5, 5, 5, 3, 3, 3, 1, 1, 5, 1, 1, 5, + 3, 3, 3, 3, 1, 3, 7, 5, 7, 3, 7, 1, 3, 3, 5, 1, 3, 5, 5, 7, 7, 7, 1, 1, 3, 3, 1, 1, 5, 1, + 5, 7, 5, 1, 7, 5, 3, 3, 1, 5, 7, 1, 7, 5, 1, 7, 3, 1, 7, 1, 7, 3, 3, 5, 7, 3, 3, 5, 1, 3, + 3, 1, 3, 5, 1, 3, 3, 3, 7, 1, 1, 7, 3, 1, 3, 7, 5, 5, 7, 5, 5, 3, 1, 3, 3, 3, 1, 3, 3, 7, + 3, 3, 1, 7, 5, 1, 7, 7, 5, 7, 5, 1, 3, 1, 7, 3, 7, 3, 5, 7, 3, 1, 3, 3, 3, 1, 5, 7, 3, 3, + 7, 7, 7, 5, 3, 1, 7, 1, 3, 7, 5, 3, 3, 3, 7, 1, 1, 3, 1, 5, 7, 1, 3, 5, 3, 5, 3, 3, 7, 5, + 5, 3, 3, 1, 3, 7, 7, 7, 1, 5, 7, 1, 3, 1, 1, 7, 1, 3, 1, 7, 1, 5, 3, 5, 3, 1, 1, 5, 5, 3, + 3, 5, 7, 1, 5, 3, 7, 7, 3, 5, 3, 3, 1, 7, 3, 1, 3, 5, 7, 1, 3, 7, 1, 5, 1, 3, 1, 5, 3, 1, + 7, 1, 5, 5, 5, 3, 7, 1, 1, 7, 3, 1, 1, 7, 5, 7, 5, 7, 7, 3, 7, 1, 3, 7, 7, 3, 5, 1, 1, 7, + 1, 5, 5, 5, 1, 5, 1, 7, 5, 5, 7, 1, 1, 7, 1, 7, 7, 1, 1, 3, 3, 3, 7, 7, 5, 3, 7, 3, 1, 3, + 7, 5, 3, 3, 5, 7, 1, 1, 5, 5, 7, 7, 1, 1, 1, 1, 5, 5, 5, 7, 5, 7, 1, 1, 3, 5, 1, 3, 3, 7, + 3, 7, 5, 3, 5, 3, 1, 7, 1, 7, 7, 1, 1, 7, 7, 7, 5, 5, 1, 1, 7, 5, 5, 7, 5, 1, 1, 5, 5, 5, + 5, 5, 5, 1, 3, 1, 5, 7, 3, 3, 5, 7, 3, 7, 1, 7, 7, 1, 3, + 5, 1, 5, 5, 3, 7, 3, 7, 7, 5, 7, 5, 7, 1, 1, 5, 3, 5, 1, + 5, 3, 7, 1, 5, 7, 7, 3, 5, 1, 3, 5, 1, 5, 3, 3, 3, 7, 3, 5, 1, 3, 7, 7, 3, 7, 5, 3, 3, 1, + 7, 5, 1, 1, 3, 7, 1, 7, 1, 7, 3, 7, 3, 5, 7, 3, 5, 3, 1, 1, 1, 5, 7, 7, 3, 3, 1, 1, 1, 5, + 5, 7, 3, 1, 1, 3, 3, 7, 3, 3, 5, 1, 3, 7, 3, 3, 7, 3, 5, 7, 5, 7, 7, 3, 3, 5, 1, 3, 5, 3, + 1, 3, 5, 1, 1, 3, 7, 7, 1, 5, 1, 3, 7, 3, 7, 3, 5, 1, 7, 1, 1, 3, 5, 3, 7, 1, 5, 5, 1, 1, + 3, 1, 3, 3, 7, 1, 7, 3, 1, 7, 3, 1, 7, 3, 5, 3, 5, 7, 3, 3, 3, 5, 1, 7, 7, 1, 3, 1, 3, 7, + 7, 1, 3, 7, 3, 1, 5, 3, 1, 1, 1, 5, 3, 3, 7, 1, 5, 3, 5, 1, 3, 1, 3, 1, 5, 7, 7, 1, 1, 5, + 3, 1, 5, 1, 1, 7, 7, 3, 5, 5, 1, 7, 1, 5, 1, 1, 3, 1, 5, 7, 5, 7, 7, 1, 5, 1, 1, 3, 5, 1, + 5, 5, 3, 1, 3, 1, 5, 5, 3, 3, 3, 3, 1, 1, 3, 1, 3, 5, 5, 7, 5, 5, 7, 5, 7, 1, 3, 7, 7, 3, + 5, 5, 7, 5, 5, 3, 3, 3, 1, 7, 1, 5, 5, 5, 3, 3, 5, 1, 3, 1, 3, 3, 3, 7, 1, 7, 7, 3, 7, 1, + 1, 5, 7, 1, 7, 1, 7, 7, 1, 3, 7, 5, 1, 3, 5, 5, 5, 1, 1, 7, 1, 7, 1, 7, 7, 3, 1, 1, 5, 1, + 5, 1, 5, 3, 5, 5, 5, 5, 5, 3, 3, 7, 3, 3, 5, 5, 3, 7, 1, 5, 7, 5, 1, 5, 5, 3, 5, 5, 7, 5, + 3, 5, 5, 5, 1, 5, 5, 5, 5, 1, 3, 5, 3, 1, 7, 5, 5, 7, 1, 5, 3, 3, 1, 5, 3, 7, 1, 7, 5, 1, + 1, 3, 1, 1, 7, 1, 5, 5, 3, 7, 3, 7, 5, 3, 1, 1, 3, 1, 3, 5, + 5, 7, 5, 3, 7, 7, 7, 3, 7, 3, 7, 1, 3, 1, 7, 7, 1, 7, + 3, 7, 3, 7, 3, 7, 3, 5, 1, 1, 7, 3, 1, 5, 5, 7, 1, 5, 5, 5, 7, 1, 5, 5, 1, 5, 5, 3, 1, 3, + 1, 7, 3, 1, 3, 5, 7, 7, 7, 1, 1, 7, 3, 1, 5, 5, 5, 1, 1, 1, 1, 1, 5, 3, 5, 1, 3, 5, 3, 1, + 1, 1, 1, 3, 7, 3, 7, 5, 7, 1, 5, 5, 7, 5, 3, 3, 7, 5, 3, 1, 1, 3, 1, 3, 1, 1, 3, 7, 1, 7, + 1, 1, 5, 1, 7, 5, 3, 7, 3, 5, 3, 1, 1, 5, 5, 1, 7, 7, 3, 7, 3, 7, 1, 5, 1, 5, 3, 7, 3, 5, + 7, 7, 7, 3, 3, 1, 1, 5, 5, 3, 7, 1, 1, 1, 3, 5, 3, 1, 1, 3, 3, 7, 5, 1, 1, 3, 7, 1, 5, 7, + 3, 7, 5, 5, 7, 3, 5, 3, 1, 5, 3, 1, 1, 7, 5, 1, 7, 3, 7, 5, 1, 7, 1, 7, 7, 1, 1, 7, 1, 5, + 5, 1, 1, 7, 5, 7, 1, 5, 3, 5, 3, 3, 7, 1, 5, 1, 1, 5, 5, 3, 3, 7, 5, 5, 1, 1, 1, 3, 1, 5, + 7, 7, 1, 7, 5, 7, 3, 7, 3, 1, 3, 7, 3, 1, 5, 5, 3, 5, 1, 3, 5, 5, 5, 1, 1, 7, 7, 1, 5, 5, + 1, 3, 5, 1, 5, 3, 5, 3, 3, 7, 5, 7, 3, 7, 3, 1, 3, 7, 7, 3, 3, 1, 1, 3, 3, 3, 3, 3, 5, 5, + 3, 3, 3, 1, 3, 5, 7, 7, 1, 5, 7, 3, 7, 1, 1, 3, 5, 7, 5, 3, 3, 3}, + /* [3][*] */ + {0, 0, 0, 0, + 1, 7, 9, 13, 11, 1, 3, 7, 9, 5, 13, 13, 11, 3, 15, 5, 3, + 15, 7, 9, 13, 9, 1, 11, 7, 5, 15, 1, 15, 11, 5, 11, 1, 7, 9, 7, 7, 1, 15, 15, 15, 13, + 3, 3, 15, 5, 9, 7, 13, 3, 7, 5, 11, 9, 1, 9, 1, 5, 7, 13, 9, 9, 1, 7, 3, 5, 1, 11, 11, + 13, 7, 7, 9, 9, 1, 1, 3, 9, 15, 1, 5, 13, 1, 9, 9, 9, 9, 9, 13, 11, 3, 5, 11, 11, 13, + 5, 3, 15, 1, 11, 11, 7, 13, 15, 11, 13, 9, 11, 15, 15, 13, 3, 15, 7, 9, 11, 13, 11, + 9, 9, 5, 13, 9, 1, 13, 7, 7, 7, 7, 7, 5, 9, 7, 13, 11, 9, 11, 15, 3, 13, 11, 1, 11, 3, + 3, 9, 11, 1, 7, 1, 15, 15, 3, 1, 9, 1, 7, 13, 11, 3, 13, 11, 7, 3, 3, 5, 13, 11, 5, + 11, 1, 3, 9, 7, 15, 7, 5, 13, 7, 9, 13, 15, 13, 9, 7, 15, 7, 9, 5, 11, 11, 13, 13, 9, + 3, 5, 13, 9, 11, 15, 11, 7, 1, 7, 13, 3, 13, 3, 13, 9, 15, 7, 13, 13, 3, 13, 15, 15, + 11, 9, 13, 9, 15, 1, 1, 15, 11, 11, 7, 1, 11, 13, 9, 13, 3, 5, 11, 13, 9, 9, 13, 1, + 11, 15, 13, 3, 13, 7, 15, 1, 15, 3, 3, 11, 7, 13, 7, 7, 9, 7, 5, 15, 9, 5, 5, 7, 15, + 13, 15, 5, 15, 5, 3, 1, 11, 7, 1, 5, 7, 9, 3, 11, 1, 15, 1, 3, 15, 11, 13, 5, 13, 1, + 7, 1, 15, 7, 5, 1, 1, 15, 13, 11, 11, 13, 5, 11, 7, 9, 7, 1, 5, 3, 9, 5, 5, 11, 5, 1, + 7, 1, 11, 7, 9, 13, 15, 13, 3, 1, 11, 13, 15, 1, 1, 11, 9, 13, 3, 13, 11, 15, 13, 9, + 9, 9, 5, 5, 5, 5, 1, 15, 5, 9, + 11, 7, 15, 5, 3, 13, 5, 3, 11, 5, 1, 11, 13, 9, 11, + 3, 7, 13, 15, 1, 7, 11, 1, 13, 1, 15, 1, 9, 7, 3, 9, 11, 1, 9, 13, 13, 3, 11, 7, 9, 1, + 7, 15, 9, 1, 5, 13, 5, 11, 3, 9, 15, 11, 13, 5, 1, 7, 7, 5, 13, 7, 7, 9, 5, 11, 11, 1, + 1, 15, 3, 13, 9, 13, 9, 9, 11, 5, 5, 13, 15, 3, 9, 15, 3, 11, 11, 15, 15, 3, 11, 15, + 15, 3, 1, 3, 1, 3, 3, 1, 3, 13, 1, 11, 5, 15, 7, 15, 9, 1, 7, 1, 9, 11, 15, 1, 13, 9, + 13, 11, 7, 3, 7, 3, 13, 7, 9, 7, 7, 3, 3, 9, 9, 7, 5, 11, 13, 13, 7, 7, 15, 9, 5, 5, 3, + 3, 13, 3, 9, 3, 1, 11, 1, 3, 11, 15, 11, 11, 11, 9, 13, 7, 9, 15, 9, 11, 1, 3, 3, 9, + 7, 15, 13, 13, 7, 15, 9, 13, 9, 15, 13, 15, 9, 13, 1, 11, 7, 11, 3, 13, 5, 1, 7, 15, + 3, 13, 7, 13, 13, 11, 3, 5, 3, 13, 11, 9, 9, 3, 11, 11, 7, 9, 13, 11, 7, 15, 13, 7, + 5, 3, 1, 5, 15, 15, 3, 11, 1, 7, 3, 15, 11, 5, 5, 3, 5, 5, 1, 15, 5, 1, 5, 3, 7, 5, 11, + 3, 13, 9, 13, 15, 5, 3, 5, 9, 5, 3, 11, 1, 13, 9, 15, 3, 5, 11, 9, 1, 3, 15, 9, 9, 9, + 11, 7, 5, 13, 1, 15, 3, 13, 9, 13, 5, 1, 5, 1, 13, 13, 7, 7, 1, 9, 5, 11, 9, 11, 13, + 3, 15, 15, 13, 15, 7, 5, 7, 9, 7, 9, 9, 9, 11, 9, 3, 11, 15, 13, 13, 5, 9, 15, 1, 1, + 9, 5, 13, 3, 13, 15, 3, 1, 3, 11, 13, 1, 15, 9, 9, 3, 1, 9, 1, 9, 1, 13, 11, 15, 7, + 11, 15, 13, 15, 1, 9, 9, 7, + 3, 5, 11, 7, 3, 9, 5, 15, 7, 5, 3, 13, 7, 1, 1, 9, + 15, 15, 15, 11, 3, 5, 15, 13, 7, 15, 15, 11, 11, 9, 5, 15, 9, 7, 3, 13, 1, 1, 5, 1, + 3, 1, 7, 1, 1, 5, 1, 11, 11, 9, 9, 5, 13, 7, 7, 7, 1, 1, 9, 9, 11, 11, 15, 7, 5, 5, 3, + 11, 1, 3, 7, 13, 7, 7, 7, 3, 15, 15, 11, 9, 3, 9, 3, 15, 13, 5, 3, 3, 3, 5, 9, 15, 9, + 9, 1, 5, 9, 9, 15, 5, 15, 7, 9, 1, 9, 9, 5, 11, 5, 15, 15, 11, 7, 7, 7, 1, 1, 11, 11, + 13, 15, 3, 13, 5, 1, 7, 1, 11, 3, 13, 15, 3, 5, 3, 5, 7, 3, 9, 9, 5, 1, 7, 11, 9, 3, 5, + 11, 13, 13, 13, 9, 15, 5, 7, 1, 15, 11, 9, 15, 15, 13, 13, 13, 1, 11, 9, 15, 9, 5, + 15, 5, 7, 3, 11, 3, 15, 7, 13, 11, 7, 3, 7, 13, 5, 13, 15, 5, 13, 9, 1, 15, 11, 5, 5, + 1, 11, 3, 3, 7, 1, 9, 7, 15, 9, 9, 3, 11, 15, 7, 1, 3, 1, 1, 1, 9, 1, 5, 15, 15, 7, 5, + 5, 7, 9, 7, 15, 13, 13, 11, 1, 9, 11, 1, 13, 1, 7, 15, 15, 5, 5, 1, 11, 3, 9, 11, 9, + 9, 9, 1, 9, 3, 5, 15, 1, 1, 9, 7, 3, 3, 1, 9, 9, 11, 9, 9, 13, 13, 3, 13, 11, 13, 5, 1, + 5, 5, 9, 9, 3, 13, 13, 9, 15, 9, 11, 7, 11, 9, 13, 9, 1, 15, 9, 7, 7, 1, 7, 9, 9, 15, + 1, 11, 1, 13, 13, 15, 9, 13, 7, 15, 3, 9, 3, 1, 13, 7, 5, 9, 3, 1, 7, 1, 1, 13, 3, 3, + 11, 1, 7, 13, 15, 15, 5, 7, 13, 13, 15, 11, 13, 1, 13, 13, 3, 9, 15, 15, 11, 15, 9, + 15, 1, 13, 15, 1, 1, 5, + 11, 5, 1, 11, 11, 5, 3, 9, 1, 3, 5, 13, 9, 7, 7, 1, + 9, 9, 15, 7, 5, 5, 15, 13, 9, 7, 13, 3, 13, 11, 13, 7, 9, 13, 13, 13, 15, 9, 5, 5, 3, + 3, 3, 1, 3, 15}, + /* [4][*] */ + {0, 0, 0, 0, 0, 0, + 9, 3, 27, 15, 29, 21, 23, 19, 11, 25, 7, 13, 17, 1, + 25, 29, 3, 31, 11, 5, 23, 27, 19, 21, 5, 1, 17, 13, 7, 15, 9, 31, 25, 3, 5, 23, 7, + 3, 17, 23, 3, 3, 21, 25, 25, 23, 11, 19, 3, 11, 31, 7, 9, 5, 17, 23, 17, 17, 25, + 13, 11, 31, 27, 19, 17, 23, 7, 5, 11, 19, 19, 7, 13, 21, 21, 7, 9, 11, 1, 5, 21, + 11, 13, 25, 9, 7, 7, 27, 15, 25, 15, 21, 17, 19, 19, 21, 5, 11, 3, 5, 29, 31, 29, + 5, 5, 1, 31, 27, 11, 13, 1, 3, 7, 11, 7, 3, 23, 13, 31, 17, 1, 27, 11, 25, 1, 23, + 29, 17, 25, 7, 25, 27, 17, 13, 17, 23, 5, 17, 5, 13, 11, 21, 5, 11, 5, 9, 31, 19, + 17, 9, 9, 27, 21, 15, 15, 1, 1, 29, 5, 31, 11, 17, 23, 19, 21, 25, 15, 11, 5, 5, 1, + 19, 19, 19, 7, 13, 21, 17, 17, 25, 23, 19, 23, 15, 13, 5, 19, 25, 9, 7, 3, 21, 17, + 25, 1, 27, 25, 27, 25, 9, 13, 3, 17, 25, 23, 9, 25, 9, 13, 17, 17, 3, 15, 7, 7, 29, + 3, 19, 29, 29, 19, 29, 13, 15, 25, 27, 1, 3, 9, 9, 13, 31, 29, 31, 5, 15, 29, 1, + 19, 5, 9, 19, 5, 15, 3, 5, 7, 15, 17, 17, 23, 11, 9, 23, 19, 3, 17, 1, 27, 9, 9, 17, + 13, 25, 29, 23, 29, 11, 31, 25, 21, 29, 19, 27, 31, 3, 5, 3, 3, 13, 21, 9, 29, 3, + 17, 11, 11, 9, 21, 19, 7, 17, 31, 25, 1, 27, 5, 15, 27, 29, 29, 29, 25, 27, 25, 3, + 21, 17, 25, 13, 15, 17, 13, 23, 9, 3, 11, 7, 9, 9, 7, 17, 7, 1, + 27, 1, 9, 5, 31, 21, 25, 25, 21, 11, 1, 23, 19, 27, + 15, 3, 5, 23, 9, 25, 7, 29, 11, 9, 13, 5, 11, 1, 3, 31, 27, 3, 17, 27, 11, 13, 15, + 29, 15, 1, 15, 23, 25, 13, 21, 15, 3, 29, 29, 5, 25, 17, 11, 7, 15, 5, 21, 7, 31, + 13, 11, 23, 5, 7, 23, 27, 21, 29, 15, 7, 27, 27, 19, 7, 15, 27, 27, 19, 19, 9, 15, + 1, 3, 29, 29, 5, 27, 31, 9, 1, 7, 3, 19, 19, 29, 9, 3, 21, 31, 29, 25, 1, 3, 9, 27, + 5, 27, 25, 21, 11, 29, 31, 27, 21, 29, 17, 9, 17, 13, 11, 25, 15, 21, 11, 19, 31, + 3, 19, 5, 3, 3, 9, 13, 13, 3, 29, 7, 5, 9, 23, 13, 21, 23, 21, 31, 11, 7, 7, 3, 23, + 1, 23, 5, 9, 17, 21, 1, 17, 29, 7, 5, 17, 13, 25, 17, 9, 19, 9, 5, 7, 21, 19, 13, 9, + 7, 3, 9, 3, 15, 31, 29, 29, 25, 13, 9, 21, 9, 31, 7, 15, 5, 31, 7, 15, 27, 25, 19, + 9, 9, 25, 25, 23, 1, 9, 7, 11, 15, 19, 15, 27, 17, 11, 11, 31, 13, 25, 25, 9, 7, + 13, 29, 19, 5, 19, 31, 25, 13, 25, 15, 5, 9, 29, 31, 9, 29, 27, 25, 27, 11, 17, 5, + 17, 3, 23, 15, 9, 9, 17, 17, 31, 11, 19, 25, 13, 23, 15, 25, 21, 31, 19, 3, 11, + 25, 7, 15, 19, 7, 5, 3, 13, 13, 1, 23, 5, 25, 11, 25, 15, 13, 21, 11, 23, 29, 5, + 17, 27, 9, 19, 15, 5, 29, 23, 19, 1, 27, 3, 23, 21, 19, 27, 11, 17, 13, 27, 11, + 31, 23, 5, 9, 21, 31, 29, 11, 21, 17, 15, 7, 15, 7, 9, 21, 27, 25, + 29, 11, 3, 21, 13, 23, 19, 27, 17, 29, 25, 17, 9, + 1, 19, 23, 5, 23, 1, 17, 17, 13, 27, 23, 7, 7, 11, 13, 17, 13, 11, 21, 13, 23, 1, + 27, 13, 9, 7, 1, 27, 29, 5, 13, 25, 21, 3, 31, 15, 13, 3, 19, 13, 1, 27, 15, 17, 1, + 3, 13, 13, 13, 31, 29, 27, 7, 7, 21, 29, 15, 17, 17, 21, 19, 17, 3, 15, 5, 27, 27, + 3, 31, 31, 7, 21, 3, 13, 11, 17, 27, 25, 1, 9, 7, 29, 27, 21, 23, 13, 25, 29, 15, + 17, 29, 9, 15, 3, 21, 15, 17, 17, 31, 9, 9, 23, 19, 25, 3, 1, 11, 27, 29, 1, 31, + 29, 25, 29, 1, 23, 29, 25, 13, 3, 31, 25, 5, 5, 11, 3, 21, 9, 23, 7, 11, 23, 11, 1, + 1, 3, 23, 25, 23, 1, 23, 3, 27, 9, 27, 3, 23, 25, 19, 29, 29, 13, 27, 5, 9, 29, 29, + 13, 17, 3, 23, 19, 7, 13, 3, 19, 23, 5, 29, 29, 13, 13, 5, 19, 5, 17, 9, 11, 11, + 29, 27, 23, 19, 17, 25, 13, 1, 13, 3, 11, 1, 17, 29, 1, 13, 17, 9, 17, 21, 1, 11, + 1, 1, 25, 5, 7, 29, 29, 19, 19, 1, 29, 13, 3, 1, 31, 15, 13, 3, 1, 11, 19, 5, 29, + 13, 29, 23, 3, 1, 31, 13, 19, 17, 5, 5, 1, 29, 23, 3, 19, 25, 19, 27, 9, 27, 13, + 15, 29, 23, 13, 25, 25, 17, 19, 17, 15, 27, 3, 25, 17, 27, 3, 27, 31, 23, 13, 31, + 11, 15, 7, 21, 19, 27, 19, 21, 29, 7, 31, 13, 9, 9, 7, 21, 13, 11, 9, 11, 29, 19, + 11, 19, 21, 5, 29, 13, 7, 19, 19, 27, 23, 31, 1, 27, 21, 7, 3, 7, 11, + 23, 13, 29, 11, 31, 19, 1, 5, 5, 11, 5, 3, 27, 5, + 7, 11, 31, 1, 27, 31, 31, 23, 5, 21, 27, 9, 25, 3, 15, 19, 1, 19, 9, 5, 25, 21, 15, + 25, 29, 15, 21, 11, 19, 15, 3, 7, 13, 11, 25, 17, 1, 5, 31, 13, 29, 23, 9, 5, 29, + 7, 17, 27, 7, 17, 31, 9, 31, 9, 9, 7, 21, 3, 3, 3, 9, 11, 21, 11, 31, 9, 25, 5, 1, + 31, 13, 29, 9, 29, 1, 11, 19, 7, 27, 13, 31, 7, 31, 7, 25, 23, 21, 29, 11, 11, 13, + 11, 27, 1, 23, 31, 21, 23, 21, 19, 31, 5, 31, 25, 25, 19, 17, 11, 25, 7, 13, 1, + 29, 17, 23, 15, 7, 29, 17, 13, 3, 17}, + /* [5][*] */ + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 37, 33, 7, 5, 11, 39, 63, 59, 17, 15, 23, 29, 3, 21, + 13, 31, 25, 9, 49, 33, 19, 29, 11, 19, 27, 15, 25, 63, 55, 17, 63, 49, 19, 41, + 59, 3, 57, 33, 49, 53, 57, 57, 39, 21, 7, 53, 9, 55, 15, 59, 19, 49, 31, 3, 39, 5, + 5, 41, 9, 19, 9, 57, 25, 1, 15, 51, 11, 19, 61, 53, 29, 19, 11, 9, 21, 19, 43, 13, + 13, 41, 25, 31, 9, 11, 19, 5, 53, 37, 7, 51, 45, 7, 7, 61, 23, 45, 7, 59, 41, 1, + 29, 61, 37, 27, 47, 15, 31, 35, 31, 17, 51, 13, 25, 45, 5, 5, 33, 39, 5, 47, 29, + 35, 47, 63, 45, 37, 47, 59, 21, 59, 33, 51, 9, 27, 13, 25, 43, 3, 17, 21, 59, 61, + 27, 47, 57, 11, 17, 39, 1, 63, 21, 59, 17, 13, 31, 3, 31, 7, 9, 27, 37, 23, 31, 9, + 45, 43, 31, 63, 21, 39, 51, 27, 7, 53, 11, 1, 59, 39, 23, 49, 23, 7, 55, 59, 3, + 19, 35, 13, 9, 13, 15, 23, 9, 7, 43, 55, 3, 19, 9, 27, 33, 27, 49, 23, 47, 19, 7, + 11, 55, 27, 35, 5, 5, 55, 35, 37, 9, 33, 29, 47, 25, 11, 47, 53, 61, 59, 3, 53, + 47, 5, 19, 59, 5, 47, 23, 45, 53, 3, 49, 61, 47, 39, 29, 17, 57, 5, 17, 31, 23, + 41, 39, 5, 27, 7, 29, 29, 33, 31, 41, 31, 29, 17, 29, 29, 9, 9, 31, 27, 53, 35, 5, + 61, 1, 49, 13, 57, 29, 5, 21, 43, 25, 57, 49, 37, 27, 11, 61, 37, 49, 5, 63, 63, + 3, 45, 37, 63, 21, 21, 19, 27, 59, 21, 45, 23, 13, 15, 3, 43, 63, 39, 19, + 63, 31, 41, 41, 15, 43, 63, 53, 1, 63, 31, 7, 17, + 11, 61, 31, 51, 37, 29, 59, 25, 63, 59, 47, 15, 27, 19, 29, 45, 35, 55, 39, 19, + 43, 21, 19, 13, 17, 51, 37, 5, 33, 35, 49, 25, 45, 1, 63, 47, 9, 63, 15, 25, 25, + 15, 41, 13, 3, 19, 51, 49, 37, 25, 49, 13, 53, 47, 23, 35, 29, 33, 21, 35, 23, 3, + 43, 31, 63, 9, 1, 61, 43, 3, 11, 55, 11, 35, 1, 63, 35, 49, 19, 45, 9, 57, 51, 1, + 47, 41, 9, 11, 37, 19, 55, 23, 55, 55, 13, 7, 47, 37, 11, 43, 17, 3, 25, 19, 55, + 59, 37, 33, 43, 1, 5, 21, 5, 63, 49, 61, 21, 51, 15, 19, 43, 47, 17, 9, 53, 45, + 11, 51, 25, 11, 25, 47, 47, 1, 43, 29, 17, 31, 15, 59, 27, 63, 11, 41, 51, 29, 7, + 27, 63, 31, 43, 3, 29, 39, 3, 59, 59, 1, 53, 63, 23, 63, 47, 51, 23, 61, 39, 47, + 21, 39, 15, 3, 9, 57, 61, 39, 37, 21, 51, 1, 23, 43, 27, 25, 11, 13, 21, 43, 7, + 11, 33, 55, 1, 37, 35, 27, 61, 39, 5, 19, 61, 61, 57, 59, 21, 59, 61, 57, 25, 55, + 27, 31, 41, 33, 63, 19, 57, 35, 13, 63, 35, 17, 11, 11, 49, 41, 55, 5, 45, 17, + 35, 5, 31, 31, 37, 17, 45, 51, 1, 39, 49, 55, 19, 41, 13, 5, 51, 5, 49, 1, 21, 13, + 17, 59, 51, 11, 3, 61, 1, 33, 37, 33, 61, 25, 27, 59, 7, 49, 13, 63, 3, 33, 3, 15, + 9, 13, 35, 39, 11, 59, 59, 1, 57, 11, 5, 57, 13, 31, 13, 11, 55, 45, 9, 55, 55, + 19, 25, 41, 23, 45, 29, 63, 59, 27, 39, 21, 37, 7, + 61, 49, 35, 39, 9, 29, 7, 25, 23, 57, 5, 19, 15, 33, 49, 37, 25, 17, 45, 29, 15, + 25, 3, 3, 49, 11, 39, 15, 19, 57, 39, 15, 11, 3, 57, 31, 55, 61, 19, 5, 41, 35, + 59, 61, 39, 41, 53, 53, 63, 31, 9, 59, 13, 35, 55, 41, 49, 5, 41, 25, 27, 43, 5, + 5, 43, 5, 5, 17, 5, 15, 27, 29, 17, 9, 3, 55, 31, 1, 45, 45, 13, 57, 17, 3, 61, 15, + 49, 15, 47, 9, 37, 45, 9, 51, 61, 21, 33, 11, 21, 63, 63, 47, 57, 61, 49, 9, 59, + 19, 29, 21, 23, 55, 23, 43, 41, 57, 9, 39, 27, 41, 35, 61, 29, 57, 63, 21, 31, + 59, 35, 49, 3, 49, 47, 49, 33, 21, 19, 21, 35, 11, 17, 37, 23, 59, 13, 37, 35, + 55, 57, 1, 29, 45, 11, 1, 15, 9, 33, 19, 53, 43, 39, 23, 7, 13, 13, 1, 19, 41, 55, + 1, 13, 15, 59, 55, 15, 3, 57, 37, 31, 17, 1, 3, 21, 29, 25, 55, 9, 37, 33, 53, 41, + 51, 19, 57, 13, 63, 43, 19, 7, 13, 37, 33, 19, 15, 63, 51, 11, 49, 23, 57, 47, + 51, 15, 53, 41, 1, 15, 37, 61, 11, 35, 29, 33, 23, 55, 11, 59, 19, 61, 61, 45, + 13, 49, 13, 63, 5, 61, 5, 31, 17, 61, 63, 13, 27, 57, 1, 21, 5, 11, 39, 57, 51, + 53, 39, 25, 41, 39, 37, 23, 31, 25, 33, 17, 57, 29, 27, 23, 47, 41, 29, 19, 47, + 41, 25, 5, 51, 43, 39, 29, 7, 31, 45, 51, 49, 55, 17, 43, 49, 45, 9, 29, 3, 5, 47, + 9, 15, 19, + 51, 45, 57, 63, 9, 21, 59, 3, 9, 13, 45, 23, 15, + 31, 21, 15, 51, 35, 9, 11, 61, 23, 53, 29, 51, 45, 31, 29, 5, 35, 29, 53, 35, 17, + 59, 55, 27, 51, 59, 27, 47, 15, 29, 37, 7, 49, 55, 5, 19, 45, 29, 19, 57, 33, 53, + 45, 21, 9, 3, 35, 29, 43, 31, 39, 3, 45, 1, 41, 29, 5, 59, 41, 33, 35, 27, 19, 13, + 25, 27, 43, 33, 35, 17, 17, 23, 7, 35, 15, 61, 61, 53, 5, 15, 23, 11, 13, 43, 55, + 47, 25, 43, 15, 57, 45, 1, 49, 63, 57, 15, 31, 31, 7, 53, 27, 15, 47, 23, 7, 29, + 53, 47, 9, 53, 3, 25, 55, 45, 63, 21, 17, 23, 31, 27, 27, 43, 63, 55, 63, 45, 51, + 15, 27, 5, 37, 43, 11, 27, 5, 27, 59, 21, 7, 39, 27, 63, 35, 47, 55, 17, 17, 17, + 3, 19, 21, 13, 49, 61, 39, 15}, + /* [6][*] */ + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 13, 33, 115, 41, 79, 17, 29, 119, 75, 73, 105, 7, + 59, 65, 21, 3, 113, 61, 89, 45, 107, 21, 71, 79, 19, 71, 61, 41, 57, 121, 87, + 119, 55, 85, 121, 119, 11, 23, 61, 11, 35, 33, 43, 107, 113, 101, 29, 87, 119, + 97, 29, 17, 89, 5, 127, 89, 119, 117, 103, 105, 41, 83, 25, 41, 55, 69, 117, + 49, 127, 29, 1, 99, 53, 83, 15, 31, 73, 115, 35, 21, 89, 5, 1, 91, 53, 35, 95, + 83, 19, 85, 55, 51, 101, 33, 41, 55, 45, 95, 61, 27, 37, 89, 75, 57, 61, 15, + 117, 15, 21, 27, 25, 27, 123, 39, 109, 93, 51, 21, 91, 109, 107, 45, 15, 93, + 127, 3, 53, 81, 79, 107, 79, 87, 35, 109, 73, 35, 83, 107, 1, 51, 7, 59, 33, + 115, 43, 111, 45, 121, 105, 125, 87, 101, 41, 95, 75, 1, 57, 117, 21, 27, 67, + 29, 53, 117, 63, 1, 77, 89, 115, 49, 127, 15, 79, 81, 29, 65, 103, 33, 73, 79, + 29, 21, 113, 31, 33, 107, 95, 111, 59, 99, 117, 63, 63, 99, 39, 9, 35, 63, 125, + 99, 45, 93, 33, 93, 9, 105, 75, 51, 115, 11, 37, 17, 41, 21, 43, 73, 19, 93, 7, + 95, 81, 93, 79, 81, 55, 9, 51, 63, 45, 89, 73, 19, 115, 39, 47, 81, 39, 5, 5, 45, + 53, 65, 49, 17, 105, 13, 107, 5, 5, 19, 73, 59, 43, 83, 97, 115, 27, 1, 69, 103, + 3, 99, 103, 63, 67, 25, 121, 97, 77, 13, 83, 103, 41, 11, 27, 81, 37, 33, 125, + 71, 41, 41, 59, 41, 87, 123, + 43, 101, 63, 45, 39, 21, 97, 15, 97, 111, 21, 49, + 13, 17, 79, 91, 65, 105, 75, 1, 45, 67, 83, 107, 125, 87, 15, 81, 95, 105, 65, + 45, 59, 103, 23, 103, 99, 67, 99, 47, 117, 71, 89, 35, 53, 73, 9, 115, 49, 37, + 1, 35, 9, 45, 81, 19, 127, 17, 17, 105, 89, 49, 101, 7, 37, 33, 11, 95, 95, 17, + 111, 105, 41, 115, 5, 69, 101, 27, 27, 101, 103, 53, 9, 21, 43, 79, 91, 65, + 117, 87, 125, 55, 45, 63, 85, 83, 97, 45, 83, 87, 113, 93, 95, 5, 17, 77, 77, + 127, 123, 45, 81, 85, 121, 119, 27, 85, 41, 49, 15, 107, 21, 51, 119, 11, 87, + 101, 115, 63, 63, 37, 121, 109, 7, 43, 69, 19, 77, 49, 71, 59, 35, 7, 13, 55, + 101, 127, 103, 85, 109, 29, 61, 67, 21, 111, 67, 23, 57, 75, 71, 101, 123, 41, + 107, 101, 107, 125, 27, 47, 119, 41, 19, 127, 33, 31, 109, 7, 91, 91, 39, 125, + 105, 47, 125, 123, 91, 9, 103, 45, 23, 117, 9, 125, 73, 11, 37, 61, 79, 21, 5, + 47, 117, 67, 53, 85, 33, 81, 121, 47, 61, 51, 127, 29, 65, 45, 41, 95, 57, 73, + 33, 117, 61, 111, 59, 123, 65, 47, 105, 23, 29, 107, 37, 81, 67, 29, 115, 119, + 75, 73, 99, 103, 7, 57, 45, 61, 95, 49, 101, 101, 35, 47, 119, 39, 67, 31, 103, + 7, 61, 127, 87, 3, 35, 29, 73, 95, 103, 71, 75, 51, 87, 57, 97, 11, 105, 87, 41, + 73, 109, 69, 35, 121, 39, 111, 1, 77, + 39, 47, 53, 91, 3, 17, 51, 83, 39, 125, 85, 111, + 21, 69, 85, 29, 55, 11, 117, 1, 47, 17, 65, 63, 47, 117, 17, 115, 51, 25, 33, + 123, 123, 83, 51, 113, 95, 121, 51, 91, 109, 43, 55, 35, 55, 87, 33, 37, 5, 3, + 45, 21, 105, 127, 35, 17, 35, 37, 97, 97, 21, 77, 123, 17, 89, 53, 105, 75, 25, + 125, 13, 47, 21, 125, 23, 55, 63, 61, 5, 17, 93, 57, 121, 69, 73, 93, 121, 105, + 75, 91, 67, 95, 75, 9, 69, 97, 99, 93, 11, 53, 19, 73, 5, 33, 79, 107, 65, 69, + 79, 125, 25, 93, 55, 61, 17, 117, 69, 97, 87, 111, 37, 93, 59, 79, 95, 53, 115, + 53, 85, 85, 65, 59, 23, 75, 21, 67, 27, 99, 79, 27, 3, 95, 27, 69, 19, 75, 47, + 59, 41, 85, 77, 99, 55, 49, 93, 93, 119, 51, 125, 63, 13, 15, 45, 61, 19, 105, + 115, 17, 83, 7, 7, 11, 61, 37, 63, 89, 95, 119, 113, 67, 123, 91, 33, 37, 99, + 43, 11, 33, 65, 81, 79, 81, 107, 63, 63, 55, 89, 91, 25, 93, 101, 27, 55, 75, + 121, 79, 43, 125, 73, 27, 109, 35, 21, 71, 113, 89, 59, 95, 41, 45, 113, 119, + 113, 39, 59, 73, 15, 13, 59, 67, 121, 27, 7, 105, 15, 59, 59, 35, 91, 89, 23, + 125, 97, 53, 41, 91, 111, 29, 31, 3, 103, 61, 71, 35, 7, 119, 29, 45, 49, 111, + 41, 109, 59, 125, 13, 27, 19, 79, 9, 75, 83, 81, 33, 91, 109, 33, 29, 107, 111, + 101, 107, 109, 65, 59, 43, 37, + 1, 9, 15, 109, 37, 111, 113, 119, 79, 73, 65, + 71, 93, 17, 101, 87, 97, 43, 23, 75, 109, 41, 49, 53, 31, 97, 105, 109, 119, + 51, 9, 53, 113, 97, 73, 89, 79, 49, 61, 105, 13, 99, 53, 71, 7, 87, 21, 101, 5, + 71, 31, 123, 121, 121, 73, 79, 115, 13, 39, 101, 19, 37, 51, 83, 97, 55, 81, + 91, 127, 105, 89, 63, 47, 49, 75, 37, 77, 15, 49, 107, 23, 23, 35, 19, 69, 17, + 59, 63, 73, 29, 125, 61, 65, 95, 101, 81, 57, 69, 83, 37, 11, 37, 95, 1, 73, 27, + 29, 57, 7, 65, 83, 99, 69, 19, 103, 43, 95, 25, 19, 103, 41, 125, 97, 71, 105, + 83, 83, 61, 39, 9, 45, 117, 63, 31, 5, 117, 67, 125, 41, 117, 43, 77, 97, 15, + 29, 5, 59, 25, 63, 87, 39, 39, 77, 85, 37, 81, 73, 89, 29, 125, 109, 21, 23, + 119, 105, 43, 93, 97, 15, 125, 29, 51, 69, 37, 45, 31, 75, 109, 119, 53, 5, + 101, 125, 121, 35, 29, 7, 63, 17, 63, 13, 69, 15, 105, 51, 127, 105, 9, 57, 95, + 59, 109, 35, 49, 23, 33, 107, 55, 33, 57, 79, 73, 69, 59, 107, 55, 11, 63, 95, + 103, 23, 125, 91, 31, 91, 51, 65, 61, 75, 69, 107, 65, 101, 59, 35, 15}, + /* [7][*] */ + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 7, 23, 39, 217, 141, 27, 53, 181, 169, 35, 15, + 207, 45, 247, 185, 117, 41, 81, 223, 151, 81, 189, 61, 95, 185, 23, 73, 113, + 239, 85, 9, 201, 83, 53, 183, 203, 91, 149, 101, 13, 111, 239, 3, 205, 253, + 247, 121, 189, 169, 179, 197, 175, 217, 249, 195, 95, 63, 19, 7, 5, 75, 217, + 245, 111, 189, 165, 169, 141, 221, 249, 159, 253, 207, 249, 219, 23, 49, + 127, 237, 5, 25, 177, 37, 103, 65, 167, 81, 87, 119, 45, 79, 143, 57, 79, 187, + 143, 183, 75, 97, 211, 149, 175, 37, 135, 189, 225, 241, 63, 33, 43, 13, 73, + 213, 57, 239, 183, 117, 21, 29, 115, 43, 205, 223, 15, 3, 159, 51, 101, 127, + 99, 239, 171, 113, 171, 119, 189, 245, 201, 27, 185, 229, 105, 153, 189, 33, + 35, 137, 77, 97, 17, 181, 55, 197, 201, 155, 37, 197, 137, 223, 25, 179, 91, + 23, 235, 53, 253, 49, 181, 249, 53, 173, 97, 247, 67, 115, 103, 159, 239, 69, + 173, 217, 95, 221, 247, 97, 91, 123, 223, 213, 129, 181, 87, 239, 85, 89, + 249, 141, 39, 57, 249, 71, 101, 159, 33, 137, 189, 71, 253, 205, 171, 13, + 249, 109, 131, 199, 189, 179, 31, 99, 113, 41, 173, 23, 189, 197, 3, 135, 9, + 95, 195, 27, 183, 1, 123, 73, 53, 99, 197, 59, 27, 101, 55, 193, 31, 61, 119, + 11, 7, 255, 233, 53, 157, 193, 97, 83, 65, 81, 239, 167, 69, 71, 109, + 97, 137, 71, 193, 189, 115, 79, 205, 37, 227, + 53, 33, 91, 229, 245, 105, 77, 229, 161, 103, 93, 13, 161, 229, 223, 69, 15, + 25, 23, 233, 93, 25, 217, 247, 61, 75, 27, 9, 223, 213, 55, 197, 145, 89, 199, + 41, 201, 5, 149, 35, 119, 183, 53, 11, 13, 3, 179, 229, 43, 55, 187, 233, 47, + 133, 91, 47, 71, 93, 105, 145, 45, 255, 221, 115, 175, 19, 129, 5, 209, 197, + 57, 177, 115, 187, 119, 77, 211, 111, 33, 113, 23, 87, 137, 41, 7, 83, 43, + 121, 145, 5, 219, 27, 11, 111, 207, 55, 97, 63, 229, 53, 33, 149, 23, 187, + 153, 91, 193, 183, 59, 211, 93, 139, 59, 179, 163, 209, 77, 39, 111, 79, 229, + 85, 237, 199, 137, 147, 25, 73, 121, 129, 83, 87, 93, 205, 167, 53, 107, 229, + 213, 95, 219, 109, 175, 13, 209, 97, 61, 147, 19, 13, 123, 73, 35, 141, 81, + 19, 171, 255, 111, 107, 233, 113, 133, 89, 9, 231, 95, 69, 33, 1, 253, 219, + 253, 247, 129, 11, 251, 221, 153, 35, 103, 239, 7, 27, 235, 181, 5, 207, 53, + 149, 155, 225, 165, 137, 155, 201, 97, 245, 203, 47, 39, 35, 105, 239, 49, + 15, 253, 7, 237, 213, 55, 87, 199, 27, 175, 49, 41, 229, 85, 3, 149, 179, 129, + 185, 249, 197, 15, 97, 197, 139, 203, 63, 33, 251, 217, 199, 199, 99, 249, + 33, 229, 177, 13, 209, 147, 97, 31, 125, 177, 137, + 187, 11, 91, 223, 29, 169, 231, 59, 31, 163, 41, + 57, 87, 247, 25, 127, 101, 207, 187, 73, 61, 105, 27, 91, 171, 243, 33, 3, 1, + 21, 229, 93, 71, 61, 37, 183, 65, 211, 53, 11, 151, 165, 47, 5, 129, 79, 101, + 147, 169, 181, 19, 95, 77, 139, 197, 219, 97, 239, 183, 143, 9, 13, 209, 23, + 215, 53, 137, 203, 19, 151, 171, 133, 219, 231, 3, 15, 253, 225, 33, 111, + 183, 213, 169, 119, 111, 15, 201, 123, 121, 225, 113, 113, 225, 161, 165, 1, + 139, 55, 3, 93, 217, 193, 97, 29, 69, 231, 161, 93, 69, 143, 137, 9, 87, 183, + 113, 183, 73, 215, 137, 89, 251, 163, 41, 227, 145, 57, 81, 57, 11, 135, 145, + 161, 175, 159, 25, 55, 167, 157, 211, 97, 247, 249, 23, 129, 159, 71, 197, + 127, 141, 219, 5, 233, 131, 217, 101, 131, 33, 157, 173, 69, 207, 239, 81, + 205, 11, 41, 169, 65, 193, 77, 201, 173, 1, 221, 157, 1, 15, 113, 147, 137, + 205, 225, 73, 45, 49, 149, 113, 253, 99, 17, 119, 105, 117, 129, 243, 75, + 203, 53, 29, 247, 35, 247, 171, 31, 199, 213, 29, 251, 7, 251, 187, 91, 11, + 149, 13, 205, 37, 249, 137, 139, 9, 7, 113, 183, 205, 187, 39, 3, 79, 155, + 227, 89, 185, 51, 127, 63, 83, 41, 133, 183, 181, 127, 19, 255, 219, 59, 251, + 3, 187, 57, 217, 115, 217, 229, 181, 185, 149, 83, 115, 11, + 123, 19, 109, 165, 103, 123, 219, 129, 155, + 207, 177, 9, 49, 181, 231, 33, 233, 67, 155, 41, 9, 95, 123, 65, 117, 249, 85, + 169, 129, 241, 173, 251, 225, 147, 165, 69, 81, 239, 95, 23, 83, 227, 249, + 143, 171, 193, 9, 21, 57, 73, 97, 57, 29, 239, 151, 159, 191, 47, 51, 1, 223, + 251, 251, 151, 41, 119, 127, 131, 33, 209, 123, 53, 241, 25, 31, 183, 107, + 25, 115, 39, 11, 213, 239, 219, 109, 185, 35, 133, 123, 185, 27, 55, 245, 61, + 75, 205, 213, 169, 163, 63, 55, 49, 83, 195, 51, 31, 41, 15, 203, 41, 63, 127, + 161, 5, 143, 7, 199, 251, 95, 75, 101, 15, 43, 237, 197, 117, 167, 155, 21, + 83, 205, 255, 49, 101, 213, 237, 135, 135, 21, 73, 93, 115, 7, 85, 223, 237, + 79, 89, 5, 57, 239, 67, 65, 201, 155, 71, 85, 195, 89, 181, 119, 135, 147, + 237, 173, 41, 155, 67, 113, 111, 21, 183, 23, 103, 207, 253, 69, 219, 205, + 195, 43, 197, 229, 139, 177, 129, 69, 97, 201, 163, 189, 11, 99, 91, 253, + 239, 91, 145, 19, 179, 231, 121, 7, 225, 237, 125, 191, 119, 59, 175, 237, + 131, 79, 43, 45, 205, 199, 251, 153, 207, 37, 179, 113, 255, 107, 217, 61, 7, + 181, 247, 31, 13, 113, 145, 107, 233, 233, 43, 79, 23, 169, 137, 129, 183, + 53, 91, 55, 103, 223, 87, 177, 157, 79, 213, 139, + 183, 231, 205, 143, 129, 243, 205, 93, 59, + 15, 89, 9, 11, 47, 133, 227, 75, 9, 91, 19, 171, 163, 79, 7, 103, 5, 119, 155, + 75, 11, 71, 95, 17, 13, 243, 207, 187}, + /* [8][*] */ + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 235, 307, 495, 417, 57, 151, 19, 119, 375, 451, + 55, 449, 501, 53, 185, 317, 17, 21, 487, 13, 347, 393, 15, 391, 307, 189, + 381, 71, 163, 99, 467, 167, 433, 337, 257, 179, 47, 385, 23, 117, 369, 425, + 207, 433, 301, 147, 333, 85, 221, 423, 49, 3, 43, 229, 227, 201, 383, 281, + 229, 207, 21, 343, 251, 397, 173, 507, 421, 443, 399, 53, 345, 77, 385, 317, + 155, 187, 269, 501, 19, 169, 235, 415, 61, 247, 183, 5, 257, 401, 451, 95, + 455, 49, 489, 75, 459, 377, 87, 463, 155, 233, 115, 429, 211, 419, 143, 487, + 195, 209, 461, 193, 157, 193, 363, 181, 271, 445, 381, 231, 135, 327, 403, + 171, 197, 181, 343, 113, 313, 393, 311, 415, 267, 247, 425, 233, 289, 55, + 39, 247, 327, 141, 5, 189, 183, 27, 337, 341, 327, 87, 429, 357, 265, 251, + 437, 201, 29, 339, 257, 377, 17, 53, 327, 47, 375, 393, 369, 403, 125, 429, + 257, 157, 217, 85, 267, 117, 337, 447, 219, 501, 41, 41, 193, 509, 131, 207, + 505, 421, 149, 111, 177, 167, 223, 291, 91, 29, 305, 151, 177, 337, 183, + 361, 435, 307, 507, 77, 181, 507, 315, 145, 423, 71, 103, 493, 271, 469, + 339, 237, 437, 483, 31, 219, 61, 131, 391, 233, 219, 69, 57, 459, 225, 421, + 7, 461, 111, 451, 277, 185, 193, 125, 251, 199, 73, 71, 7, 409, 417, 149, + 193, 53, 437, 29, 467, 229, 31, 35, 75, 105, + 503, 75, 317, 401, 367, 131, 365, 441, 433, 93, 377, 405, 465, 259, 283, + 443, 143, 445, 3, 461, 329, 309, 77, 323, 155, 347, 45, 381, 315, 463, 207, + 321, 157, 109, 479, 313, 345, 167, 439, 307, 235, 473, 79, 101, 245, 19, + 381, 251, 35, 25, 107, 187, 115, 113, 321, 115, 445, 61, 77, 293, 405, 13, + 53, 17, 171, 299, 41, 79, 3, 485, 331, 13, 257, 59, 201, 497, 81, 451, 199, + 171, 81, 253, 365, 75, 451, 149, 483, 81, 453, 469, 485, 305, 163, 401, 15, + 91, 3, 129, 35, 239, 355, 211, 387, 101, 299, 67, 375, 405, 357, 267, 363, + 79, 83, 437, 457, 39, 97, 473, 289, 179, 57, 23, 49, 79, 71, 341, 287, 95, + 229, 271, 475, 49, 241, 261, 495, 353, 381, 13, 291, 37, 251, 105, 399, 81, + 89, 265, 507, 205, 145, 331, 129, 119, 503, 249, 1, 289, 463, 163, 443, 63, + 123, 361, 261, 49, 429, 137, 355, 175, 507, 59, 277, 391, 25, 185, 381, 197, + 39, 5, 429, 119, 247, 177, 329, 465, 421, 271, 467, 151, 45, 429, 137, 471, + 11, 17, 409, 347, 199, 463, 177, 11, 51, 361, 95, 497, 163, 351, 127, 395, + 511, 327, 353, 49, 105, 151, 321, 331, 329, 509, 107, 109, 303, 467, 287, + 161, 45, 385, 289, 363, 331, 265, 407, 37, 433, 315, 343, 63, 51, 185, 71, + 27, 267, + 503, 239, 293, 245, 281, 297, 75, 461, 371, + 129, 189, 189, 339, 287, 111, 111, 379, 93, 27, 185, 347, 337, 247, 507, + 161, 231, 43, 499, 73, 327, 263, 331, 249, 493, 37, 25, 115, 3, 167, 197, + 127, 357, 497, 103, 125, 191, 165, 55, 101, 95, 79, 351, 341, 43, 125, 135, + 173, 289, 373, 133, 421, 241, 281, 213, 177, 363, 151, 227, 145, 363, 239, + 431, 81, 397, 241, 67, 291, 255, 405, 421, 399, 75, 399, 105, 329, 41, 425, + 7, 283, 375, 475, 427, 277, 209, 411, 3, 137, 195, 289, 509, 121, 55, 147, + 275, 251, 19, 129, 285, 415, 487, 491, 193, 219, 403, 23, 97, 65, 285, 75, + 21, 373, 261, 339, 239, 495, 415, 333, 107, 435, 297, 213, 149, 463, 199, + 323, 45, 19, 301, 121, 499, 187, 229, 63, 425, 99, 281, 35, 125, 349, 87, + 101, 59, 195, 511, 355, 73, 263, 243, 101, 165, 141, 11, 389, 219, 187, 449, + 447, 393, 477, 305, 221, 51, 355, 209, 499, 479, 265, 377, 145, 411, 173, + 11, 433, 483, 135, 385, 341, 89, 209, 391, 33, 395, 319, 451, 119, 341, 227, + 375, 61, 331, 493, 411, 293, 47, 203, 375, 167, 395, 155, 5, 237, 361, 489, + 127, 21, 345, 101, 371, 233, 431, 109, 119, 277, 125, 263, 73, 135, 123, 83, + 123, 405, 69, 75, 287, 401, 23, 283, 393, 41, 379, 431, 11, 475, 505, 19, + 365, 265, 271, + 499, 489, 443, 165, 91, 83, 291, 319, 199, + 107, 245, 389, 143, 137, 89, 125, 281, 381, 215, 131, 299, 249, 375, 455, + 43, 73, 281, 217, 297, 229, 431, 357, 81, 357, 171, 451, 481, 13, 387, 491, + 489, 439, 385, 487, 177, 393, 33, 71, 375, 443, 129, 407, 395, 127, 65, 333, + 309, 119, 197, 435, 497, 373, 71, 379, 509, 387, 159, 265, 477, 463, 449, + 47, 353, 249, 335, 505, 89, 141, 55, 235, 187, 87, 363, 93, 363, 101, 67, + 215, 321, 331, 305, 261, 411, 491, 479, 65, 307, 469, 415, 131, 315, 487, + 83, 455, 19, 113, 163, 503, 99, 499, 251, 239, 81, 167, 391, 255, 317, 363, + 359, 395, 419, 307, 251, 267, 171, 461, 183, 465, 165, 163, 293, 477, 223, + 403, 389, 97, 335, 357, 297, 19, 469, 501, 249, 85, 213, 311, 265, 379, 297, + 283, 393, 449, 463, 289, 159, 289, 499, 407, 129, 137, 221, 43, 89, 403, + 271, 75, 83, 445, 453, 389, 149, 143, 423, 499, 317, 445, 157, 137, 453, + 163, 87, 23, 391, 119, 427, 323, 173, 89, 259, 377, 511, 249, 31, 363, 229, + 353, 329, 493, 427, 57, 205, 389, 91, 83, 13, 219, 439, 45, 35, 371, 441, 17, + 267, 501, 53, 25, 333, 17, 201, 475, 257, 417, 345, 381, 377, 55, 403, 77, + 389, 347, 363, 211, 413, 419, 5, 167, 219, 201, 285, 425, 11, 77, 269, 489, + 281, 403, 79, + 425, 125, 81, 331, 437, 271, 397, 299, 475, + 271, 249, 413, 233, 261, 495, 171, 69, 27, 409, 21, 421, 367, 81, 483, 255, + 15, 219, 365, 497, 181, 75, 431, 99, 325, 407, 229, 281, 63, 83, 493, 5, 113, + 15, 271, 37, 87, 451, 299, 83, 451, 311, 441, 47, 455, 47, 253, 13, 109, 369, + 347, 11, 409, 275, 63, 441, 15}, + /* [9][*] */ + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 519, 307, 931, 1023, 517, 771, 151, 1023, + 539, 725, 45, 927, 707, 29, 125, 371, 275, 279, 817, 389, 453, 989, 1015, + 29, 169, 743, 99, 923, 981, 181, 693, 309, 227, 111, 219, 897, 377, 425, + 609, 227, 19, 221, 143, 581, 147, 919, 127, 725, 793, 289, 411, 835, 921, + 957, 443, 349, 813, 5, 105, 457, 393, 539, 101, 197, 697, 27, 343, 515, 69, + 485, 383, 855, 693, 133, 87, 743, 747, 475, 87, 469, 763, 721, 345, 479, + 965, 527, 121, 271, 353, 467, 177, 245, 627, 113, 357, 7, 691, 725, 355, + 889, 635, 737, 429, 545, 925, 357, 873, 187, 351, 677, 999, 921, 477, 233, + 765, 495, 81, 953, 479, 89, 173, 473, 131, 961, 411, 291, 967, 65, 511, 13, + 805, 945, 369, 827, 295, 163, 835, 259, 207, 331, 29, 315, 999, 133, 967, + 41, 117, 677, 471, 717, 881, 755, 351, 723, 259, 879, 455, 721, 289, 149, + 199, 805, 987, 851, 423, 597, 129, 11, 733, 549, 153, 285, 451, 559, 377, + 109, 357, 143, 693, 615, 677, 701, 475, 767, 85, 229, 509, 547, 151, 389, + 711, 785, 657, 319, 509, 99, 1007, 775, 359, 697, 677, 85, 497, 105, 615, + 891, 71, 449, 835, 609, 377, 693, 665, 627, 215, 911, 503, 729, 131, 19, + 895, 199, 161, 239, 633, 1013, 537, 255, 23, 149, 679, 1021, 595, 199, 557, + 659, 251, 829, 727, 439, 495, 647, 223, + 949, 625, 87, 481, 85, 799, 917, 769, 949, + 739, 115, 499, 945, 547, 225, 1015, 469, 737, 495, 353, 103, 17, 665, 639, + 525, 75, 447, 185, 43, 729, 577, 863, 735, 317, 99, 17, 477, 893, 537, 519, + 1017, 375, 297, 325, 999, 353, 343, 729, 135, 489, 859, 267, 141, 831, 141, + 893, 249, 807, 53, 613, 131, 547, 977, 131, 999, 175, 31, 341, 739, 467, + 675, 241, 645, 247, 391, 583, 183, 973, 433, 367, 131, 467, 571, 309, 385, + 977, 111, 917, 935, 473, 345, 411, 313, 97, 149, 959, 841, 839, 669, 431, + 51, 41, 301, 247, 1015, 377, 329, 945, 269, 67, 979, 581, 643, 823, 557, 91, + 405, 117, 801, 509, 347, 893, 303, 227, 783, 555, 867, 99, 703, 111, 797, + 873, 541, 919, 513, 343, 319, 517, 135, 871, 917, 285, 663, 301, 15, 763, + 89, 323, 757, 317, 807, 309, 1013, 345, 499, 279, 711, 915, 411, 281, 193, + 739, 365, 315, 375, 809, 469, 487, 621, 857, 975, 537, 939, 585, 129, 625, + 447, 129, 1017, 133, 83, 3, 415, 661, 53, 115, 903, 49, 79, 55, 385, 261, + 345, 297, 199, 385, 617, 25, 515, 275, 849, 401, 471, 377, 661, 535, 505, + 939, 465, 225, 929, 219, 955, 659, 441, 117, 527, 427, 515, 287, 191, 33, + 389, 197, 825, 63, 417, 949, 35, 571, 9, 131, 609, 439, 95, 19, 569, 893, + 451, 397, 971, 801, + 125, 471, 187, 257, 67, 949, 621, 453, 411, + 621, 955, 309, 783, 893, 597, 377, 753, 145, 637, 941, 593, 317, 555, 375, + 575, 175, 403, 571, 555, 109, 377, 931, 499, 649, 653, 329, 279, 271, 647, + 721, 665, 429, 957, 803, 767, 425, 477, 995, 105, 495, 575, 687, 385, 227, + 923, 563, 723, 481, 717, 111, 633, 113, 369, 955, 253, 321, 409, 909, 367, + 33, 967, 453, 863, 449, 539, 781, 911, 113, 7, 219, 725, 1015, 971, 1021, + 525, 785, 873, 191, 893, 297, 507, 215, 21, 153, 645, 913, 755, 371, 881, + 113, 903, 225, 49, 587, 201, 927, 429, 599, 513, 97, 319, 331, 833, 325, + 887, 139, 927, 399, 163, 307, 803, 169, 1019, 869, 537, 907, 479, 335, 697, + 479, 353, 769, 787, 1023, 855, 493, 883, 521, 735, 297, 1011, 991, 879, + 855, 591, 415, 917, 375, 453, 553, 189, 841, 339, 211, 601, 57, 765, 745, + 621, 209, 875, 639, 7, 595, 971, 263, 1009, 201, 23, 77, 621, 33, 535, 963, + 661, 523, 263, 917, 103, 623, 231, 47, 301, 549, 337, 675, 189, 357, 1005, + 789, 189, 319, 721, 1005, 525, 675, 539, 191, 813, 917, 51, 167, 415, 579, + 755, 605, 721, 837, 529, 31, 327, 799, 961, 279, 409, 847, 649, 241, 285, + 545, 407, 161, 591, 73, 313, 811, 17, 663, 269, 261, 37, 783, 127, 917, 231, + 577, 975, 793, + 921, 343, 751, 139, 221, 79, 817, 393, 545, + 11, 781, 71, 1, 699, 767, 917, 9, 107, 341, 587, 903, 965, 599, 507, 843, + 739, 579, 397, 397, 325, 775, 565, 925, 75, 55, 979, 931, 93, 957, 857, 753, + 965, 795, 67, 5, 87, 909, 97, 995, 271, 875, 671, 613, 33, 351, 69, 811, 669, + 729, 401, 647, 241, 435, 447, 721, 271, 745, 53, 775, 99, 343, 451, 427, + 593, 339, 845, 243, 345, 17, 573, 421, 517, 971, 499, 435, 769, 75, 203, + 793, 985, 343, 955, 735, 523, 659, 703, 303, 421, 951, 405, 631, 825, 735, + 433, 841, 485, 49, 749, 107, 669, 211, 497, 143, 99, 57, 277, 969, 107, 397, + 563, 551, 447, 381, 187, 57, 405, 731, 769, 923, 955, 915, 737, 595, 341, + 253, 823, 197, 321, 315, 181, 885, 497, 159, 571, 981, 899, 785, 947, 217, + 217, 135, 753, 623, 565, 717, 903, 581, 955, 621, 361, 869, 87, 943, 907, + 853, 353, 335, 197, 771, 433, 743, 195, 91, 1023, 63, 301, 647, 205, 485, + 927, 1003, 987, 359, 577, 147, 141, 1017, 701, 273, 89, 589, 487, 859, 343, + 91, 847, 341, 173, 287, 1003, 289, 639, 983, 685, 697, 35, 701, 645, 911, + 501, 705, 873, 763, 745, 657, 559, 699, 315, 347, 429, 197, 165, 955, 859, + 167, 303, 833, 531, 473, 635, 641, 195, 589, 821, 205, 3, 635, 371, 891, + 249, 123, + 77, 623, 993, 401, 525, 427, 71, 655, 951, + 357, 851, 899, 535, 493, 323, 1003, 343, 515, 859, 1017, 5, 423, 315, 1011, + 703, 41, 777, 163, 95, 831, 79, 975, 235, 633, 723, 297, 589, 317, 679, 981, + 195, 399, 1003, 121, 501, 155}, + /* [10][*] */ + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 7, 2011, 1001, 49, 825, 415, 1441, 383, 1581, + 623, 1621, 1319, 1387, 619, 839, 217, 75, 1955, 505, 281, 1629, 1379, 53, + 1111, 1399, 301, 209, 49, 155, 1647, 631, 129, 1569, 335, 67, 1955, 1611, + 2021, 1305, 121, 37, 877, 835, 1457, 669, 1405, 935, 1735, 665, 551, 789, + 1543, 1267, 1027, 1, 1911, 163, 1929, 67, 1975, 1681, 1413, 191, 1711, + 1307, 401, 725, 1229, 1403, 1609, 2035, 917, 921, 1789, 41, 2003, 187, 67, + 1635, 717, 1449, 277, 1903, 1179, 363, 1211, 1231, 647, 1261, 1029, 1485, + 1309, 1149, 317, 1335, 171, 243, 271, 1055, 1601, 1129, 1653, 205, 1463, + 1681, 1621, 197, 951, 573, 1697, 1265, 1321, 1805, 1235, 1853, 1307, 945, + 1197, 1411, 833, 273, 1517, 1747, 1095, 1345, 869, 57, 1383, 221, 1713, + 335, 1751, 1141, 839, 523, 1861, 1105, 389, 1177, 1877, 805, 93, 1591, + 423, 1835, 99, 1781, 1515, 1909, 1011, 303, 385, 1635, 357, 973, 1781, + 1707, 1363, 1053, 649, 1469, 623, 1429, 1241, 1151, 1055, 503, 921, 3, + 349, 1149, 293, 45, 303, 877, 1565, 1583, 1001, 663, 1535, 395, 1141, + 1481, 1797, 643, 1507, 465, 2027, 1695, 367, 937, 719, 545, 1991, 83, 819, + 239, 1791, 1461, 1647, 1501, 1161, 1629, 139, 1595, 1921, 1267, 1415, + 509, 347, 777, 1083, 363, 269, 1015, + 1809, 1105, 1429, 1471, 2019, 381, 2025, + 1223, 827, 1733, 887, 1321, 803, 1951, 1297, 1995, 833, 1107, 1135, 1181, + 1251, 983, 1389, 1565, 273, 137, 71, 735, 1005, 933, 67, 1471, 551, 457, + 1667, 1729, 919, 285, 1629, 1815, 653, 1919, 1039, 531, 393, 1411, 359, + 221, 699, 1485, 471, 1357, 1715, 595, 1677, 153, 1903, 1281, 215, 781, + 543, 293, 1807, 965, 1695, 443, 1985, 321, 879, 1227, 1915, 839, 1945, + 1993, 1165, 51, 557, 723, 1491, 817, 1237, 947, 1215, 1911, 1225, 1965, + 1889, 1503, 1177, 73, 1767, 303, 177, 1897, 1401, 321, 921, 217, 1779, + 327, 1889, 333, 615, 1665, 1825, 1639, 237, 1205, 361, 129, 1655, 983, + 1089, 1171, 401, 677, 643, 749, 303, 1407, 1873, 1579, 1491, 1393, 1247, + 789, 763, 49, 5, 1607, 1891, 735, 1557, 1909, 1765, 1777, 1127, 813, 695, + 97, 731, 1503, 1751, 333, 769, 865, 693, 377, 1919, 957, 1359, 1627, 1039, + 1783, 1065, 1665, 1917, 1947, 991, 1997, 841, 459, 221, 327, 1595, 1881, + 1269, 1007, 129, 1413, 475, 1105, 791, 1983, 1359, 503, 691, 659, 691, + 343, 1375, 1919, 263, 1373, 603, 1383, 297, 781, 145, 285, 767, 1739, + 1715, 715, 317, 1333, 85, 831, 1615, 81, 1667, 1467, 1457, 1453, 1825, + 109, 387, 1207, 2039, 213, 1351, 1329, 1173, + 57, 1769, 951, 183, 23, 451, 1155, 1551, + 2037, 811, 635, 1671, 1451, 863, 1499, 1673, 363, 1029, 1077, 1525, 277, + 1023, 655, 665, 1869, 1255, 965, 277, 1601, 329, 1603, 1901, 395, 65, + 1307, 2029, 21, 1321, 543, 1569, 1185, 1905, 1701, 413, 2041, 1697, 725, + 1417, 1847, 411, 211, 915, 1891, 17, 1877, 1699, 687, 1089, 1973, 1809, + 851, 1495, 1257, 63, 1323, 1307, 609, 881, 1543, 177, 617, 1505, 1747, + 1537, 925, 183, 77, 1723, 1877, 1703, 397, 459, 521, 257, 1177, 389, 1947, + 1553, 1583, 1831, 261, 485, 289, 1281, 1543, 1591, 1123, 573, 821, 1065, + 1933, 1373, 2005, 905, 207, 173, 1573, 1597, 573, 1883, 1795, 1499, 1743, + 553, 335, 333, 1645, 791, 871, 1157, 969, 557, 141, 223, 1129, 1685, 423, + 1069, 391, 99, 95, 1847, 531, 1859, 1833, 1833, 341, 237, 1997, 1799, 409, + 431, 1917, 363, 335, 1039, 1085, 1657, 1975, 1527, 1111, 659, 389, 899, + 595, 1439, 1861, 1979, 1569, 1087, 1009, 165, 1895, 1481, 1583, 29, 1193, + 1673, 1075, 301, 1081, 1377, 1747, 1497, 1103, 1789, 887, 739, 1577, 313, + 1367, 1299, 1801, 1131, 1837, 73, 1865, 1065, 843, 635, 55, 1655, 913, + 1037, 223, 1871, 1161, 461, 479, 511, 1721, 1107, 389, 151, 35, 375, 1099, + 937, 1185, 1701, 769, 639, 1633, + 1609, 379, 1613, 2031, 685, 289, 975, 671, + 1599, 1447, 871, 647, 99, 139, 1427, 959, 89, 117, 841, 891, 1959, 223, + 1697, 1145, 499, 1435, 1809, 1413, 1445, 1675, 171, 1073, 1349, 1545, + 2039, 1027, 1563, 859, 215, 1673, 1919, 1633, 779, 411, 1845, 1477, 1489, + 447, 1545, 351, 1989, 495, 183, 1639, 1385, 1805, 1097, 1249, 1431, 1571, + 591, 697, 1509, 709, 31, 1563, 165, 513, 1425, 1299, 1081, 145, 1841, + 1211, 941, 609, 845, 1169, 1865, 1593, 347, 293, 1277, 157, 211, 93, 1679, + 1799, 527, 41, 473, 563, 187, 1525, 575, 1579, 857, 703, 1211, 647, 709, + 981, 285, 697, 163, 981, 153, 1515, 47, 1553, 599, 225, 1147, 381, 135, + 821, 1965, 609, 1033, 983, 503, 1117, 327, 453, 2005, 1257, 343, 1649, + 1199, 599, 1877, 569, 695, 1587, 1475, 187, 973, 233, 511, 51, 1083, 665, + 1321, 531, 1875, 1939, 859, 1507, 1979, 1203, 1965, 737, 921, 1565, 1943, + 819, 223, 365, 167, 1705, 413, 1577, 745, 1573, 655, 1633, 1003, 91, 1123, + 477, 1741, 1663, 35, 715, 37, 1513, 815, 941, 1379, 263, 1831, 1735, 1111, + 1449, 353, 1941, 1655, 1349, 877, 285, 1723, 125, 1753, 985, 723, 175, + 439, 791, 1051, 1261, 717, 1555, 1757, 1777, 577, 1583, 1957, 873, 331, + 1163, 313, 1, 1963, 963, 1905, 821, + 1677, 185, 709, 545, 1723, 215, 1885, + 1249, 583, 1803, 839, 885, 485, 413, 1767, 425, 129, 1035, 329, 1263, + 1881, 1779, 1565, 359, 367, 453, 707, 1419, 831, 1889, 887, 1871, 1869, + 747, 223, 1547, 1799, 433, 1441, 553, 2021, 1303, 1505, 1735, 1619, 1065, + 1161, 2047, 347, 867, 881, 1447, 329, 781, 1065, 219, 589, 645, 1257, + 1833, 749, 1841, 1733, 1179, 1191, 1025, 1639, 1955, 1423, 1685, 1711, + 493, 549, 783, 1653, 397, 895, 233, 759, 1505, 677, 1449, 1573, 1297, + 1821, 1691, 791, 289, 1187, 867, 1535, 575, 183}, + /* [11][*] */ + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 3915, 97, 3047, 937, 2897, 953, 127, 1201, + 3819, 193, 2053, 3061, 3759, 1553, 2007, 2493, 603, 3343, 3751, 1059, + 783, 1789, 1589, 283, 1093, 3919, 2747, 277, 2605, 2169, 2905, 721, 4069, + 233, 261, 1137, 3993, 3619, 2881, 1275, 3865, 1299, 3757, 1193, 733, 993, + 1153, 2945, 3163, 3179, 437, 271, 3493, 3971, 1005, 2615, 2253, 1131, + 585, 2775, 2171, 2383, 2937, 2447, 1745, 663, 1515, 3767, 2709, 1767, + 3185, 3017, 2815, 1829, 87, 3341, 793, 2627, 2169, 1875, 3745, 367, 3783, + 783, 827, 3253, 2639, 2955, 3539, 1579, 2109, 379, 2939, 3019, 1999, + 2253, 2911, 3733, 481, 1767, 1055, 4019, 4085, 105, 1829, 2097, 2379, + 1567, 2713, 737, 3423, 3941, 2659, 3961, 1755, 3613, 1937, 1559, 2287, + 2743, 67, 2859, 325, 2601, 1149, 3259, 2403, 3947, 2011, 175, 3389, 3915, + 1315, 2447, 141, 359, 3609, 3933, 729, 2051, 1755, 2149, 2107, 1741, + 1051, 3681, 471, 1055, 845, 257, 1559, 1061, 2803, 2219, 1315, 1369, + 3211, 4027, 105, 11, 1077, 2857, 337, 3553, 3503, 3917, 2665, 3823, 3403, + 3711, 2085, 1103, 1641, 701, 4095, 2883, 1435, 653, 2363, 1597, 767, 869, + 1825, 1117, 1297, 501, 505, 149, 873, 2673, 551, 1499, 2793, 3277, 2143, + 3663, 533, 3991, 575, 1877, 1009, 3929, 473, 3009, 2595, 3249, 675, 3593, + 2453, 1567, 973, 595, 1335, 1715, 589, 85, + 2265, 3069, 461, 1659, 2627, 1307, 1731, 1501, 1699, 3545, 3803, 2157, + 453, 2813, 2047, 2999, 3841, 2361, 1079, 573, 69, 1363, 1597, 3427, 2899, + 2771, 1327, 1117, 1523, 3521, 2393, 2537, 1979, 3179, 683, 2453, 453, + 1227, 779, 671, 3483, 2135, 3139, 3381, 3945, 57, 1541, 3405, 3381, 2371, + 2879, 1985, 987, 3017, 3031, 3839, 1401, 3749, 2977, 681, 1175, 1519, + 3355, 907, 117, 771, 3741, 3337, 1743, 1227, 3335, 2755, 1909, 3603, + 2397, 653, 87, 2025, 2617, 3257, 287, 3051, 3809, 897, 2215, 63, 2043, + 1757, 3671, 297, 3131, 1305, 293, 3865, 3173, 3397, 2269, 3673, 717, + 3041, 3341, 3595, 3819, 2871, 3973, 1129, 513, 871, 1485, 3977, 2473, + 1171, 1143, 3063, 3547, 2183, 3993, 133, 2529, 2699, 233, 2355, 231, + 3241, 611, 1309, 3829, 1839, 1495, 301, 1169, 1613, 2673, 243, 3601, + 3669, 2813, 2671, 2679, 3463, 2477, 1795, 617, 2317, 1855, 1057, 1703, + 1761, 2515, 801, 1205, 1311, 473, 3963, 697, 1221, 251, 381, 3887, 1761, + 3093, 3721, 2079, 4085, 379, 3601, 3845, 433, 1781, 29, 1897, 1599, 2163, + 75, 3475, 3957, 1641, 3911, 2959, 2833, 1279, 1099, 403, 799, 2183, 2699, + 1711, 2037, 727, 289, 1785, 1575, 3633, 2367, 1261, 3953, 1735, 171, 1959, - 2867,859,2951,3211,15,1279,1323,599, - 1651,3951,1011,315,3513,3351,1725,3793,2399,287,4017,3571, - 1007,541,3115,429,1585,1285,755,1211,3047,915,3611,2697,2129, - 3669,81,3939,2437,915,779,3567,3701,2479,3807,1893,3927,2619, - 2543,3633,2007,3857,3837,487,1769,3759,3105,2727,3155,2479, - 1341,1657,2767,2541,577,2105,799,17,2871,3637,953,65,69,2897, - 3841,3559,4067,2335,3409,1087,425,2813,1705,1701,1237,821, - 1375,3673,2693,3925,1541,1871,2285,847,4035,1101,2029,855, - 2733,2503,121,2855,1069,3463,3505,1539,607,1349,575,2301, - 2321,1101,333,291,2171,4085,2173,2541,1195,925,4039,1379,699, - 1979,275,953,1755,1643,325,101,2263,3329,3673,3413,1977,2727, - 2313,1419,887,609,2475,591,2613,2081,3805,3435,2409,111,3557, - 3607,903,231,3059,473,2959,2925,3861,2043,3887,351,2865,369, - 1377,2639,1261,3625,3279,2201,2949,3049,449,1297,897,1891, - 411,2773,749,2753,1825,853,2775,3547,3923,3923,987,3723,2189, - 3877,3577,297,2763,1845,3083,2951,483,2169,3985,245,3655, - 3441,1023,235,835,3693,3585,327,1003,543,3059,2637, - 2923,87,3617,1031,1043,903,2913, - 2177,2641,3279,389,2009,525,4085,3299,987,2409,813,2683,373, - 2695,3775,2375,1119,2791,223,325,587,1379,2877,2867,3793,655, - 831,3425,1663,1681,2657,1865,3943,2977,1979,2271,3247,1267, - 1747,811,159,429,2001,1195,3065,553,1499,3529,1081,2877,3077, - 845,1793,2409,3995,2559,4081,1195,2955,1117,1409,785,287, - 1521,1607,85,3055,3123,2533,2329,3477,799,3683,3715,337,3139, - 3311,431,3511,2299,365,2941,3067,1331,1081,1097,2853,2299, - 495,1745,749,3819,619,1059,3559,183,3743,723,949,3501,733, - 2599,3983,3961,911,1899,985,2493,1795,653,157,433,2361,3093, - 3119,3679,2367,1701,1445,1321,2397,1241,3305,3985,2349,4067, - 3805,3073,2837,1567,3783,451,2441,1181,487,543,1201,3735, - 2517,733,1535,2175,3613,3019}, - /* [12][*] */ - {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, - 2319,653,1379,1675,1951,7075,2087, - 7147,1427,893,171,2019,7235,5697,3615,1961,7517,6849,2893, - 1883,2863,2173,4543,73,381,3893,6045,1643,7669,1027,1549, - 3983,1985,6589,7497,2745,2375,7047,1117,1171,1975,5199,3915, - 3695,8113,4303,3773,7705,6855,1675,2245,2817,1719,569,1021, - 2077,5945,1833,2631,4851,6371,833,7987,331,1899,8093,6719, - 6903,5903,5657,5007,2689,6637,2675,1645,1819,689,6709,7717, - 6295,7013,7695,3705,7069,2621,3631,6571,6259,7261,3397,7645, - 1115,4753,2047,7579,2271,5403,4911,7629,4225,1209,6955,6951, - 1829,5579,5231,1783,4285,7425,599,5785,3275,5643,2263,657, - 6769,6261,1251,3249,4447,4111,3991,1215,131,4397,3487,7585, - 5565,7199,3573,7105,7409,1671,949,3889,5971,3333,225,3647, - 5403,3409,7459,6879,5789,6567,5581,4919,1927,4407,8085,4691, - 611,3005,591,753,589,171,5729,5891,1033,3049,6567,5257,8003, - 1757,4489,4923,6379,5171,1757,689,3081,1389,4113,455,2761, - 847,7575,5829,633,6629,1103,7635,803,6175,6587,2711,3879,67, - 1179,4761,7281,1557,3379,2459,4273,4127,7147,35, - 3549,395,3735,5787,4179,5889,5057, - 7473,4713,2133,2897,1841,2125,1029,1695,6523,1143,5105,7133, - 3351,2775,3971,4503,7589,5155,4305,1641,4717,2427,5617,1267, - 399,5831,4305,4241,3395,3045,4899,1713,171,411,7099,5473, - 5209,1195,1077,1309,2953,7343,4887,3229,6759,6721,6775,675, - 4039,2493,7511,3269,4199,6625,7943,2013,4145,667,513,2303, - 4591,7941,2741,987,8061,3161,5951,1431,831,5559,7405,1357, - 4319,4235,5421,2559,4415,2439,823,1725,6219,4903,6699,5451, - 349,7703,2927,7809,6179,1417,5987,3017,4983,3479,4525,4643, - 4911,227,5475,2287,5581,6817,1937,1421,4415,7977,1789,3907, - 6815,6789,6003,5609,4507,337,7427,7943,3075,6427,1019,7121, - 4763,81,3587,2929,1795,8067,2415,1265,4025,5599,4771,3025, - 2313,6129,7611,6881,5253,4413,7869,105,3173,1629,2537,1023, - 4409,7209,4413,7107,7469,33,1955,2881,5167,6451,4211,179, - 5573,7879,3387,7759,5455,7157,1891,5683,5689,6535,3109,6555, - 6873,1249,4251,6437,49,2745,1201,7327,4179,6783,623,2779, - 5963,2585,6927,5333,4033,285,7467,4443,4917,3, - 4319,5517,3449,813,5499,2515,5771, - 3357,2073,4395,4925,2643,7215,5817,1199,1597,1619,7535,4833, - 609,4797,8171,6847,793,6757,8165,3371,2431,5235,4739,7703, - 7223,6525,5891,5605,4433,3533,5267,5125,5037,225,6717,1121, - 5741,2013,4327,4839,569,5227,7677,4315,2391,5551,859,3627, - 6377,3903,4311,6527,7573,4905,7731,1909,1555,3279,1949,1887, - 6675,5509,2033,5473,3539,5033,5935,6095,4761,1771,1271,1717, - 4415,5083,6277,3147,7695,2461,4783,4539,5833,5583,651,1419, - 2605,5511,3913,5795,2333,2329,4431,3725,6069,2699,7055,6879, - 1017,3121,2547,4603,2385,6915,6103,5669,7833,2001,4287,6619, - 955,2761,5711,6291,3415,3909,2841,5627,4939,7671,6059,6275, - 6517,1931,4583,7301,1267,7509,1435,2169,6939,3515,2985,2787, - 2123,1969,3307,353,4359,7059,5273,5873,6657,6765,6229,3179, - 1583,6237,2155,371,273,7491,3309,6805,3015,6831,7819,713, - 4747,3935,4109,1311,709,3089,7059,4247,2989,1509,4919,1841, - 3045,3821,6929,4655,1333,6429,6649,2131,5265,1051,261,8057, - 3379,2179,1993,5655,3063,6381, - 3587,7417,1579,1541,2107,5085,2873, - 6141,955,3537,2157,841,1999,1465,5171,5651,1535,7235,4349, - 1263,1453,1005,6893,2919,1947,1635,3963,397,969,4569,655, - 6737,2995,7235,7713,973,4821,2377,1673,1,6541} + 2867, 859, 2951, 3211, 15, 1279, 1323, 599, + 1651, 3951, 1011, 315, 3513, 3351, 1725, 3793, 2399, 287, 4017, 3571, + 1007, 541, 3115, 429, 1585, 1285, 755, 1211, 3047, 915, 3611, 2697, 2129, + 3669, 81, 3939, 2437, 915, 779, 3567, 3701, 2479, 3807, 1893, 3927, 2619, + 2543, 3633, 2007, 3857, 3837, 487, 1769, 3759, 3105, 2727, 3155, 2479, + 1341, 1657, 2767, 2541, 577, 2105, 799, 17, 2871, 3637, 953, 65, 69, 2897, + 3841, 3559, 4067, 2335, 3409, 1087, 425, 2813, 1705, 1701, 1237, 821, + 1375, 3673, 2693, 3925, 1541, 1871, 2285, 847, 4035, 1101, 2029, 855, + 2733, 2503, 121, 2855, 1069, 3463, 3505, 1539, 607, 1349, 575, 2301, + 2321, 1101, 333, 291, 2171, 4085, 2173, 2541, 1195, 925, 4039, 1379, 699, + 1979, 275, 953, 1755, 1643, 325, 101, 2263, 3329, 3673, 3413, 1977, 2727, + 2313, 1419, 887, 609, 2475, 591, 2613, 2081, 3805, 3435, 2409, 111, 3557, + 3607, 903, 231, 3059, 473, 2959, 2925, 3861, 2043, 3887, 351, 2865, 369, + 1377, 2639, 1261, 3625, 3279, 2201, 2949, 3049, 449, 1297, 897, 1891, + 411, 2773, 749, 2753, 1825, 853, 2775, 3547, 3923, 3923, 987, 3723, 2189, + 3877, 3577, 297, 2763, 1845, 3083, 2951, 483, 2169, 3985, 245, 3655, + 3441, 1023, 235, 835, 3693, 3585, 327, 1003, 543, 3059, 2637, + 2923, 87, 3617, 1031, 1043, 903, 2913, + 2177, 2641, 3279, 389, 2009, 525, 4085, 3299, 987, 2409, 813, 2683, 373, + 2695, 3775, 2375, 1119, 2791, 223, 325, 587, 1379, 2877, 2867, 3793, 655, + 831, 3425, 1663, 1681, 2657, 1865, 3943, 2977, 1979, 2271, 3247, 1267, + 1747, 811, 159, 429, 2001, 1195, 3065, 553, 1499, 3529, 1081, 2877, 3077, + 845, 1793, 2409, 3995, 2559, 4081, 1195, 2955, 1117, 1409, 785, 287, + 1521, 1607, 85, 3055, 3123, 2533, 2329, 3477, 799, 3683, 3715, 337, 3139, + 3311, 431, 3511, 2299, 365, 2941, 3067, 1331, 1081, 1097, 2853, 2299, + 495, 1745, 749, 3819, 619, 1059, 3559, 183, 3743, 723, 949, 3501, 733, + 2599, 3983, 3961, 911, 1899, 985, 2493, 1795, 653, 157, 433, 2361, 3093, + 3119, 3679, 2367, 1701, 1445, 1321, 2397, 1241, 3305, 3985, 2349, 4067, + 3805, 3073, 2837, 1567, 3783, 451, 2441, 1181, 487, 543, 1201, 3735, + 2517, 733, 1535, 2175, 3613, 3019}, + /* [12][*] */ + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 2319, 653, 1379, 1675, 1951, 7075, 2087, + 7147, 1427, 893, 171, 2019, 7235, 5697, 3615, 1961, 7517, 6849, 2893, + 1883, 2863, 2173, 4543, 73, 381, 3893, 6045, 1643, 7669, 1027, 1549, + 3983, 1985, 6589, 7497, 2745, 2375, 7047, 1117, 1171, 1975, 5199, 3915, + 3695, 8113, 4303, 3773, 7705, 6855, 1675, 2245, 2817, 1719, 569, 1021, + 2077, 5945, 1833, 2631, 4851, 6371, 833, 7987, 331, 1899, 8093, 6719, + 6903, 5903, 5657, 5007, 2689, 6637, 2675, 1645, 1819, 689, 6709, 7717, + 6295, 7013, 7695, 3705, 7069, 2621, 3631, 6571, 6259, 7261, 3397, 7645, + 1115, 4753, 2047, 7579, 2271, 5403, 4911, 7629, 4225, 1209, 6955, 6951, + 1829, 5579, 5231, 1783, 4285, 7425, 599, 5785, 3275, 5643, 2263, 657, + 6769, 6261, 1251, 3249, 4447, 4111, 3991, 1215, 131, 4397, 3487, 7585, + 5565, 7199, 3573, 7105, 7409, 1671, 949, 3889, 5971, 3333, 225, 3647, + 5403, 3409, 7459, 6879, 5789, 6567, 5581, 4919, 1927, 4407, 8085, 4691, + 611, 3005, 591, 753, 589, 171, 5729, 5891, 1033, 3049, 6567, 5257, 8003, + 1757, 4489, 4923, 6379, 5171, 1757, 689, 3081, 1389, 4113, 455, 2761, + 847, 7575, 5829, 633, 6629, 1103, 7635, 803, 6175, 6587, 2711, 3879, 67, + 1179, 4761, 7281, 1557, 3379, 2459, 4273, 4127, 7147, 35, + 3549, 395, 3735, 5787, 4179, 5889, 5057, + 7473, 4713, 2133, 2897, 1841, 2125, 1029, 1695, 6523, 1143, 5105, 7133, + 3351, 2775, 3971, 4503, 7589, 5155, 4305, 1641, 4717, 2427, 5617, 1267, + 399, 5831, 4305, 4241, 3395, 3045, 4899, 1713, 171, 411, 7099, 5473, + 5209, 1195, 1077, 1309, 2953, 7343, 4887, 3229, 6759, 6721, 6775, 675, + 4039, 2493, 7511, 3269, 4199, 6625, 7943, 2013, 4145, 667, 513, 2303, + 4591, 7941, 2741, 987, 8061, 3161, 5951, 1431, 831, 5559, 7405, 1357, + 4319, 4235, 5421, 2559, 4415, 2439, 823, 1725, 6219, 4903, 6699, 5451, + 349, 7703, 2927, 7809, 6179, 1417, 5987, 3017, 4983, 3479, 4525, 4643, + 4911, 227, 5475, 2287, 5581, 6817, 1937, 1421, 4415, 7977, 1789, 3907, + 6815, 6789, 6003, 5609, 4507, 337, 7427, 7943, 3075, 6427, 1019, 7121, + 4763, 81, 3587, 2929, 1795, 8067, 2415, 1265, 4025, 5599, 4771, 3025, + 2313, 6129, 7611, 6881, 5253, 4413, 7869, 105, 3173, 1629, 2537, 1023, + 4409, 7209, 4413, 7107, 7469, 33, 1955, 2881, 5167, 6451, 4211, 179, + 5573, 7879, 3387, 7759, 5455, 7157, 1891, 5683, 5689, 6535, 3109, 6555, + 6873, 1249, 4251, 6437, 49, 2745, 1201, 7327, 4179, 6783, 623, 2779, + 5963, 2585, 6927, 5333, 4033, 285, 7467, 4443, 4917, 3, + 4319, 5517, 3449, 813, 5499, 2515, 5771, + 3357, 2073, 4395, 4925, 2643, 7215, 5817, 1199, 1597, 1619, 7535, 4833, + 609, 4797, 8171, 6847, 793, 6757, 8165, 3371, 2431, 5235, 4739, 7703, + 7223, 6525, 5891, 5605, 4433, 3533, 5267, 5125, 5037, 225, 6717, 1121, + 5741, 2013, 4327, 4839, 569, 5227, 7677, 4315, 2391, 5551, 859, 3627, + 6377, 3903, 4311, 6527, 7573, 4905, 7731, 1909, 1555, 3279, 1949, 1887, + 6675, 5509, 2033, 5473, 3539, 5033, 5935, 6095, 4761, 1771, 1271, 1717, + 4415, 5083, 6277, 3147, 7695, 2461, 4783, 4539, 5833, 5583, 651, 1419, + 2605, 5511, 3913, 5795, 2333, 2329, 4431, 3725, 6069, 2699, 7055, 6879, + 1017, 3121, 2547, 4603, 2385, 6915, 6103, 5669, 7833, 2001, 4287, 6619, + 955, 2761, 5711, 6291, 3415, 3909, 2841, 5627, 4939, 7671, 6059, 6275, + 6517, 1931, 4583, 7301, 1267, 7509, 1435, 2169, 6939, 3515, 2985, 2787, + 2123, 1969, 3307, 353, 4359, 7059, 5273, 5873, 6657, 6765, 6229, 3179, + 1583, 6237, 2155, 371, 273, 7491, 3309, 6805, 3015, 6831, 7819, 713, + 4747, 3935, 4109, 1311, 709, 3089, 7059, 4247, 2989, 1509, 4919, 1841, + 3045, 3821, 6929, 4655, 1333, 6429, 6649, 2131, 5265, 1051, 261, 8057, + 3379, 2179, 1993, 5655, 3063, 6381, + 3587, 7417, 1579, 1541, 2107, 5085, 2873, + 6141, 955, 3537, 2157, 841, 1999, 1465, 5171, 5651, 1535, 7235, 4349, + 1263, 1453, 1005, 6893, 2919, 1947, 1635, 3963, 397, 969, 4569, 655, + 6737, 2995, 7235, 7713, 973, 4821, 2377, 1673, 1, 6541} }; #endif diff --git a/src/util/sobolseq.c b/src/util/sobolseq.c index b0eb822..6626f51 100644 --- a/src/util/sobolseq.c +++ b/src/util/sobolseq.c @@ -57,21 +57,21 @@ #ifndef HAVE_UINT32_T # if SIZEOF_UNSIGNED_LONG == 4 - typedef unsigned long uint32_t; +typedef unsigned long uint32_t; # elif SIZEOF_UNSIGNED_INT == 4 - typedef unsigned int uint32_t; +typedef unsigned int uint32_t; # else # error No 32-bit unsigned integer type # endif #endif typedef struct nlopt_soboldata_s { - unsigned sdim; /* dimension of sequence being generated */ - uint32_t *mdata; /* array of length 32 * sdim */ - uint32_t *m[32]; /* more convenient pointers to mdata, of direction #s */ - uint32_t *x; /* previous x = x_n, array of length sdim */ - unsigned *b; /* position of fixed point in x[i] is after bit b[i] */ - uint32_t n; /* number of x's generated so far */ + unsigned sdim; /* dimension of sequence being generated */ + uint32_t *mdata; /* array of length 32 * sdim */ + uint32_t *m[32]; /* more convenient pointers to mdata, of direction #s */ + uint32_t *x; /* previous x = x_n, array of length sdim */ + unsigned *b; /* position of fixed point in x[i] is after bit b[i] */ + uint32_t n; /* number of x's generated so far */ } soboldata; /* Return position (0, 1, ...) of rightmost (least-significant) zero bit in n. @@ -88,105 +88,114 @@ static unsigned rightzero32(uint32_t n) { #if defined(__GNUC__) && \ ((__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || __GNUC__ > 3) - return __builtin_ctz(~n); /* gcc builtin for version >= 3.4 */ + return __builtin_ctz(~n); /* gcc builtin for version >= 3.4 */ #else - const uint32_t a = 0x05f66a47; /* magic number, found by brute force */ - static const unsigned decode[32] = {0,1,2,26,23,3,15,27,24,21,19,4,12,16,28,6,31,25,22,14,20,18,11,5,30,13,17,10,29,9,8,7}; - n = ~n; /* change to rightmost-one problem */ - n = a * (n & (-n)); /* store in n to make sure mult. is 32 bits */ - return decode[n >> 27]; + const uint32_t a = 0x05f66a47; /* magic number, found by brute force */ + static const unsigned decode[32] = { 0, 1, 2, 26, 23, 3, 15, 27, 24, 21, 19, 4, 12, 16, 28, 6, 31, 25, 22, 14, 20, 18, 11, 5, 30, 13, 17, 10, 29, 9, 8, 7 }; + n = ~n; /* change to rightmost-one problem */ + n = a * (n & (-n)); /* store in n to make sure mult. is 32 bits */ + return decode[n >> 27]; #endif } /* generate the next term x_{n+1} in the Sobol sequence, as an array x[sdim] of numbers in (0,1). Returns 1 on success, 0 on failure (if too many #'s generated) */ -static int sobol_gen(soboldata *sd, double *x) +static int sobol_gen(soboldata * sd, double *x) { - unsigned c, b, i, sdim; - - if (sd->n == 4294967295U) return 0; /* n == 2^32 - 1 ... we would - need to switch to a 64-bit version - to generate more terms. */ - c = rightzero32(sd->n++); - sdim = sd->sdim; - for (i = 0; i < sdim; ++i) { - b = sd->b[i]; - if (b >= c) { - sd->x[i] ^= sd->m[c][i] << (b - c); - x[i] = ((double) (sd->x[i])) / (1U << (b+1)); - } - else { - sd->x[i] = (sd->x[i] << (c - b)) ^ sd->m[c][i]; - sd->b[i] = c; - x[i] = ((double) (sd->x[i])) / (1U << (c+1)); - } - } - return 1; + unsigned c, b, i, sdim; + + if (sd->n == 4294967295U) + return 0; /* n == 2^32 - 1 ... we would + need to switch to a 64-bit version + to generate more terms. */ + c = rightzero32(sd->n++); + sdim = sd->sdim; + for (i = 0; i < sdim; ++i) { + b = sd->b[i]; + if (b >= c) { + sd->x[i] ^= sd->m[c][i] << (b - c); + x[i] = ((double) (sd->x[i])) / (1U << (b + 1)); + } else { + sd->x[i] = (sd->x[i] << (c - b)) ^ sd->m[c][i]; + sd->b[i] = c; + x[i] = ((double) (sd->x[i])) / (1U << (c + 1)); + } + } + return 1; } #include "soboldata.h" -static int sobol_init(soboldata *sd, unsigned sdim) +static int sobol_init(soboldata * sd, unsigned sdim) { - unsigned i,j; - - if (!sdim || sdim > MAXDIM) return 0; - - sd->mdata = (uint32_t *) malloc(sizeof(uint32_t) * (sdim * 32)); - if (!sd->mdata) return 0; - - for (j = 0; j < 32; ++j) { - sd->m[j] = sd->mdata + j * sdim; - sd->m[j][0] = 1; /* special-case Sobol sequence */ - } - for (i = 1; i < sdim; ++i) { - uint32_t a = sobol_a[i-1]; - unsigned d = 0, k; - - while (a) { - ++d; - a >>= 1; - } - d--; /* d is now degree of poly */ - - /* set initial values of m from table */ - for (j = 0; j < d; ++j) - sd->m[j][i] = sobol_minit[j][i-1]; - - /* fill in remaining values using recurrence */ - for (j = d; j < 32; ++j) { - a = sobol_a[i-1]; - sd->m[j][i] = sd->m[j - d][i]; - for (k = 0; k < d; ++k) { - sd->m[j][i] ^= ((a & 1) * sd->m[j-d+k][i]) << (d-k); - a >>= 1; - } - } - } - - sd->x = (uint32_t *) malloc(sizeof(uint32_t) * sdim); - if (!sd->x) { free(sd->mdata); return 0; } - - sd->b = (unsigned *) malloc(sizeof(unsigned) * sdim); - if (!sd->b) { free(sd->x); free(sd->mdata); return 0; } - - for (i = 0; i < sdim; ++i) { - sd->x[i] = 0; - sd->b[i] = 0; - } - - sd->n = 0; - sd->sdim = sdim; - - return 1; + unsigned i, j; + + if (!sdim || sdim > MAXDIM) + return 0; + + sd->mdata = (uint32_t *) malloc(sizeof(uint32_t) * (sdim * 32)); + if (!sd->mdata) + return 0; + + for (j = 0; j < 32; ++j) { + sd->m[j] = sd->mdata + j * sdim; + sd->m[j][0] = 1; /* special-case Sobol sequence */ + } + for (i = 1; i < sdim; ++i) { + uint32_t a = sobol_a[i - 1]; + unsigned d = 0, k; + + while (a) { + ++d; + a >>= 1; + } + d--; /* d is now degree of poly */ + + /* set initial values of m from table */ + for (j = 0; j < d; ++j) + sd->m[j][i] = sobol_minit[j][i - 1]; + + /* fill in remaining values using recurrence */ + for (j = d; j < 32; ++j) { + a = sobol_a[i - 1]; + sd->m[j][i] = sd->m[j - d][i]; + for (k = 0; k < d; ++k) { + sd->m[j][i] ^= ((a & 1) * sd->m[j - d + k][i]) << (d - k); + a >>= 1; + } + } + } + + sd->x = (uint32_t *) malloc(sizeof(uint32_t) * sdim); + if (!sd->x) { + free(sd->mdata); + return 0; + } + + sd->b = (unsigned *) malloc(sizeof(unsigned) * sdim); + if (!sd->b) { + free(sd->x); + free(sd->mdata); + return 0; + } + + for (i = 0; i < sdim; ++i) { + sd->x[i] = 0; + sd->b[i] = 0; + } + + sd->n = 0; + sd->sdim = sdim; + + return 1; } -static void sobol_destroy(soboldata *sd) +static void sobol_destroy(soboldata * sd) { - free(sd->mdata); - free(sd->x); - free(sd->b); + free(sd->mdata); + free(sd->x); + free(sd->b); } /************************************************************************/ @@ -195,40 +204,43 @@ static void sobol_destroy(soboldata *sd) nlopt_sobol nlopt_sobol_create(unsigned sdim) { - nlopt_sobol s = (nlopt_sobol) malloc(sizeof(soboldata)); - if (!s) return NULL; - if (!sobol_init(s, sdim)) { free(s); return NULL; } - return s; + nlopt_sobol s = (nlopt_sobol) malloc(sizeof(soboldata)); + if (!s) + return NULL; + if (!sobol_init(s, sdim)) { + free(s); + return NULL; + } + return s; } extern void nlopt_sobol_destroy(nlopt_sobol s) { - if (s) { - sobol_destroy(s); - free(s); - } + if (s) { + sobol_destroy(s); + free(s); + } } /* next vector x[sdim] in Sobol sequence, with each x[i] in (0,1) */ void nlopt_sobol_next01(nlopt_sobol s, double *x) { - if (!sobol_gen(s, x)) { - /* fall back on pseudo random numbers in the unlikely event - that we exceed 2^32-1 points */ - unsigned i; - for (i = 0; i < s->sdim; ++i) - x[i] = nlopt_urand(0.0,1.0); - } + if (!sobol_gen(s, x)) { + /* fall back on pseudo random numbers in the unlikely event + that we exceed 2^32-1 points */ + unsigned i; + for (i = 0; i < s->sdim; ++i) + x[i] = nlopt_urand(0.0, 1.0); + } } /* next vector in Sobol sequence, scaled to (lb[i], ub[i]) interval */ -void nlopt_sobol_next(nlopt_sobol s, double *x, - const double *lb, const double *ub) +void nlopt_sobol_next(nlopt_sobol s, double *x, const double *lb, const double *ub) { - unsigned i, sdim; - nlopt_sobol_next01(s, x); - for (sdim = s->sdim, i = 0; i < sdim; ++i) - x[i] = lb[i] + (ub[i] - lb[i]) * x[i]; + unsigned i, sdim; + nlopt_sobol_next01(s, x); + for (sdim = s->sdim, i = 0; i < sdim; ++i) + x[i] = lb[i] + (ub[i] - lb[i]) * x[i]; } /* if we know in advance how many points (n) we want to compute, then @@ -237,9 +249,11 @@ void nlopt_sobol_next(nlopt_sobol s, double *x, points equal to the largest power of 2 smaller than n */ void nlopt_sobol_skip(nlopt_sobol s, unsigned n, double *x) { - if (s) { - unsigned k = 1; - while (k*2 < n) k *= 2; - while (k-- > 0) sobol_gen(s, x); - } + if (s) { + unsigned k = 1; + while (k * 2 < n) + k *= 2; + while (k-- > 0) + sobol_gen(s, x); + } } diff --git a/src/util/sobolseq_test.c b/src/util/sobolseq_test.c index 0936ae1..7e8c08a 100644 --- a/src/util/sobolseq_test.c +++ b/src/util/sobolseq_test.c @@ -35,7 +35,7 @@ static double testfunc(unsigned n, const double *x) unsigned j; for (j = 1; j <= n; ++j) { double cj = pow((double) j, 0.3333333333333333333); - f *= (fabs(4*x[j-1] - 2) + cj) / (1 + cj); + f *= (fabs(4 * x[j - 1] - 2) + cj) / (1 + cj); } return f; } @@ -60,16 +60,16 @@ int main(int argc, char **argv) testint_sobol += testfunc(sdim, x); if (j < 100) { printf("x[%u]: %g", j, x[0]); - for (i = 1; i < sdim; ++i) printf(", %g", x[i]); + for (i = 1; i < sdim; ++i) + printf(", %g", x[i]); printf("\n"); } - for (i = 0; i < sdim; ++i) x[i] = nlopt_urand(0.,1.); + for (i = 0; i < sdim; ++i) + x[i] = nlopt_urand(0., 1.); testint_rand += testfunc(sdim, x); } nlopt_sobol_destroy(s); - printf("Test integral = %g using Sobol, %g using pseudorandom.\n", - testint_sobol / n, testint_rand / n); - printf(" error = %g using Sobol, %g using pseudorandom.\n", - testint_sobol / n - 1, testint_rand / n - 1); + printf("Test integral = %g using Sobol, %g using pseudorandom.\n", testint_sobol / n, testint_rand / n); + printf(" error = %g using Sobol, %g using pseudorandom.\n", testint_sobol / n - 1, testint_rand / n - 1); return 0; } diff --git a/src/util/stop.c b/src/util/stop.c index b834b55..dcdf6cc 100644 --- a/src/util/stop.c +++ b/src/util/stop.c @@ -31,110 +31,103 @@ static int relstop(double vold, double vnew, double reltol, double abstol) { - if (nlopt_isinf(vold)) return 0; - return(fabs(vnew - vold) < abstol - || fabs(vnew - vold) < reltol * (fabs(vnew) + fabs(vold)) * 0.5 - || (reltol > 0 && vnew == vold)); /* catch vnew == vold == 0 */ + if (nlopt_isinf(vold)) + return 0; + return (fabs(vnew - vold) < abstol || fabs(vnew - vold) < reltol * (fabs(vnew) + fabs(vold)) * 0.5 || (reltol > 0 && vnew == vold)); /* catch vnew == vold == 0 */ } -int nlopt_stop_ftol(const nlopt_stopping *s, double f, double oldf) +int nlopt_stop_ftol(const nlopt_stopping * s, double f, double oldf) { - return (relstop(oldf, f, s->ftol_rel, s->ftol_abs)); + return (relstop(oldf, f, s->ftol_rel, s->ftol_abs)); } -int nlopt_stop_f(const nlopt_stopping *s, double f, double oldf) +int nlopt_stop_f(const nlopt_stopping * s, double f, double oldf) { - return (f <= s->minf_max || nlopt_stop_ftol(s, f, oldf)); + return (f <= s->minf_max || nlopt_stop_ftol(s, f, oldf)); } -int nlopt_stop_x(const nlopt_stopping *s, const double *x, const double *oldx) +int nlopt_stop_x(const nlopt_stopping * s, const double *x, const double *oldx) { - unsigned i; - for (i = 0; i < s->n; ++i) - if (!relstop(oldx[i], x[i], s->xtol_rel, s->xtol_abs[i])) - return 0; - return 1; + unsigned i; + for (i = 0; i < s->n; ++i) + if (!relstop(oldx[i], x[i], s->xtol_rel, s->xtol_abs[i])) + return 0; + return 1; } -int nlopt_stop_dx(const nlopt_stopping *s, const double *x, const double *dx) +int nlopt_stop_dx(const nlopt_stopping * s, const double *x, const double *dx) { - unsigned i; - for (i = 0; i < s->n; ++i) - if (!relstop(x[i] - dx[i], x[i], s->xtol_rel, s->xtol_abs[i])) - return 0; - return 1; + unsigned i; + for (i = 0; i < s->n; ++i) + if (!relstop(x[i] - dx[i], x[i], s->xtol_rel, s->xtol_abs[i])) + return 0; + return 1; } static double sc(double x, double smin, double smax) { - return smin + x * (smax - smin); + return smin + x * (smax - smin); } /* some of the algorithms rescale x to a unit hypercube, so we need to scale back before we can compare to the tolerances */ -int nlopt_stop_xs(const nlopt_stopping *s, - const double *xs, const double *oldxs, - const double *scale_min, const double *scale_max) +int nlopt_stop_xs(const nlopt_stopping * s, const double *xs, const double *oldxs, const double *scale_min, const double *scale_max) { - unsigned i; - for (i = 0; i < s->n; ++i) - if (relstop(sc(oldxs[i], scale_min[i], scale_max[i]), - sc(xs[i], scale_min[i], scale_max[i]), - s->xtol_rel, s->xtol_abs[i])) - return 1; - return 0; + unsigned i; + for (i = 0; i < s->n; ++i) + if (relstop(sc(oldxs[i], scale_min[i], scale_max[i]), sc(xs[i], scale_min[i], scale_max[i]), s->xtol_rel, s->xtol_abs[i])) + return 1; + return 0; } -int nlopt_stop_evals(const nlopt_stopping *s) +int nlopt_stop_evals(const nlopt_stopping * s) { - return (s->maxeval > 0 && *(s->nevals_p) >= s->maxeval); + return (s->maxeval > 0 && *(s->nevals_p) >= s->maxeval); } int nlopt_stop_time_(double start, double maxtime) { - return (maxtime > 0 && nlopt_seconds() - start >= maxtime); + return (maxtime > 0 && nlopt_seconds() - start >= maxtime); } -int nlopt_stop_time(const nlopt_stopping *s) +int nlopt_stop_time(const nlopt_stopping * s) { - return nlopt_stop_time_(s->start, s->maxtime); + return nlopt_stop_time_(s->start, s->maxtime); } -int nlopt_stop_evalstime(const nlopt_stopping *stop) +int nlopt_stop_evalstime(const nlopt_stopping * stop) { - return nlopt_stop_evals(stop) || nlopt_stop_time(stop); + return nlopt_stop_evals(stop) || nlopt_stop_time(stop); } -int nlopt_stop_forced(const nlopt_stopping *stop) +int nlopt_stop_forced(const nlopt_stopping * stop) { - return stop->force_stop && *(stop->force_stop); + return stop->force_stop && *(stop->force_stop); } -unsigned nlopt_count_constraints(unsigned p, const nlopt_constraint *c) +unsigned nlopt_count_constraints(unsigned p, const nlopt_constraint * c) { - unsigned i, count = 0; - for (i = 0; i < p; ++i) - count += c[i].m; - return count; + unsigned i, count = 0; + for (i = 0; i < p; ++i) + count += c[i].m; + return count; } -unsigned nlopt_max_constraint_dim(unsigned p, const nlopt_constraint *c) +unsigned nlopt_max_constraint_dim(unsigned p, const nlopt_constraint * c) { - unsigned i, max_dim = 0; - for (i = 0; i < p; ++i) - if (c[i].m > max_dim) - max_dim = c[i].m; - return max_dim; + unsigned i, max_dim = 0; + for (i = 0; i < p; ++i) + if (c[i].m > max_dim) + max_dim = c[i].m; + return max_dim; } -void nlopt_eval_constraint(double *result, double *grad, - const nlopt_constraint *c, - unsigned n, const double *x) +void nlopt_eval_constraint(double *result, double *grad, const nlopt_constraint * c, unsigned n, const double *x) { - if (c->f) - result[0] = c->f(n, x, grad, c->f_data); - else - c->mf(c->m, result, n, x, grad, c->f_data); + if (c->f) + result[0] = c->f(n, x, grad, c->f_data); + else + c->mf(c->m, result, n, x, grad, c->f_data); } char *nlopt_vsprintf(char *p, const char *format, va_list ap) @@ -143,20 +136,22 @@ char *nlopt_vsprintf(char *p, const char *format, va_list ap) int ret; p = (char *) realloc(p, len); - if (!p) abort(); + if (!p) + abort(); /* TODO: check HAVE_VSNPRINTF, and fallback to vsprintf otherwise */ - while ((ret = vsnprintf(p, len, format, ap)) < 0 || (size_t)ret >= len) { + while ((ret = vsnprintf(p, len, format, ap)) < 0 || (size_t) ret >= len) { /* C99 vsnprintf returns the required number of bytes (excluding \0) if the buffer is too small; older versions (e.g. MS) return -1 */ - len = ret >= 0 ? (size_t)(ret + 1) : (len*3)>>1; + len = ret >= 0 ? (size_t) (ret + 1) : (len * 3) >> 1; p = (char *) realloc(p, len); - if (!p) abort(); + if (!p) + abort(); } return p; } -void nlopt_stop_msg(const nlopt_stopping *s, const char *format, ...) +void nlopt_stop_msg(const nlopt_stopping * s, const char *format, ...) { va_list ap; if (s->stop_msg) { @@ -176,7 +171,7 @@ int nlopt_isinf(double x) #else || (!nlopt_isnan(x) && nlopt_isnan(x - x)) #endif - ; + ; } int nlopt_isfinite(double x) @@ -187,7 +182,7 @@ int nlopt_isfinite(double x) #elif defined(_WIN32) || _finite(x) #endif - ; + ; } int nlopt_istiny(double x) @@ -201,7 +196,7 @@ int nlopt_istiny(double x) int c = _fpclass(x); return c == _FPCLASS_ND || c == _FPCLASS_PD; #else - return fabs(x) < 2.2250738585072014e-308; /* assume IEEE 754 double */ + return fabs(x) < 2.2250738585072014e-308; /* assume IEEE 754 double */ #endif } } @@ -213,6 +208,6 @@ int nlopt_isnan(double x) #elif defined(_WIN32) return _isnan(x); #else - return (x != x); /* might fail with aggressive optimization */ + return (x != x); /* might fail with aggressive optimization */ #endif } diff --git a/src/util/timer.c b/src/util/timer.c index 7eb7f29..2319a08 100644 --- a/src/util/timer.c +++ b/src/util/timer.c @@ -34,43 +34,43 @@ #endif #if defined(_WIN32) || defined(__WIN32__) -# include +# include #endif /* return time in seconds since some arbitrary point in the past */ double nlopt_seconds(void) { - static THREADLOCAL int start_inited = 0; /* whether start time has been initialized */ + static THREADLOCAL int start_inited = 0; /* whether start time has been initialized */ #if defined(HAVE_GETTIMEOFDAY) - static THREADLOCAL struct timeval start; - struct timeval tv; - if (!start_inited) { - start_inited = 1; - gettimeofday(&start, NULL); - } - gettimeofday(&tv, NULL); - return (tv.tv_sec - start.tv_sec) + 1.e-6 * (tv.tv_usec - start.tv_usec); + static THREADLOCAL struct timeval start; + struct timeval tv; + if (!start_inited) { + start_inited = 1; + gettimeofday(&start, NULL); + } + gettimeofday(&tv, NULL); + return (tv.tv_sec - start.tv_sec) + 1.e-6 * (tv.tv_usec - start.tv_usec); #elif defined(HAVE_TIME) - return time(NULL); + return time(NULL); #elif defined(_WIN32) || defined(__WIN32__) - static THREADLOCAL ULONGLONG start; - FILETIME ft; - if (!start_inited) { - start_inited = 1; - GetSystemTimeAsFileTime(&ft); - start = (((ULONGLONG) ft.dwHighDateTime) << 32) + ft.dwLowDateTime; - } - GetSystemTimeAsFileTime(&ft); - return 100e-9 * (((((ULONGLONG) ft.dwHighDateTime) << 32) + ft.dwLowDateTime) - start); + static THREADLOCAL ULONGLONG start; + FILETIME ft; + if (!start_inited) { + start_inited = 1; + GetSystemTimeAsFileTime(&ft); + start = (((ULONGLONG) ft.dwHighDateTime) << 32) + ft.dwLowDateTime; + } + GetSystemTimeAsFileTime(&ft); + return 100e-9 * (((((ULONGLONG) ft.dwHighDateTime) << 32) + ft.dwLowDateTime) - start); #else - /* use clock() as a fallback... this is somewhat annoying - because clock() may wrap around with a fairly short period */ - static THREADLOCAL clock_t start; - if (!start_inited) { - start_inited = 1; - start = clock(); - } - return (clock() - start) * 1.0 / CLOCKS_PER_SEC; + /* use clock() as a fallback... this is somewhat annoying + because clock() may wrap around with a fairly short period */ + static THREADLOCAL clock_t start; + if (!start_inited) { + start_inited = 1; + start = clock(); + } + return (clock() - start) * 1.0 / CLOCKS_PER_SEC; #endif } @@ -78,16 +78,16 @@ double nlopt_seconds(void) unsigned long nlopt_time_seed(void) { #if defined(HAVE_GETTIMEOFDAY) - struct timeval tv; - gettimeofday(&tv, NULL); - return (tv.tv_sec ^ tv.tv_usec); + struct timeval tv; + gettimeofday(&tv, NULL); + return (tv.tv_sec ^ tv.tv_usec); #elif defined(HAVE_TIME) - return time(NULL); + return time(NULL); #elif defined(_WIN32) || defined(__WIN32__) - FILETIME ft; - GetSystemTimeAsFileTime(&ft); - return ft.dwHighDateTime ^ ft.dwLowDateTime; + FILETIME ft; + GetSystemTimeAsFileTime(&ft); + return ft.dwHighDateTime ^ ft.dwLowDateTime; #else - return clock(); + return clock(); #endif } diff --git a/test/box.c b/test/box.c index ebe728e..884129e 100644 --- a/test/box.c +++ b/test/box.c @@ -11,136 +11,131 @@ int testfuncs_counter = 0; static double testfuncs_status(int n, const double *x, double f) { - ++testfuncs_counter; - if (testfuncs_verbose) { - int i; - printf("f_%d (%g", testfuncs_counter, x[0]); - for (i = 1; i < n; ++i) printf(", %g", x[i]); - printf(") = %g\n", f); - } - return f; + ++testfuncs_counter; + if (testfuncs_verbose) { + int i; + printf("f_%d (%g", testfuncs_counter, x[0]); + for (i = 1; i < n; ++i) + printf(", %g", x[i]); + printf(") = %g\n", f); + } + return f; } #define RETURN(f) return testfuncs_status(n, x, f); -static const double k1=-145421.402, k2=2931.1506, k3=-40.427932, k4=5106.192, - k5=15711.36, k6=-161622.577, k7=4176.15328, k8=2.8260078, - k9=9200.476, k10=13160.295, k11=-21686.9194, k12=123.56928, - k13=-21.1188894, k14=706.834, k15=2898.573, k16=28298.388, - k17=60.81096, k18=31.242116, k19=329.574, k20=-2882.082, - k21=74095.3845, k22=-306.262544, k23=16.243649, k24=-3094.252, - k25=-5566.2628, k26=-26237, k27=99, k28=-0.42, - k29=1300, k30=2100, k31=925548.252, k32=-61968.8432, - k33=23.3088196, k34=-27096.648, k35=-50843.766; +static const double k1 = -145421.402, k2 = 2931.1506, k3 = -40.427932, k4 = 5106.192, + k5 = 15711.36, k6 = -161622.577, k7 = 4176.15328, k8 = 2.8260078, + k9 = 9200.476, k10 = 13160.295, k11 = -21686.9194, k12 = 123.56928, + k13 = -21.1188894, k14 = 706.834, k15 = 2898.573, k16 = 28298.388, + k17 = 60.81096, k18 = 31.242116, k19 = 329.574, k20 = -2882.082, + k21 = 74095.3845, k22 = -306.262544, k23 = 16.243649, k24 = -3094.252, + k25 = -5566.2628, k26 = -26237, k27 = 99, k28 = -0.42, k29 = 1300, k30 = 2100, k31 = 925548.252, k32 = -61968.8432, k33 = 23.3088196, k34 = -27096.648, k35 = -50843.766; static double box(int n, const double *x, double *grad, void *data) { - double x1 = x[0], x2 = x[1], x3 = x[2], x4 = x[3], x5 = x[4]; - double b, x6, y1, y2, y3, y4, u; - const double a0=9, a1=15, a2=50, a3=9.583, a4=20, a5=15, a6=6, a7=0.75; - b = x2 + 0.01*x3; - x6 = (k1 + k2*x2 + k3*x3 + k4*x4 + k5*x5) * x1; - y1 = k6 + k7*x2 + k8*x3 + k9*x4 + k10*x5; - y2 = k11 + k12*x2 + k13*x3 + k14*x4 + k15*x5; - y3 = k16 + k17*x2 + k18*x3 + k19*x4 + k20*x5; - y4 = k21 + k22*x2 + k23*x3 + k24*x4 + k25*x5; - u = a2*y1 + a3*y2 + a4*y3 + a5*y4 + 7840*a6 - 100000*a0 - -50800*b*a7 + k31 + k32*x2 + k33*x3 + k34*x4 + k35*x5; - if (grad) { - int i; - grad[0] = u + a1*(k1 + k2*x2 + k3*x3 + k4*x4 + k5*x5); - grad[1] = x1 * (a2*k7 + a3*k12 + a4*k17 + a5*k22 - 50800*a7 + k32) + a1 * (k2 * x1); - grad[2] = x1 * (a2*k8 + a3*k13 + a4*k18 + a5*k23 - 50800*a7*0.01) + a1*x1*k3; - grad[3] = x1 * (a2*k9 + a3*k14 + a4*k19 + a5*k24) + a1*x1*k4; - grad[4] = x1 * (a2*k10 + a3*k15 + a4*k20 + a5*k25) + a1*x1*k5; - for (i = 0; i < 5; ++i) grad[i] = -grad[i]; - } - RETURN(-(u*x1 - 24345 + a1*x6)); + double x1 = x[0], x2 = x[1], x3 = x[2], x4 = x[3], x5 = x[4]; + double b, x6, y1, y2, y3, y4, u; + const double a0 = 9, a1 = 15, a2 = 50, a3 = 9.583, a4 = 20, a5 = 15, a6 = 6, a7 = 0.75; + b = x2 + 0.01 * x3; + x6 = (k1 + k2 * x2 + k3 * x3 + k4 * x4 + k5 * x5) * x1; + y1 = k6 + k7 * x2 + k8 * x3 + k9 * x4 + k10 * x5; + y2 = k11 + k12 * x2 + k13 * x3 + k14 * x4 + k15 * x5; + y3 = k16 + k17 * x2 + k18 * x3 + k19 * x4 + k20 * x5; + y4 = k21 + k22 * x2 + k23 * x3 + k24 * x4 + k25 * x5; + u = a2 * y1 + a3 * y2 + a4 * y3 + a5 * y4 + 7840 * a6 - 100000 * a0 - 50800 * b * a7 + k31 + k32 * x2 + k33 * x3 + k34 * x4 + k35 * x5; + if (grad) { + int i; + grad[0] = u + a1 * (k1 + k2 * x2 + k3 * x3 + k4 * x4 + k5 * x5); + grad[1] = x1 * (a2 * k7 + a3 * k12 + a4 * k17 + a5 * k22 - 50800 * a7 + k32) + a1 * (k2 * x1); + grad[2] = x1 * (a2 * k8 + a3 * k13 + a4 * k18 + a5 * k23 - 50800 * a7 * 0.01) + a1 * x1 * k3; + grad[3] = x1 * (a2 * k9 + a3 * k14 + a4 * k19 + a5 * k24) + a1 * x1 * k4; + grad[4] = x1 * (a2 * k10 + a3 * k15 + a4 * k20 + a5 * k25) + a1 * x1 * k5; + for (i = 0; i < 5; ++i) + grad[i] = -grad[i]; + } + RETURN(-(u * x1 - 24345 + a1 * x6)); } static double box_constraint(int n, const double *x, double *grad, void *data) { - int which_constraint = *((int*) data); - double x1 = x[0], x2 = x[1], x3 = x[2], x4 = x[3], x5 = x[4]; - double x6, y1, y2, y3, x7, x8; - int i; + int which_constraint = *((int *) data); + double x1 = x[0], x2 = x[1], x3 = x[2], x4 = x[3], x5 = x[4]; + double x6, y1, y2, y3, x7, x8; + int i; - x6 = (k1 + k2*x2 + k3*x3 + k4*x4 + k5*x5) * x1; - y1 = k6 + k7*x2 + k8*x3 + k9*x4 + k10*x5; - y2 = k11 + k12*x2 + k13*x3 + k14*x4 + k15*x5; - y3 = k16 + k17*x2 + k18*x3 + k19*x4 + k20*x5; - x7 = (y1 + y2 + y3) * x1; - x8 = (k26 + k27*x2 + k28*x3 + k29*x4 + k30*x5) * x1 + x6 + x7; + x6 = (k1 + k2 * x2 + k3 * x3 + k4 * x4 + k5 * x5) * x1; + y1 = k6 + k7 * x2 + k8 * x3 + k9 * x4 + k10 * x5; + y2 = k11 + k12 * x2 + k13 * x3 + k14 * x4 + k15 * x5; + y3 = k16 + k17 * x2 + k18 * x3 + k19 * x4 + k20 * x5; + x7 = (y1 + y2 + y3) * x1; + x8 = (k26 + k27 * x2 + k28 * x3 + k29 * x4 + k30 * x5) * x1 + x6 + x7; - if (grad) { - grad[0] = grad[1] = grad[2] = grad[3] = grad[4] = 0; + if (grad) { + grad[0] = grad[1] = grad[2] = grad[3] = grad[4] = 0; - if (which_constraint != 2 && which_constraint != -2) { - /* grad x6 */ - grad[0] += (k1 + k2*x2 + k3*x3 + k4*x4 + k5*x5); - grad[1] += x1 * k2; - grad[2] += x1 * k3; - grad[3] += x1 * k4; - grad[4] += x1 * k5; - } - if (which_constraint != 1 && which_constraint != -1) { - /* grad x7 */ - grad[0] += (y1 + y2 + y3); - grad[1] += x1 * (k7 + k12 + k17); - grad[2] += x1 * (k8 + k13 + k18); - grad[3] += x1 * (k9 + k14 + k19); - grad[4] += x1 * (k10 + k15 + k20); - } - if (which_constraint == 3 || which_constraint == -3) { - /* grad (x8 - x6 - x7) */ - grad[0] += k26 + k27*x2 + k28*x3 + k29*x4 + k30*x5; - grad[1] += x1 * k27; - grad[2] += x1 * k28; - grad[3] += x1 * k29; - grad[4] += x1 * k30; - } - } + if (which_constraint != 2 && which_constraint != -2) { + /* grad x6 */ + grad[0] += (k1 + k2 * x2 + k3 * x3 + k4 * x4 + k5 * x5); + grad[1] += x1 * k2; + grad[2] += x1 * k3; + grad[3] += x1 * k4; + grad[4] += x1 * k5; + } + if (which_constraint != 1 && which_constraint != -1) { + /* grad x7 */ + grad[0] += (y1 + y2 + y3); + grad[1] += x1 * (k7 + k12 + k17); + grad[2] += x1 * (k8 + k13 + k18); + grad[3] += x1 * (k9 + k14 + k19); + grad[4] += x1 * (k10 + k15 + k20); + } + if (which_constraint == 3 || which_constraint == -3) { + /* grad (x8 - x6 - x7) */ + grad[0] += k26 + k27 * x2 + k28 * x3 + k29 * x4 + k30 * x5; + grad[1] += x1 * k27; + grad[2] += x1 * k28; + grad[3] += x1 * k29; + grad[4] += x1 * k30; + } + } - if (which_constraint == -1) { - if (grad) for (i = 0; i < 5; ++i) grad[i] = -grad[i]; - return -x6; - } - else if (which_constraint == 1) { - return x6 - 294000; - } - else if (which_constraint == -2) { - if (grad) for (i = 0; i < 5; ++i) grad[i] = -grad[i]; - return -x7; - } - else if (which_constraint == 2) { - return x7 - 294000; - } - else if (which_constraint == -3) { - if (grad) for (i = 0; i < 5; ++i) grad[i] = -grad[i]; - return -x8; - } - else if (which_constraint == 3) { - return x8 - 277200; - } - return 0; + if (which_constraint == -1) { + if (grad) + for (i = 0; i < 5; ++i) + grad[i] = -grad[i]; + return -x6; + } else if (which_constraint == 1) { + return x6 - 294000; + } else if (which_constraint == -2) { + if (grad) + for (i = 0; i < 5; ++i) + grad[i] = -grad[i]; + return -x7; + } else if (which_constraint == 2) { + return x7 - 294000; + } else if (which_constraint == -3) { + if (grad) + for (i = 0; i < 5; ++i) + grad[i] = -grad[i]; + return -x8; + } else if (which_constraint == 3) { + return x8 - 277200; + } + return 0; } int main(void) { - const double box_lb[5] = {0,1.2,20,9,6.5}; - const double box_ub[5] = {HUGE_VAL, 2.4, 60, 9.3, 7.0}; - const double box_xmin[5] = {4.53743, 2.4, 60, 9.3, 7.0}; + const double box_lb[5] = { 0, 1.2, 20, 9, 6.5 }; + const double box_ub[5] = { HUGE_VAL, 2.4, 60, 9.3, 7.0 }; + const double box_xmin[5] = { 4.53743, 2.4, 60, 9.3, 7.0 }; - int cdata[6] = {-1,1,-2,2,-3,3}; - double x[5] = {2.52, 2, 37.5, 9.25, 6.8}; - double minf; + int cdata[6] = { -1, 1, -2, 2, -3, 3 }; + double x[5] = { 2.52, 2, 37.5, 9.25, 6.8 }; + double minf; - nlopt_minimize_constrained(NLOPT_LN_COBYLA, 5, box, NULL, - 6, box_constraint, cdata, sizeof(int), - box_lb, box_ub, x, &minf, - -HUGE_VAL, - 1e-10, 0, 0, NULL, 0, 0); - printf("found f(%g,%g,%g,%g,%g) = %0.8f after %d iters\n", - x[0],x[1],x[2],x[3],x[4], minf, testfuncs_counter); - return 0; + nlopt_minimize_constrained(NLOPT_LN_COBYLA, 5, box, NULL, 6, box_constraint, cdata, sizeof(int), box_lb, box_ub, x, &minf, -HUGE_VAL, 1e-10, 0, 0, NULL, 0, 0); + printf("found f(%g,%g,%g,%g,%g) = %0.8f after %d iters\n", x[0], x[1], x[2], x[3], x[4], minf, testfuncs_counter); + return 0; } diff --git a/test/lorentzfit.c b/test/lorentzfit.c index afa957a..6566425 100644 --- a/test/lorentzfit.c +++ b/test/lorentzfit.c @@ -5,102 +5,97 @@ #include typedef struct { - int N; - double *x, *y; /* length N; */ + int N; + double *x, *y; /* length N; */ } lorentzdata; -static double sqr(double x) { return x * x; } +static double sqr(double x) +{ + return x * x; +} static int count = 0; static double lorentzerr(int n, const double *p, double *grad, void *data) { - lorentzdata *d = (lorentzdata *) data; - int N = d->N; - const double *xs = d->x; - const double *ys = d->y; - double val = 0; - int i, j; - - for (i = 0; i < N; ++i) { - double x = xs[i], y = ys[i]; - double lorsum = 0; - - for (j = 0; j < n; j += 3) { - double A = p[j + 0]; - double w = p[j + 1]; - double G = p[j + 2]; - double lor = A / (sqr(x - w) + G*G); - - lorsum += lor; - } - - val += sqr(y - lorsum); - - if (grad) - for (j = 0; j < n; j += 3) { - double A = p[j + 0]; - double w = p[j + 1]; - double G = p[j + 2]; - double deninv = 1.0 / (sqr(x - w) + G*G); - - grad[j + 0] += -2 * (y - lorsum) * deninv; - grad[j + 1] += 4*A * (w - x) * (y - lorsum) * sqr(deninv); - grad[j + 2] += 4*A * G * (y - lorsum) * sqr(deninv); - } - } - ++count; - // printf("%d: f(%g,%g,%g) = %g\n", count, p[0],p[1],p[2], val); - return val; + lorentzdata *d = (lorentzdata *) data; + int N = d->N; + const double *xs = d->x; + const double *ys = d->y; + double val = 0; + int i, j; + + for (i = 0; i < N; ++i) { + double x = xs[i], y = ys[i]; + double lorsum = 0; + + for (j = 0; j < n; j += 3) { + double A = p[j + 0]; + double w = p[j + 1]; + double G = p[j + 2]; + double lor = A / (sqr(x - w) + G * G); + + lorsum += lor; + } + + val += sqr(y - lorsum); + + if (grad) + for (j = 0; j < n; j += 3) { + double A = p[j + 0]; + double w = p[j + 1]; + double G = p[j + 2]; + double deninv = 1.0 / (sqr(x - w) + G * G); + + grad[j + 0] += -2 * (y - lorsum) * deninv; + grad[j + 1] += 4 * A * (w - x) * (y - lorsum) * sqr(deninv); + grad[j + 2] += 4 * A * G * (y - lorsum) * sqr(deninv); + } + } + ++count; + // printf("%d: f(%g,%g,%g) = %g\n", count, p[0],p[1],p[2], val); + return val; } extern double nlopt_urand(double a, double b); int main(void) { - lorentzdata d; - int i; - double A = 1, w = 0, G = 1, noise=0.01; - double lb[3] = {-HUGE_VAL,-HUGE_VAL,0}; - double ub[3] = {HUGE_VAL,HUGE_VAL,HUGE_VAL}; - double p[3] = {0,1,2}, minf; + lorentzdata d; + int i; + double A = 1, w = 0, G = 1, noise = 0.01; + double lb[3] = { -HUGE_VAL, -HUGE_VAL, 0 }; + double ub[3] = { HUGE_VAL, HUGE_VAL, HUGE_VAL }; + double p[3] = { 0, 1, 2 }, minf; - nlopt_srand_time(); + nlopt_srand_time(); - d.N = 200; - d.x = (double *) malloc(sizeof(double) * d.N * 2); - d.y = d.x + d.N; - for (i = 0; i < d.N; ++i) { - d.x[i] = nlopt_urand(-0.5, 0.5) * 8*G + w; - d.y[i] = 2*noise*nlopt_urand(-0.5,0.5) + A / (sqr(d.x[i]-w) + G*G); - } + d.N = 200; + d.x = (double *) malloc(sizeof(double) * d.N * 2); + d.y = d.x + d.N; + for (i = 0; i < d.N; ++i) { + d.x[i] = nlopt_urand(-0.5, 0.5) * 8 * G + w; + d.y[i] = 2 * noise * nlopt_urand(-0.5, 0.5) + A / (sqr(d.x[i] - w) + G * G); + } - nlopt_minimize(NLOPT_LN_NEWUOA_BOUND, 3, lorentzerr, &d, - lb, ub, p, &minf, - -HUGE_VAL, 0,0, 1e-6,NULL, 0,0); + nlopt_minimize(NLOPT_LN_NEWUOA_BOUND, 3, lorentzerr, &d, lb, ub, p, &minf, -HUGE_VAL, 0, 0, 1e-6, NULL, 0, 0); - printf("%d minf=%g at A=%g, w=%g, G=%g\n", count, minf, p[0],p[1],p[2]); + printf("%d minf=%g at A=%g, w=%g, G=%g\n", count, minf, p[0], p[1], p[2]); - count = 0; - nlopt_minimize(NLOPT_LN_COBYLA, 3, lorentzerr, &d, - lb, ub, p, &minf, - -HUGE_VAL, 0,0, 1e-6,NULL, 0,0); + count = 0; + nlopt_minimize(NLOPT_LN_COBYLA, 3, lorentzerr, &d, lb, ub, p, &minf, -HUGE_VAL, 0, 0, 1e-6, NULL, 0, 0); - printf("%d minf=%g at A=%g, w=%g, G=%g\n", count, minf, p[0],p[1],p[2]); + printf("%d minf=%g at A=%g, w=%g, G=%g\n", count, minf, p[0], p[1], p[2]); - count = 0; - nlopt_minimize(NLOPT_LN_NELDERMEAD, 3, lorentzerr, &d, - lb, ub, p, &minf, - -HUGE_VAL, 0,0, 1e-6,NULL, 0,0); + count = 0; + nlopt_minimize(NLOPT_LN_NELDERMEAD, 3, lorentzerr, &d, lb, ub, p, &minf, -HUGE_VAL, 0, 0, 1e-6, NULL, 0, 0); - printf("%d minf=%g at A=%g, w=%g, G=%g\n", count, minf, p[0],p[1],p[2]); + printf("%d minf=%g at A=%g, w=%g, G=%g\n", count, minf, p[0], p[1], p[2]); - count = 0; - nlopt_minimize(NLOPT_LN_SBPLX, 3, lorentzerr, &d, - lb, ub, p, &minf, - -HUGE_VAL, 0,0, 1e-6,NULL, 0,0); + count = 0; + nlopt_minimize(NLOPT_LN_SBPLX, 3, lorentzerr, &d, lb, ub, p, &minf, -HUGE_VAL, 0, 0, 1e-6, NULL, 0, 0); - printf("%d minf=%g at A=%g, w=%g, G=%g\n", count, minf, p[0],p[1],p[2]); + printf("%d minf=%g at A=%g, w=%g, G=%g\n", count, minf, p[0], p[1], p[2]); - return 0; + return 0; } diff --git a/test/testfuncs.c b/test/testfuncs.c index ec6908a..bcdc7c2 100644 --- a/test/testfuncs.c +++ b/test/testfuncs.c @@ -6,500 +6,501 @@ #define UNUSED(x) (void) x -static double sqr(double x) { return x * x; } +static double sqr(double x) +{ + return x * x; +} int testfuncs_verbose = 0; int testfuncs_counter = 0; static double testfuncs_status(unsigned n, const double *x, double f) { - ++testfuncs_counter; - if (testfuncs_verbose) { - unsigned i; - printf("f_%d (%g", testfuncs_counter, x[0]); - for (i = 1; i < n; ++i) printf(", %g", x[i]); - printf(") = %g\n", f); - } - return f; + ++testfuncs_counter; + if (testfuncs_verbose) { + unsigned i; + printf("f_%d (%g", testfuncs_counter, x[0]); + for (i = 1; i < n; ++i) + printf(", %g", x[i]); + printf(") = %g\n", f); + } + return f; } #define RETURN(f) return testfuncs_status(n, x, f); -#define PI2 6.283185307179586 /* 2*pi */ -#define PI3 9.424777960769379 /* 3*pi */ -#define PI4 12.5663706143592 /* 4*pi */ +#define PI2 6.283185307179586 /* 2*pi */ +#define PI3 9.424777960769379 /* 3*pi */ +#define PI4 12.5663706143592 /* 4*pi */ /****************************************************************************/ static double rosenbrock_f(unsigned n, const double *x, double *grad, void *data) { - double a = x[1] - x[0] * x[0], b = 1 - x[0]; - UNUSED(data); - if (grad) { - grad[0] = -400 * a * x[0] - 2*b; - grad[1] = 200 * a; - } - RETURN(100 * sqr(a) + sqr(b)); + double a = x[1] - x[0] * x[0], b = 1 - x[0]; + UNUSED(data); + if (grad) { + grad[0] = -400 * a * x[0] - 2 * b; + grad[1] = 200 * a; + } + RETURN(100 * sqr(a) + sqr(b)); } -static const double rosenbrock_lb[2] = {-2, -2}; -static const double rosenbrock_ub[2] = {2, 2}; -static const double rosenbrock_xmin[2] = {1, 1}; +static const double rosenbrock_lb[2] = { -2, -2 }; +static const double rosenbrock_ub[2] = { 2, 2 }; +static const double rosenbrock_xmin[2] = { 1, 1 }; /****************************************************************************/ static double mccormic_f(unsigned n, const double *x, double *grad, void *data) { - double a = x[0] + x[1], b = x[0] - x[1]; - UNUSED(data); - if (grad) { - grad[0] = cos(a) + 2*b - 1.5; - grad[1] = cos(a) - 2*b + 2.5; - } - RETURN(sin(a) + sqr(b) - 1.5*x[0] + 2.5*x[1] + 1); + double a = x[0] + x[1], b = x[0] - x[1]; + UNUSED(data); + if (grad) { + grad[0] = cos(a) + 2 * b - 1.5; + grad[1] = cos(a) - 2 * b + 2.5; + } + RETURN(sin(a) + sqr(b) - 1.5 * x[0] + 2.5 * x[1] + 1); } -static const double mccormic_lb[2] = {-1.5, -3}; -static const double mccormic_ub[2] = {4, 4}; -static const double mccormic_xmin[2] = {-0.547197553, -1.54719756}; +static const double mccormic_lb[2] = { -1.5, -3 }; +static const double mccormic_ub[2] = { 4, 4 }; +static const double mccormic_xmin[2] = { -0.547197553, -1.54719756 }; /****************************************************************************/ static double boxbetts_f(unsigned n, const double *x, double *grad, void *data) { - unsigned i; - double f = 0; - UNUSED(data); - if (grad) - grad[0] = grad[1] = grad[2] = 0; - for (i = 1; i <= 10; ++i) { - double e0 = exp(-0.1*i*x[0]); - double e1 = exp(-0.1*i*x[1]); - double e2 = exp(-0.1*i) - exp(-1.0*i); - double g = e0 - e1 - e2 * x[2]; - f += sqr(g); - if (grad) { - grad[0] += (2 * g) * (-0.1*i*e0); - grad[1] += (2 * g) * (0.1*i*e1); - grad[2] += -(2 * g) * e2; - } - } - RETURN(f); + unsigned i; + double f = 0; + UNUSED(data); + if (grad) + grad[0] = grad[1] = grad[2] = 0; + for (i = 1; i <= 10; ++i) { + double e0 = exp(-0.1 * i * x[0]); + double e1 = exp(-0.1 * i * x[1]); + double e2 = exp(-0.1 * i) - exp(-1.0 * i); + double g = e0 - e1 - e2 * x[2]; + f += sqr(g); + if (grad) { + grad[0] += (2 * g) * (-0.1 * i * e0); + grad[1] += (2 * g) * (0.1 * i * e1); + grad[2] += -(2 * g) * e2; + } + } + RETURN(f); } -static const double boxbetts_lb[3] = {0.9,9,0.9}; -static const double boxbetts_ub[3] = {1.2,11.2,1.2}; -static const double boxbetts_xmin[3] = {1,10,1}; +static const double boxbetts_lb[3] = { 0.9, 9, 0.9 }; +static const double boxbetts_ub[3] = { 1.2, 11.2, 1.2 }; +static const double boxbetts_xmin[3] = { 1, 10, 1 }; /****************************************************************************/ static double paviani_f(unsigned n, const double *x, double *grad, void *data) { - unsigned i; - double f = 0, prod = 1; - UNUSED(data); - if (grad) for (i = 0; i < 10; ++i) grad[i] = 0; - for (i = 0; i < 10; ++i) { - double ln1 = log(x[i] - 2); - double ln2 = log(10 - x[i]); - f += sqr(ln1) + sqr(ln2); - if (grad) - grad[i] += 2 * ln1 / (x[i] - 2) - 2 * ln2 / (10 - x[i]); - prod *= x[i]; - } - f -= (prod = pow(prod, 0.2)); - if (grad) - for (i = 0; i < 10; ++i) - grad[i] -= 0.2 * prod / x[i]; - RETURN(f); + unsigned i; + double f = 0, prod = 1; + UNUSED(data); + if (grad) + for (i = 0; i < 10; ++i) + grad[i] = 0; + for (i = 0; i < 10; ++i) { + double ln1 = log(x[i] - 2); + double ln2 = log(10 - x[i]); + f += sqr(ln1) + sqr(ln2); + if (grad) + grad[i] += 2 * ln1 / (x[i] - 2) - 2 * ln2 / (10 - x[i]); + prod *= x[i]; + } + f -= (prod = pow(prod, 0.2)); + if (grad) + for (i = 0; i < 10; ++i) + grad[i] -= 0.2 * prod / x[i]; + RETURN(f); } -static const double paviani_lb[10] = {2.001,2.001,2.001,2.001,2.001,2.001,2.001,2.001,2.001,2.001}; -static const double paviani_ub[10] = {9.999,9.999,9.999,9.999,9.999,9.999,9.999,9.999,9.999,9.999}; -static const double paviani_xmin[10] = {9.35026583,9.35026583,9.35026583,9.35026583,9.35026583,9.35026583,9.35026583,9.35026583,9.35026583,9.35026583}; +static const double paviani_lb[10] = { 2.001, 2.001, 2.001, 2.001, 2.001, 2.001, 2.001, 2.001, 2.001, 2.001 }; +static const double paviani_ub[10] = { 9.999, 9.999, 9.999, 9.999, 9.999, 9.999, 9.999, 9.999, 9.999, 9.999 }; +static const double paviani_xmin[10] = { 9.35026583, 9.35026583, 9.35026583, 9.35026583, 9.35026583, 9.35026583, 9.35026583, 9.35026583, 9.35026583, 9.35026583 }; /****************************************************************************/ static double grosenbrock_f(unsigned n, const double *x, double *grad, void *data) { - unsigned i; - double f = 0; - UNUSED(data); - if (grad) grad[0] = 0; - for (i = 0; i < 29; ++i) { - double a = x[i+1] - x[i] * x[i], b = 1 - x[i]; - if (grad) { - grad[i] += -400 * a * x[i] - 2*b; - grad[i+1] = 200 * a; - } - f += 100 * sqr(a) + sqr(b); - } - RETURN(f); + unsigned i; + double f = 0; + UNUSED(data); + if (grad) + grad[0] = 0; + for (i = 0; i < 29; ++i) { + double a = x[i + 1] - x[i] * x[i], b = 1 - x[i]; + if (grad) { + grad[i] += -400 * a * x[i] - 2 * b; + grad[i + 1] = 200 * a; + } + f += 100 * sqr(a) + sqr(b); + } + RETURN(f); } -static const double grosenbrock_lb[30] = {-30,-30,-30,-30,-30,-30,-30,-30,-30,-30,-30,-30,-30,-30,-30,-30,-30,-30,-30,-30,-30,-30,-30,-30,-30,-30,-30,-30,-30,-30}; -static const double grosenbrock_ub[30] = {30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30}; -static const double grosenbrock_xmin[30] = {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}; +static const double grosenbrock_lb[30] = { -30, -30, -30, -30, -30, -30, -30, -30, -30, -30, -30, -30, -30, -30, -30, -30, -30, -30, -30, -30, -30, -30, -30, -30, -30, -30, -30, -30, -30, -30 }; +static const double grosenbrock_ub[30] = { 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30 }; +static const double grosenbrock_xmin[30] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }; /****************************************************************************/ static double goldsteinprice_f(unsigned n, const double *x, double *grad, void *data) { - double x0, x1, a1, a12, a2, b1, b12, b2; - x0 = x[0]; x1 = x[1]; - a1 = x0+x1+1; a12 = sqr(a1); - a2 = 19 - 14*x0 + 3*x0*x0 - 14*x1 + 6*x0*x1 + 3*x1*x1; - b1 = 2*x0-3*x1; b12 = sqr(b1); - b2 = 18 - 32*x0 + 12*x0*x0 + 48*x1 - 36*x0*x1 + 27*x1*x1; - UNUSED(data); - if (grad) { - grad[0] = (1 + a12 * a2) * (2 * b1 * 2 * b2 - + b12 * (-32 + 24*x0 - 36*x1)) - + (2 * a1 * a2 + a12 * (-14 + 6*x0 + 6*x1)) * (30 + b12 * b2); - grad[1] = (1 + a12 * a2) * (2 * b1 * (-3) * b2 - + b12 * (48 - 36*x0 + 54 * x1)) - + (2 * a1 * a2 + a12 * (-14 + 6*x0 + 6*x1)) * (30 + b12 * b2); - } - RETURN((1 + a12 * a2) * (30 + b12 * b2)); + double x0, x1, a1, a12, a2, b1, b12, b2; + x0 = x[0]; + x1 = x[1]; + a1 = x0 + x1 + 1; + a12 = sqr(a1); + a2 = 19 - 14 * x0 + 3 * x0 * x0 - 14 * x1 + 6 * x0 * x1 + 3 * x1 * x1; + b1 = 2 * x0 - 3 * x1; + b12 = sqr(b1); + b2 = 18 - 32 * x0 + 12 * x0 * x0 + 48 * x1 - 36 * x0 * x1 + 27 * x1 * x1; + UNUSED(data); + if (grad) { + grad[0] = (1 + a12 * a2) * (2 * b1 * 2 * b2 + b12 * (-32 + 24 * x0 - 36 * x1)) + + (2 * a1 * a2 + a12 * (-14 + 6 * x0 + 6 * x1)) * (30 + b12 * b2); + grad[1] = (1 + a12 * a2) * (2 * b1 * (-3) * b2 + b12 * (48 - 36 * x0 + 54 * x1)) + + (2 * a1 * a2 + a12 * (-14 + 6 * x0 + 6 * x1)) * (30 + b12 * b2); + } + RETURN((1 + a12 * a2) * (30 + b12 * b2)); } -static const double goldsteinprice_lb[2] = {-2, -2}; -static const double goldsteinprice_ub[2] = {2, 2}; -static const double goldsteinprice_xmin[2] = {0, -1}; +static const double goldsteinprice_lb[2] = { -2, -2 }; +static const double goldsteinprice_ub[2] = { 2, 2 }; +static const double goldsteinprice_xmin[2] = { 0, -1 }; /****************************************************************************/ static double shekel_f(unsigned n, const double *x, double *grad, void *data) { - static const double A[10][4] = { {4,4,4,4}, - {1,1,1,1}, - {8,8,8,8}, - {6,6,6,6}, - {3,7,3,7}, - {2,9,2,9}, - {5,5,3,3}, - {8,1,8,1}, - {6,2,6,2}, - {7,3.6,7,3.6} }; - static const double c[10] = {.1,.2,.2,.4,.4,.6,.3,.7,.5,.5}; - unsigned i; - double f = 0; - unsigned m = *((unsigned *) data); - if (grad) for (i = 0; i < n; ++i) grad[i] = 0; - for (i = 0; i < m; ++i) { - double fi = 1.0 / (c[i] - + sqr(x[0]-A[i][0]) - + sqr(x[1]-A[i][1]) - + sqr(x[2]-A[i][2]) - + sqr(x[3]-A[i][3])); - f -= fi; - if (grad) { - grad[0] += (2*fi*fi) * (x[0]-A[i][0]); - grad[1] += (2*fi*fi) * (x[1]-A[i][1]); - grad[2] += (2*fi*fi) * (x[2]-A[i][2]); - grad[3] += (2*fi*fi) * (x[3]-A[i][3]); - } - } - RETURN(f); + static const double A[10][4] = { {4, 4, 4, 4}, + {1, 1, 1, 1}, + {8, 8, 8, 8}, + {6, 6, 6, 6}, + {3, 7, 3, 7}, + {2, 9, 2, 9}, + {5, 5, 3, 3}, + {8, 1, 8, 1}, + {6, 2, 6, 2}, + {7, 3.6, 7, 3.6} + }; + static const double c[10] = { .1, .2, .2, .4, .4, .6, .3, .7, .5, .5 }; + unsigned i; + double f = 0; + unsigned m = *((unsigned *) data); + if (grad) + for (i = 0; i < n; ++i) + grad[i] = 0; + for (i = 0; i < m; ++i) { + double fi = 1.0 / (c[i] + + sqr(x[0] - A[i][0]) + + sqr(x[1] - A[i][1]) + + sqr(x[2] - A[i][2]) + + sqr(x[3] - A[i][3])); + f -= fi; + if (grad) { + grad[0] += (2 * fi * fi) * (x[0] - A[i][0]); + grad[1] += (2 * fi * fi) * (x[1] - A[i][1]); + grad[2] += (2 * fi * fi) * (x[2] - A[i][2]); + grad[3] += (2 * fi * fi) * (x[3] - A[i][3]); + } + } + RETURN(f); } -static unsigned shekel_m[3] = {5,7,10}; -static const double shekel_lb[4] = {0,0,0,0}; -static const double shekel_ub[4] = {10,10,10,10}; -static const double shekel0_xmin[4] = {4.000037154,4.000133276,4.000037154,4.000133276}; -static const double shekel1_xmin[4] = {4.000572917,4.000689366,3.999489709,3.999606158}; -static const double shekel2_xmin[4] = {4.000746531,4.000592935,3.999663399,3.999509801}; +static unsigned shekel_m[3] = { 5, 7, 10 }; +static const double shekel_lb[4] = { 0, 0, 0, 0 }; +static const double shekel_ub[4] = { 10, 10, 10, 10 }; +static const double shekel0_xmin[4] = { 4.000037154, 4.000133276, 4.000037154, 4.000133276 }; +static const double shekel1_xmin[4] = { 4.000572917, 4.000689366, 3.999489709, 3.999606158 }; +static const double shekel2_xmin[4] = { 4.000746531, 4.000592935, 3.999663399, 3.999509801 }; /****************************************************************************/ static double levy_f(unsigned n, const double *x, double *grad, void *data) { - unsigned i; - double a = x[n-1] - 1, b = 1 + sqr(sin(PI2*x[n-1])); - double f = sqr(sin(PI3*x[0])) + a * b; - UNUSED(data); - if (grad) { - for (i = 0; i < n; ++i) grad[i] = 0; - grad[0] = 2 * PI3 * sin(PI3*x[0]) * cos(PI3*x[0]); - grad[n-1] += b + a * 2 * PI2 * sin(PI2*x[n-1]) * cos(PI2*x[n-1]); - } - for (i = 0; i < n-1; ++i) { - a = x[i] - 1; - b = 1 + sqr(sin(PI3*x[i+1])); - f += sqr(a) * b; - if (grad) { - grad[i] += 2 * a * b; - grad[i+1] += 2*PI3 * sqr(a) * sin(PI3*x[i+1])*cos(PI3*x[i+1]); - } - } - RETURN(f); + unsigned i; + double a = x[n - 1] - 1, b = 1 + sqr(sin(PI2 * x[n - 1])); + double f = sqr(sin(PI3 * x[0])) + a * b; + UNUSED(data); + if (grad) { + for (i = 0; i < n; ++i) + grad[i] = 0; + grad[0] = 2 * PI3 * sin(PI3 * x[0]) * cos(PI3 * x[0]); + grad[n - 1] += b + a * 2 * PI2 * sin(PI2 * x[n - 1]) * cos(PI2 * x[n - 1]); + } + for (i = 0; i < n - 1; ++i) { + a = x[i] - 1; + b = 1 + sqr(sin(PI3 * x[i + 1])); + f += sqr(a) * b; + if (grad) { + grad[i] += 2 * a * b; + grad[i + 1] += 2 * PI3 * sqr(a) * sin(PI3 * x[i + 1]) * cos(PI3 * x[i + 1]); + } + } + RETURN(f); } -static const double levy_lb[7] = {-5,-5,-5,-5,-5,-5,-5}; -static const double levy_ub[7] = {5,5,5,5,5,5,5}; -static const double levy_xmin[7] = {1,1,1,1,1,1,-4.75440246}; -static const double levy4_lb[4] = {-10,-10,-10,-10}; -static const double levy4_ub[4] = {10,10,10,10}; -static const double levy4_xmin[4] = {1,1,1,-9.75235596}; +static const double levy_lb[7] = { -5, -5, -5, -5, -5, -5, -5 }; +static const double levy_ub[7] = { 5, 5, 5, 5, 5, 5, 5 }; +static const double levy_xmin[7] = { 1, 1, 1, 1, 1, 1, -4.75440246 }; +static const double levy4_lb[4] = { -10, -10, -10, -10 }; +static const double levy4_ub[4] = { 10, 10, 10, 10 }; +static const double levy4_xmin[4] = { 1, 1, 1, -9.75235596 }; /****************************************************************************/ static double griewank_f(unsigned n, const double *x, double *grad, void *data) { - unsigned i; - double f = 1, p = 1; - UNUSED(data); - for (i = 0; i < n; ++i) { - f += sqr(x[i]) * 0.00025; - p *= cos(x[i] / sqrt(i + 1.)); - if (grad) grad[i] = x[i] * 0.0005; - } - f -= p; - if (grad) - for (i = 0; i < n; ++i) - grad[i] += p * tan(x[i] / sqrt(i + 1.)) / sqrt(i + 1.); - RETURN(f); + unsigned i; + double f = 1, p = 1; + UNUSED(data); + for (i = 0; i < n; ++i) { + f += sqr(x[i]) * 0.00025; + p *= cos(x[i] / sqrt(i + 1.)); + if (grad) + grad[i] = x[i] * 0.0005; + } + f -= p; + if (grad) + for (i = 0; i < n; ++i) + grad[i] += p * tan(x[i] / sqrt(i + 1.)) / sqrt(i + 1.); + RETURN(f); } -static const double griewank_lb[10] = {-500,-500,-500,-500,-500,-500,-500,-500,-500,-500}; -static const double griewank_ub[10] = {600,600,600,600,600,600,600,600,600,600}; -static const double griewank_xmin[10] = {0,0,0,0,0,0,0,0,0,0}; +static const double griewank_lb[10] = { -500, -500, -500, -500, -500, -500, -500, -500, -500, -500 }; +static const double griewank_ub[10] = { 600, 600, 600, 600, 600, 600, 600, 600, 600, 600 }; +static const double griewank_xmin[10] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; /****************************************************************************/ static double sixhumpcamel_f(unsigned n, const double *x, double *grad, void *data) { - UNUSED(data); - if (grad) { - grad[0] = 8*x[0] - 2.1*4*pow(x[0],3.) + 2*pow(x[0],5.) + x[1]; - grad[1] = x[0] - 8*x[1] + 16*pow(x[1],3.); - } - RETURN(4*sqr(x[0]) - 2.1 * pow(x[0],4.) + pow(x[0],6.)/3. - + x[0]*x[1] - 4*sqr(x[1]) + 4*pow(x[1],4.)); + UNUSED(data); + if (grad) { + grad[0] = 8 * x[0] - 2.1 * 4 * pow(x[0], 3.) + 2 * pow(x[0], 5.) + x[1]; + grad[1] = x[0] - 8 * x[1] + 16 * pow(x[1], 3.); + } + RETURN(4 * sqr(x[0]) - 2.1 * pow(x[0], 4.) + pow(x[0], 6.) / 3. + x[0] * x[1] - 4 * sqr(x[1]) + 4 * pow(x[1], 4.)); } -static const double sixhumpcamel_lb[2] = {-5,-5}; -static const double sixhumpcamel_ub[2] = {5,5}; -static const double sixhumpcamel_xmin[2] = {0.08984201317, -0.7126564032}; +static const double sixhumpcamel_lb[2] = { -5, -5 }; +static const double sixhumpcamel_ub[2] = { 5, 5 }; +static const double sixhumpcamel_xmin[2] = { 0.08984201317, -0.7126564032 }; /****************************************************************************/ static double convexcosh_f(unsigned n, const double *x, double *grad, void *data) { - unsigned i; - double f = 1; - UNUSED(data); - for (i = 0; i < n; ++i) - f *= cosh((x[i] - i) * (i+1)); - if (grad) - for (i = 0; i < n; ++i) - grad[i] = f * tanh((x[i] - i) * (i+1)) * (i+1); - RETURN(f); + unsigned i; + double f = 1; + UNUSED(data); + for (i = 0; i < n; ++i) + f *= cosh((x[i] - i) * (i + 1)); + if (grad) + for (i = 0; i < n; ++i) + grad[i] = f * tanh((x[i] - i) * (i + 1)) * (i + 1); + RETURN(f); } -static const double convexcosh_lb[10] = {-1,0,0,0,0,0,0,0,0,0}; -static const double convexcosh_ub[10] = {2,3,6,7,8,10,11,13,14,16}; -static const double convexcosh_xmin[10] = {0,1,2,3,4,5,6,7,8,9}; +static const double convexcosh_lb[10] = { -1, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; +static const double convexcosh_ub[10] = { 2, 3, 6, 7, 8, 10, 11, 13, 14, 16 }; +static const double convexcosh_xmin[10] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; /****************************************************************************/ static double branin_f(unsigned n, const double *x, double *grad, void *data) { - double a = 1 - 2*x[1] + 0.05 * sin(PI4 * x[1]) - x[0]; - double b = x[1] - 0.5 * sin(PI2 * x[0]); - UNUSED(data); - if (grad) { - grad[0] = -2*a - cos(PI2 * x[0]) * PI2 * b; - grad[1] = 2*a*(0.05 * PI4 * cos(PI4*x[1]) - 2) + 2*b; - } - RETURN(sqr(a) + sqr(b)); + double a = 1 - 2 * x[1] + 0.05 * sin(PI4 * x[1]) - x[0]; + double b = x[1] - 0.5 * sin(PI2 * x[0]); + UNUSED(data); + if (grad) { + grad[0] = -2 * a - cos(PI2 * x[0]) * PI2 * b; + grad[1] = 2 * a * (0.05 * PI4 * cos(PI4 * x[1]) - 2) + 2 * b; + } + RETURN(sqr(a) + sqr(b)); } -static const double branin_lb[2] = {-10,-10}; -static const double branin_ub[2] = {10,10}; -static const double branin_xmin[2] = {1,0}; +static const double branin_lb[2] = { -10, -10 }; +static const double branin_ub[2] = { 10, 10 }; +static const double branin_xmin[2] = { 1, 0 }; /****************************************************************************/ static double shubert_f(unsigned n, const double *x, double *grad, void *data) { - unsigned i, j; - double f = 0; - UNUSED(data); - for (j = 1; j <= 5; ++j) - for (i = 0; i < n; ++i) - f -= j * sin((j+1) * x[i] + j); - if (grad) { - for (i = 0; i < n; ++i) { - grad[i] = 0; - for (j = 1; j <= 5; ++j) - grad[i] -= j * (j+1) * cos((j+1) * x[i] + j); - } - } - RETURN(f); + unsigned i, j; + double f = 0; + UNUSED(data); + for (j = 1; j <= 5; ++j) + for (i = 0; i < n; ++i) + f -= j * sin((j + 1) * x[i] + j); + if (grad) { + for (i = 0; i < n; ++i) { + grad[i] = 0; + for (j = 1; j <= 5; ++j) + grad[i] -= j * (j + 1) * cos((j + 1) * x[i] + j); + } + } + RETURN(f); } -static const double shubert_lb[2] = {-10,-10}; -static const double shubert_ub[2] = {10,10}; -static const double shubert_xmin[2] = {-6.774576143, -6.774576143}; +static const double shubert_lb[2] = { -10, -10 }; +static const double shubert_ub[2] = { 10, 10 }; +static const double shubert_xmin[2] = { -6.774576143, -6.774576143 }; /****************************************************************************/ static double hansen_f(unsigned n, const double *x, double *grad, void *data) { - unsigned i; - double a = 0, b = 0; - UNUSED(data); - for (i = 1; i <= 5; ++i) - a += i * cos((i-1) * x[0] + i); - for (i = 1; i <= 5; ++i) - b += i * cos((i+1) * x[1] + i); - if (grad) { - grad[0] = 0; - for (i = 1; i <= 5; ++i) - grad[0] -= i * (i-1) * sin((i-1) * x[0] + i); - grad[0] *= b; - grad[1] = 0; - for (i = 1; i <= 5; ++i) - grad[1] -= i * (i+1) * sin((i+1) * x[1] + i); - grad[1] *= a; - } - RETURN(a*b); + unsigned i; + double a = 0, b = 0; + UNUSED(data); + for (i = 1; i <= 5; ++i) + a += i * cos((i - 1) * x[0] + i); + for (i = 1; i <= 5; ++i) + b += i * cos((i + 1) * x[1] + i); + if (grad) { + grad[0] = 0; + for (i = 1; i <= 5; ++i) + grad[0] -= i * (i - 1) * sin((i - 1) * x[0] + i); + grad[0] *= b; + grad[1] = 0; + for (i = 1; i <= 5; ++i) + grad[1] -= i * (i + 1) * sin((i + 1) * x[1] + i); + grad[1] *= a; + } + RETURN(a * b); } -static const double hansen_lb[2] = {-10,-10}; -static const double hansen_ub[2] = {10,10}; -static const double hansen_xmin[2] = {-1.306707704,-1.425128429}; +static const double hansen_lb[2] = { -10, -10 }; +static const double hansen_ub[2] = { 10, 10 }; +static const double hansen_xmin[2] = { -1.306707704, -1.425128429 }; /****************************************************************************/ static double osc1d_f(unsigned n, const double *x, double *grad, void *data) { - double y = *x - 1.23456789; - UNUSED(data); - if (grad) grad[0] = y*0.02 + sin(y - 2*sin(3*y)) * (1 - 6*cos(3*y)); - RETURN(sqr(y*0.1) - cos(y - 2*sin(3*y))); + double y = *x - 1.23456789; + UNUSED(data); + if (grad) + grad[0] = y * 0.02 + sin(y - 2 * sin(3 * y)) * (1 - 6 * cos(3 * y)); + RETURN(sqr(y * 0.1) - cos(y - 2 * sin(3 * y))); } -static const double osc1d_lb[1] = {-5}; -static const double osc1d_ub[1] = {5}; -static const double osc1d_xmin[1] = {1.23456789}; +static const double osc1d_lb[1] = { -5 }; +static const double osc1d_ub[1] = { 5 }; +static const double osc1d_xmin[1] = { 1.23456789 }; /****************************************************************************/ static double corner4d_f(unsigned n, const double *x, double *grad, void *data) { - double u = x[0] + x[1] * x[2] * sin(2 * x[3]); - double v = x[0] + 2*sin(u); - UNUSED(data); - UNUSED(n); - if (grad) { - grad[0] = 2*v * (1 + 2*cos(u)); - grad[1] = 2*v * 2*cos(u) * x[2] * sin(2*x[3]) + 0.1; - grad[2] = 2*v * 2*cos(u) * x[1] * sin(2*x[3]) + 0.1; - grad[3] = 2*v * 2*cos(u) * x[1]*x[2] * cos(2*x[3]) * 2 + 0.1; - } - RETURN(1 + v*v + 0.1*(x[1]+x[2]+x[3])); + double u = x[0] + x[1] * x[2] * sin(2 * x[3]); + double v = x[0] + 2 * sin(u); + UNUSED(data); + UNUSED(n); + if (grad) { + grad[0] = 2 * v * (1 + 2 * cos(u)); + grad[1] = 2 * v * 2 * cos(u) * x[2] * sin(2 * x[3]) + 0.1; + grad[2] = 2 * v * 2 * cos(u) * x[1] * sin(2 * x[3]) + 0.1; + grad[3] = 2 * v * 2 * cos(u) * x[1] * x[2] * cos(2 * x[3]) * 2 + 0.1; + } + RETURN(1 + v * v + 0.1 * (x[1] + x[2] + x[3])); } -static const double corner4d_lb[4] = {0,0,0,0}; -static const double corner4d_ub[4] = {1,1,1,1}; -static const double corner4d_xmin[4] = {0,0,0,0}; +static const double corner4d_lb[4] = { 0, 0, 0, 0 }; +static const double corner4d_ub[4] = { 1, 1, 1, 1 }; +static const double corner4d_xmin[4] = { 0, 0, 0, 0 }; /****************************************************************************/ static double side4d_f(unsigned n, const double *x, double *grad, void *data) { - double x0, x1, x2, x3, d0,d1,d2,d3; - const double w0 = 0.1, w1 = 0.2, w2 = 0.3, w3 = 0.4; - UNUSED(data); - UNUSED(n); - x0 = +0.4977 * x[0] - 0.3153 * x[1] - 0.5066 * x[2] - 0.4391 * x[3]; - x1 = -0.3153 * x[0] + 0.3248 * x[1] - 0.4382 * x[2] - 0.4096 * x[3]; - x2 = -0.5066 * x[0] - 0.4382 * x[1] + 0.3807 * x[2] - 0.4543 * x[3]; - x3 = -0.4391 * x[0] - 0.4096 * x[1] - 0.4543 * x[2] + 0.5667 * x[3]; - - d0 = -1. / (x0*x0 + w0*w0); - d1 = -1. / (x1*x1 + w1*w1); - d2 = -1. / (x2*x2 + w2*w2); - d3 = -1. / (x3*x3 + w3*w3); - - if (grad) { - grad[0] = 2 * (x0*d0*d0 * +0.4977 + - x1*d1*d1 * -0.3153 + - x2*d2*d2 * -0.5066 + - x3*d3*d3 * -0.4391); - grad[1] = 2 * (x0*d0*d0 * -0.3153 + - x1*d1*d1 * +0.3248 + - x2*d2*d2 * -0.4382 + - x3*d3*d3 * -0.4096); - grad[2] = 2 * (x0*d0*d0 * -0.5066 + - x1*d1*d1 * -0.4382 + - x2*d2*d2 * +0.3807 + - x3*d3*d3 * -0.4543); - grad[3] = 2 * (x0*d0*d0 * -0.4391 + - x1*d1*d1 * -0.4096 + - x2*d2*d2 * -0.4543 + - x3*d3*d3 * +0.5667); - } - RETURN(d0 + d1 + d2 + d3); + double x0, x1, x2, x3, d0, d1, d2, d3; + const double w0 = 0.1, w1 = 0.2, w2 = 0.3, w3 = 0.4; + UNUSED(data); + UNUSED(n); + x0 = +0.4977 * x[0] - 0.3153 * x[1] - 0.5066 * x[2] - 0.4391 * x[3]; + x1 = -0.3153 * x[0] + 0.3248 * x[1] - 0.4382 * x[2] - 0.4096 * x[3]; + x2 = -0.5066 * x[0] - 0.4382 * x[1] + 0.3807 * x[2] - 0.4543 * x[3]; + x3 = -0.4391 * x[0] - 0.4096 * x[1] - 0.4543 * x[2] + 0.5667 * x[3]; + + d0 = -1. / (x0 * x0 + w0 * w0); + d1 = -1. / (x1 * x1 + w1 * w1); + d2 = -1. / (x2 * x2 + w2 * w2); + d3 = -1. / (x3 * x3 + w3 * w3); + + if (grad) { + grad[0] = 2 * (x0 * d0 * d0 * +0.4977 + x1 * d1 * d1 * -0.3153 + x2 * d2 * d2 * -0.5066 + x3 * d3 * d3 * -0.4391); + grad[1] = 2 * (x0 * d0 * d0 * -0.3153 + x1 * d1 * d1 * +0.3248 + x2 * d2 * d2 * -0.4382 + x3 * d3 * d3 * -0.4096); + grad[2] = 2 * (x0 * d0 * d0 * -0.5066 + x1 * d1 * d1 * -0.4382 + x2 * d2 * d2 * +0.3807 + x3 * d3 * d3 * -0.4543); + grad[3] = 2 * (x0 * d0 * d0 * -0.4391 + x1 * d1 * d1 * -0.4096 + x2 * d2 * d2 * -0.4543 + x3 * d3 * d3 * +0.5667); + } + RETURN(d0 + d1 + d2 + d3); } -static const double side4d_lb[4] = {0.1,-1,-1,-1}; -static const double side4d_ub[4] = {1,1,1,1}; -static const double side4d_xmin[4] = {0.1,0.102971169,0.0760520641,-0.0497098571}; +static const double side4d_lb[4] = { 0.1, -1, -1, -1 }; +static const double side4d_ub[4] = { 1, 1, 1, 1 }; +static const double side4d_xmin[4] = { 0.1, 0.102971169, 0.0760520641, -0.0497098571 }; /****************************************************************************/ /****************************************************************************/ const testfunc testfuncs[NTESTFUNCS] = { - { rosenbrock_f, NULL, 1, 2, - rosenbrock_lb, rosenbrock_ub, rosenbrock_xmin, - 0.0, "Rosenbrock function" }, - { mccormic_f, NULL, 1, 2, - mccormic_lb, mccormic_ub, mccormic_xmin, - -1.91322295, "McCormic function" }, - { boxbetts_f, NULL, 1, 3, - boxbetts_lb, boxbetts_ub, boxbetts_xmin, - 0.0, "Box and Betts exponential quadratic sum" }, - { paviani_f, NULL, 1, 10, - paviani_lb, paviani_ub, paviani_xmin, - -45.7784697, "Paviani function" }, - { grosenbrock_f, NULL, 1, 30, - grosenbrock_lb, grosenbrock_ub, grosenbrock_xmin, - 0.0, "Generalized Rosenbrock function" }, - { goldsteinprice_f, NULL, 1, 2, - goldsteinprice_lb, goldsteinprice_ub, goldsteinprice_xmin, - 3.0, "Goldstein and Price function" }, - { shekel_f, shekel_m + 0, 1, 4, - shekel_lb, shekel_ub, shekel0_xmin, - -10.15319968, "Shekel m=5 function" }, - { shekel_f, shekel_m + 1, 1, 4, - shekel_lb, shekel_ub, shekel1_xmin, - -10.40294057, "Shekel m=7 function" }, - { shekel_f, shekel_m + 2, 1, 4, - shekel_lb, shekel_ub, shekel2_xmin, - -10.53640982, "Shekel m=10 function" }, - { levy_f, NULL, 1, 4, - levy4_lb, levy4_ub, levy4_xmin, - -21.50235596, "Levy n=4 function" }, - { levy_f, NULL, 1, 5, - levy_lb, levy_ub, levy_xmin+2, - -11.50440302, "Levy n=5 function" }, - { levy_f, NULL, 1, 6, - levy_lb, levy_ub, levy_xmin+1, - -11.50440302, "Levy n=6 function" }, - { levy_f, NULL, 1, 7, - levy_lb, levy_ub, levy_xmin, - -11.50440302, "Levy n=7 function" }, - { griewank_f, NULL, 1, 10, - griewank_lb, griewank_ub, griewank_xmin, - 0.0, "Griewank function" }, - { sixhumpcamel_f, NULL, 1, 2, - sixhumpcamel_lb, sixhumpcamel_ub, sixhumpcamel_xmin, - -1.031628453, "Six-hump camel back function" }, - { convexcosh_f, NULL, 1, 10, - convexcosh_lb, convexcosh_ub, convexcosh_xmin, - 1.0, "Convex product of cosh functions" }, - { branin_f, NULL, 1, 2, - branin_lb, branin_ub, branin_xmin, - -.0, "Branin function" }, - { shubert_f, NULL, 1, 2, - shubert_lb, shubert_ub, shubert_xmin, - -24.06249888, "Shubert function" }, - { hansen_f, NULL, 1, 2, - hansen_lb, hansen_ub, hansen_xmin, - -176.5417931367, "Hansen function" }, - { osc1d_f, NULL, 1, 1, - osc1d_lb, osc1d_ub, osc1d_xmin, - -1.0, "1d oscillating function with a single minimum" }, - { corner4d_f, NULL, 1, 4, - corner4d_lb, corner4d_ub, corner4d_xmin, - 1.0, "4d function with minimum at corner" }, - { side4d_f, NULL, 1, 4, - side4d_lb, side4d_ub, side4d_xmin, - -141.285020472, "4d function with minimum at side" } + {rosenbrock_f, NULL, 1, 2, + rosenbrock_lb, rosenbrock_ub, rosenbrock_xmin, + 0.0, "Rosenbrock function"}, + {mccormic_f, NULL, 1, 2, + mccormic_lb, mccormic_ub, mccormic_xmin, + -1.91322295, "McCormic function"}, + {boxbetts_f, NULL, 1, 3, + boxbetts_lb, boxbetts_ub, boxbetts_xmin, + 0.0, "Box and Betts exponential quadratic sum"}, + {paviani_f, NULL, 1, 10, + paviani_lb, paviani_ub, paviani_xmin, + -45.7784697, "Paviani function"}, + {grosenbrock_f, NULL, 1, 30, + grosenbrock_lb, grosenbrock_ub, grosenbrock_xmin, + 0.0, "Generalized Rosenbrock function"}, + {goldsteinprice_f, NULL, 1, 2, + goldsteinprice_lb, goldsteinprice_ub, goldsteinprice_xmin, + 3.0, "Goldstein and Price function"}, + {shekel_f, shekel_m + 0, 1, 4, + shekel_lb, shekel_ub, shekel0_xmin, + -10.15319968, "Shekel m=5 function"}, + {shekel_f, shekel_m + 1, 1, 4, + shekel_lb, shekel_ub, shekel1_xmin, + -10.40294057, "Shekel m=7 function"}, + {shekel_f, shekel_m + 2, 1, 4, + shekel_lb, shekel_ub, shekel2_xmin, + -10.53640982, "Shekel m=10 function"}, + {levy_f, NULL, 1, 4, + levy4_lb, levy4_ub, levy4_xmin, + -21.50235596, "Levy n=4 function"}, + {levy_f, NULL, 1, 5, + levy_lb, levy_ub, levy_xmin + 2, + -11.50440302, "Levy n=5 function"}, + {levy_f, NULL, 1, 6, + levy_lb, levy_ub, levy_xmin + 1, + -11.50440302, "Levy n=6 function"}, + {levy_f, NULL, 1, 7, + levy_lb, levy_ub, levy_xmin, + -11.50440302, "Levy n=7 function"}, + {griewank_f, NULL, 1, 10, + griewank_lb, griewank_ub, griewank_xmin, + 0.0, "Griewank function"}, + {sixhumpcamel_f, NULL, 1, 2, + sixhumpcamel_lb, sixhumpcamel_ub, sixhumpcamel_xmin, + -1.031628453, "Six-hump camel back function"}, + {convexcosh_f, NULL, 1, 10, + convexcosh_lb, convexcosh_ub, convexcosh_xmin, + 1.0, "Convex product of cosh functions"}, + {branin_f, NULL, 1, 2, + branin_lb, branin_ub, branin_xmin, + -.0, "Branin function"}, + {shubert_f, NULL, 1, 2, + shubert_lb, shubert_ub, shubert_xmin, + -24.06249888, "Shubert function"}, + {hansen_f, NULL, 1, 2, + hansen_lb, hansen_ub, hansen_xmin, + -176.5417931367, "Hansen function"}, + {osc1d_f, NULL, 1, 1, + osc1d_lb, osc1d_ub, osc1d_xmin, + -1.0, "1d oscillating function with a single minimum"}, + {corner4d_f, NULL, 1, 4, + corner4d_lb, corner4d_ub, corner4d_xmin, + 1.0, "4d function with minimum at corner"}, + {side4d_f, NULL, 1, 4, + side4d_lb, side4d_ub, side4d_xmin, + -141.285020472, "4d function with minimum at side"} }; diff --git a/test/testfuncs.h b/test/testfuncs.h index 328d2e3..67042b8 100644 --- a/test/testfuncs.h +++ b/test/testfuncs.h @@ -2,30 +2,28 @@ #define TESTFUNCS_H #ifdef __cplusplus -extern "C" -{ -#endif /* __cplusplus */ +extern "C" { +#endif /* __cplusplus */ #include "nlopt.h" -typedef struct { - nlopt_func f; - void *f_data; - int has_gradient; - int n; - const double *lb, *ub, *xmin; - double minf; - const char *name; -} testfunc; + typedef struct { + nlopt_func f; + void *f_data; + int has_gradient; + int n; + const double *lb, *ub, *xmin; + double minf; + const char *name; + } testfunc; #define NTESTFUNCS 22 -extern const testfunc testfuncs[NTESTFUNCS]; + extern const testfunc testfuncs[NTESTFUNCS]; -extern int testfuncs_verbose; -extern int testfuncs_counter; + extern int testfuncs_verbose; + extern int testfuncs_counter; #ifdef __cplusplus -} /* extern "C" */ -#endif /* __cplusplus */ - +} /* extern "C" */ +#endif /* __cplusplus */ #endif diff --git a/test/testopt.c b/test/testopt.c index 07f9037..9384214 100644 --- a/test/testopt.c +++ b/test/testopt.c @@ -39,7 +39,7 @@ #define USE_FEENABLEEXCEPT 0 #if USE_FEENABLEEXCEPT # include -extern "C" int feenableexcept (int EXCEPTS); +extern "C" int feenableexcept(int EXCEPTS); #endif @@ -53,348 +53,352 @@ static int maxeval = 1000, iterations = 1, center_start = 0; static double maxtime = 0.0; static double xinit_tol = -1; static int force_constraints = 0; -static int fix_bounds[100] = {0,0,0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0,0,0}; +static int fix_bounds[100] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; -static void listalgs(FILE *f) +static void listalgs(FILE * f) { - int i; - fprintf(f, "Available algorithms:\n"); - for (i = 0; i < NLOPT_NUM_ALGORITHMS; ++i) - fprintf(f, " %2d: %s\n", i, nlopt_algorithm_name((nlopt_algorithm) i)); + int i; + fprintf(f, "Available algorithms:\n"); + for (i = 0; i < NLOPT_NUM_ALGORITHMS; ++i) + fprintf(f, " %2d: %s\n", i, nlopt_algorithm_name((nlopt_algorithm) i)); } -static void listfuncs(FILE *f) +static void listfuncs(FILE * f) { - int i; - fprintf(f, "Available objective functions:\n"); - for (i = 0; i < NTESTFUNCS; ++i) - fprintf(f, " %2d: %s (%d dims)\n", i, testfuncs[i].name, testfuncs[i].n); + int i; + fprintf(f, "Available objective functions:\n"); + for (i = 0; i < NTESTFUNCS; ++i) + fprintf(f, " %2d: %s (%d dims)\n", i, testfuncs[i].name, testfuncs[i].n); } typedef struct { - const double *lb, *ub; - nlopt_func f; - void *f_data; + const double *lb, *ub; + nlopt_func f; + void *f_data; } bounds_wrap_data; static double bounds_wrap_func(unsigned n, const double *x, double *grad, void *d_) { - bounds_wrap_data *d = (bounds_wrap_data *) d_; - unsigned i; - double b = 0; - for (i = 0; i < n; ++i) { - if (x[i] < d->lb[i]) { - b = d->lb[i]; - break; + bounds_wrap_data *d = (bounds_wrap_data *) d_; + unsigned i; + double b = 0; + for (i = 0; i < n; ++i) { + if (x[i] < d->lb[i]) { + b = d->lb[i]; + break; + } else if (x[i] > d->ub[i]) { + b = d->ub[i]; + break; + } } - else if (x[i] > d->ub[i]) { - b = d->ub[i]; - break; - } - } - if (i < n) - fprintf(stderr, "WARNING: bounds violated by x[%u] = %g = %g + %g\n", - i, x[i], b, x[i] - b); - return d->f(n, x, grad, d->f_data); + if (i < n) + fprintf(stderr, "WARNING: bounds violated by x[%u] = %g = %g + %g\n", i, x[i], b, x[i] - b); + return d->f(n, x, grad, d->f_data); } static int test_function(int ifunc) { - nlopt_opt opt; - testfunc func; - int i, iter; - double *x, minf, minf_max, f0, *xtabs, *lb, *ub; - nlopt_result ret; - double start = nlopt_seconds(); - int total_count = 0, max_count = 0, min_count = 1<<30; - double total_err = 0, max_err = 0; - bounds_wrap_data bw; - - if (ifunc < 0 || ifunc >= NTESTFUNCS) { - fprintf(stderr, "testopt: invalid function %d\n", ifunc); - listfuncs(stderr); - return 0; - } - func = testfuncs[ifunc]; - x = (double *) malloc(sizeof(double) * func.n * 5); - if (!x) { fprintf(stderr, "testopt: Out of memory!\n"); return 0; } - - lb = x + func.n * 3; - ub = lb + func.n; - xtabs = x + func.n * 2; - bw.lb = lb; - bw.ub = ub; - bw.f = func.f; - bw.f_data = func.f_data; + nlopt_opt opt; + testfunc func; + int i, iter; + double *x, minf, minf_max, f0, *xtabs, *lb, *ub; + nlopt_result ret; + double start = nlopt_seconds(); + int total_count = 0, max_count = 0, min_count = 1 << 30; + double total_err = 0, max_err = 0; + bounds_wrap_data bw; - for (i = 0; i < func.n; ++i) xtabs[i] = xtol_abs; - minf_max = minf_max_delta > (-HUGE_VAL) ? minf_max_delta + func.minf : (-HUGE_VAL); - - printf("-----------------------------------------------------------\n"); - printf("Optimizing %s (%d dims) using %s algorithm\n", - func.name, func.n, nlopt_algorithm_name(algorithm)); - printf("lower bounds at lb = ["); - for (i = 0; i < func.n; ++i) printf(" %g", func.lb[i]); - printf("]\n"); - printf("upper bounds at ub = ["); - for (i = 0; i < func.n; ++i) printf(" %g", func.ub[i]); - printf("]\n"); - memcpy(lb, func.lb, func.n * sizeof(double)); - memcpy(ub, func.ub, func.n * sizeof(double)); - for (i = 0; i < func.n; ++i) if (fix_bounds[i]) { - printf("fixing bounds for dim[%d] to xmin[%d]=%g\n", - i, i, func.xmin[i]); - lb[i] = ub[i] = func.xmin[i]; - } - if (force_constraints) { - for (i = 0; i < func.n; ++i) { - if (nlopt_iurand(2) == 0) - ub[i] = nlopt_urand(lb[i], func.xmin[i]); - else - lb[i] = nlopt_urand(func.xmin[i], ub[i]); + if (ifunc < 0 || ifunc >= NTESTFUNCS) { + fprintf(stderr, "testopt: invalid function %d\n", ifunc); + listfuncs(stderr); + return 0; + } + func = testfuncs[ifunc]; + x = (double *) malloc(sizeof(double) * func.n * 5); + if (!x) { + fprintf(stderr, "testopt: Out of memory!\n"); + return 0; } - printf("adjusted lower bounds at lb = ["); - for (i = 0; i < func.n; ++i) printf(" %g", lb[i]); - printf("]\n"); - printf("adjusted upper bounds at ub = ["); - for (i = 0; i < func.n; ++i) printf(" %g", ub[i]); - printf("]\n"); - } - if (fabs(func.f(func.n, func.xmin, 0, func.f_data) - func.minf) > 1e-8) { - fprintf(stderr, "BUG: function does not achieve given lower bound!\n"); - fprintf(stderr, "f(%g", func.xmin[0]); - for (i = 1; i < func.n; ++i) fprintf(stderr, ", %g", func.xmin[i]); - fprintf(stderr, ") = %0.16g instead of %0.16g, |diff| = %g\n", - func.f(func.n, func.xmin, 0, func.f_data), func.minf, - fabs(func.f(func.n, func.xmin, 0, func.f_data) - func.minf)); - free(x); - return 0; - } + lb = x + func.n * 3; + ub = lb + func.n; + xtabs = x + func.n * 2; + bw.lb = lb; + bw.ub = ub; + bw.f = func.f; + bw.f_data = func.f_data; - for (iter = 0; iter < iterations; ++iter) { - double val; - testfuncs_counter = 0; + for (i = 0; i < func.n; ++i) + xtabs[i] = xtol_abs; + minf_max = minf_max_delta > (-HUGE_VAL) ? minf_max_delta + func.minf : (-HUGE_VAL); - printf("Starting guess x = ["); - for (i = 0; i < func.n; ++i) { - if (center_start) - x[i] = (ub[i] + lb[i]) * 0.5; - else if (xinit_tol < 0) { /* random starting point near center of box */ - double dx = (ub[i] - lb[i]) * 0.25; - double xm = 0.5 * (ub[i] + lb[i]); - x[i] = nlopt_urand(xm - dx, xm + dx); - } - else { - x[i] = nlopt_urand(-xinit_tol, xinit_tol) - + (1 + nlopt_urand(-xinit_tol, xinit_tol)) * func.xmin[i]; - if (x[i] > ub[i]) x[i] = ub[i]; - else if (x[i] < lb[i]) x[i] = lb[i]; - } - printf(" %g", x[i]); - } + printf("-----------------------------------------------------------\n"); + printf("Optimizing %s (%d dims) using %s algorithm\n", func.name, func.n, nlopt_algorithm_name(algorithm)); + printf("lower bounds at lb = ["); + for (i = 0; i < func.n; ++i) + printf(" %g", func.lb[i]); + printf("]\n"); + printf("upper bounds at ub = ["); + for (i = 0; i < func.n; ++i) + printf(" %g", func.ub[i]); printf("]\n"); - f0 = func.f(func.n, x, x + func.n, func.f_data); - printf("Starting function value = %g\n", f0); - - if (iter == 0 && testfuncs_verbose && func.has_gradient) { - printf("checking gradient:\n"); - for (i = 0; i < func.n; ++i) { - double f; - x[i] *= 1 + 1e-6; - f = func.f(func.n, x, NULL, func.f_data); - x[i] /= 1 + 1e-6; - printf(" grad[%d] = %g vs. numerical derivative %g\n", - i, x[i + func.n], (f - f0) / (x[i] * 1e-6)); - } + memcpy(lb, func.lb, func.n * sizeof(double)); + memcpy(ub, func.ub, func.n * sizeof(double)); + for (i = 0; i < func.n; ++i) + if (fix_bounds[i]) { + printf("fixing bounds for dim[%d] to xmin[%d]=%g\n", i, i, func.xmin[i]); + lb[i] = ub[i] = func.xmin[i]; + } + if (force_constraints) { + for (i = 0; i < func.n; ++i) { + if (nlopt_iurand(2) == 0) + ub[i] = nlopt_urand(lb[i], func.xmin[i]); + else + lb[i] = nlopt_urand(func.xmin[i], ub[i]); + } + printf("adjusted lower bounds at lb = ["); + for (i = 0; i < func.n; ++i) + printf(" %g", lb[i]); + printf("]\n"); + printf("adjusted upper bounds at ub = ["); + for (i = 0; i < func.n; ++i) + printf(" %g", ub[i]); + printf("]\n"); } - - testfuncs_counter = 0; - opt = nlopt_create(algorithm, func.n); - nlopt_set_min_objective(opt, bounds_wrap_func, &bw); - nlopt_set_lower_bounds(opt, lb); - nlopt_set_upper_bounds(opt, ub); - nlopt_set_stopval(opt, minf_max); - nlopt_set_ftol_rel(opt, ftol_rel); - nlopt_set_ftol_abs(opt, ftol_abs); - nlopt_set_xtol_rel(opt, xtol_rel); - nlopt_set_xtol_abs(opt, xtabs); - nlopt_set_maxeval(opt, maxeval); - nlopt_set_maxtime(opt, maxtime); - ret = nlopt_optimize(opt, x, &minf); - printf("finished after %g seconds.\n", nlopt_seconds() - start); - printf("return code %d from nlopt_minimize\n", ret); - if (ret < 0 && ret != NLOPT_ROUNDOFF_LIMITED - && ret != NLOPT_FORCED_STOP) { - fprintf(stderr, "testopt: error in nlopt_minimize\n"); - free(x); - return 0; + + if (fabs(func.f(func.n, func.xmin, 0, func.f_data) - func.minf) > 1e-8) { + fprintf(stderr, "BUG: function does not achieve given lower bound!\n"); + fprintf(stderr, "f(%g", func.xmin[0]); + for (i = 1; i < func.n; ++i) + fprintf(stderr, ", %g", func.xmin[i]); + fprintf(stderr, ") = %0.16g instead of %0.16g, |diff| = %g\n", func.f(func.n, func.xmin, 0, func.f_data), func.minf, fabs(func.f(func.n, func.xmin, 0, func.f_data) - func.minf)); + free(x); + return 0; } - printf("Found minimum f = %g after %d evaluations (numevals = %d).\n", - minf, testfuncs_counter, nlopt_get_numevals(opt)); - nlopt_destroy(opt); - total_count += testfuncs_counter; - if (testfuncs_counter > max_count) max_count = testfuncs_counter; - if (testfuncs_counter < min_count) min_count = testfuncs_counter; - printf("Minimum at x = ["); - for (i = 0; i < func.n; ++i) printf(" %g", x[i]); - printf("]\n"); - if (func.minf == 0) - printf("|f - minf| = %g\n", fabs(minf - func.minf)); - else - printf("|f - minf| = %g, |f - minf| / |minf| = %e\n", - fabs(minf - func.minf), fabs(minf - func.minf) / fabs(func.minf)); - total_err += fabs(minf - func.minf); - if (fabs(minf - func.minf) > max_err) - max_err = fabs(minf - func.minf); - printf("vs. global minimum f = %g at x = [", func.minf); - for (i = 0; i < func.n; ++i) printf(" %g", func.xmin[i]); - printf("]\n"); - val = func.f(func.n, x, NULL, func.f_data); - if (fabs(val - minf) > 1e-12) { - fprintf(stderr, "Mismatch %g between returned minf=%g and f(x) = %g\n", - minf - val, minf, val); - free(x); - return 0; + for (iter = 0; iter < iterations; ++iter) { + double val; + testfuncs_counter = 0; + + printf("Starting guess x = ["); + for (i = 0; i < func.n; ++i) { + if (center_start) + x[i] = (ub[i] + lb[i]) * 0.5; + else if (xinit_tol < 0) { /* random starting point near center of box */ + double dx = (ub[i] - lb[i]) * 0.25; + double xm = 0.5 * (ub[i] + lb[i]); + x[i] = nlopt_urand(xm - dx, xm + dx); + } else { + x[i] = nlopt_urand(-xinit_tol, xinit_tol) + + (1 + nlopt_urand(-xinit_tol, xinit_tol)) * func.xmin[i]; + if (x[i] > ub[i]) + x[i] = ub[i]; + else if (x[i] < lb[i]) + x[i] = lb[i]; + } + printf(" %g", x[i]); + } + printf("]\n"); + f0 = func.f(func.n, x, x + func.n, func.f_data); + printf("Starting function value = %g\n", f0); + + if (iter == 0 && testfuncs_verbose && func.has_gradient) { + printf("checking gradient:\n"); + for (i = 0; i < func.n; ++i) { + double f; + x[i] *= 1 + 1e-6; + f = func.f(func.n, x, NULL, func.f_data); + x[i] /= 1 + 1e-6; + printf(" grad[%d] = %g vs. numerical derivative %g\n", i, x[i + func.n], (f - f0) / (x[i] * 1e-6)); + } + } + + testfuncs_counter = 0; + opt = nlopt_create(algorithm, func.n); + nlopt_set_min_objective(opt, bounds_wrap_func, &bw); + nlopt_set_lower_bounds(opt, lb); + nlopt_set_upper_bounds(opt, ub); + nlopt_set_stopval(opt, minf_max); + nlopt_set_ftol_rel(opt, ftol_rel); + nlopt_set_ftol_abs(opt, ftol_abs); + nlopt_set_xtol_rel(opt, xtol_rel); + nlopt_set_xtol_abs(opt, xtabs); + nlopt_set_maxeval(opt, maxeval); + nlopt_set_maxtime(opt, maxtime); + ret = nlopt_optimize(opt, x, &minf); + printf("finished after %g seconds.\n", nlopt_seconds() - start); + printf("return code %d from nlopt_minimize\n", ret); + if (ret < 0 && ret != NLOPT_ROUNDOFF_LIMITED && ret != NLOPT_FORCED_STOP) { + fprintf(stderr, "testopt: error in nlopt_minimize\n"); + free(x); + return 0; + } + printf("Found minimum f = %g after %d evaluations (numevals = %d).\n", minf, testfuncs_counter, nlopt_get_numevals(opt)); + nlopt_destroy(opt); + total_count += testfuncs_counter; + if (testfuncs_counter > max_count) + max_count = testfuncs_counter; + if (testfuncs_counter < min_count) + min_count = testfuncs_counter; + printf("Minimum at x = ["); + for (i = 0; i < func.n; ++i) + printf(" %g", x[i]); + printf("]\n"); + if (func.minf == 0) + printf("|f - minf| = %g\n", fabs(minf - func.minf)); + else + printf("|f - minf| = %g, |f - minf| / |minf| = %e\n", fabs(minf - func.minf), fabs(minf - func.minf) / fabs(func.minf)); + total_err += fabs(minf - func.minf); + if (fabs(minf - func.minf) > max_err) + max_err = fabs(minf - func.minf); + printf("vs. global minimum f = %g at x = [", func.minf); + for (i = 0; i < func.n; ++i) + printf(" %g", func.xmin[i]); + printf("]\n"); + + val = func.f(func.n, x, NULL, func.f_data); + if (fabs(val - minf) > 1e-12) { + fprintf(stderr, "Mismatch %g between returned minf=%g and f(x) = %g\n", minf - val, minf, val); + free(x); + return 0; + } } - } - if (iterations > 1) - printf("average #evaluations = %g (%d-%d)\naverage |f-minf| = %g, max |f-minf| = %g\n", total_count * 1.0 / iterations, min_count, max_count, total_err / iterations, max_err); + if (iterations > 1) + printf("average #evaluations = %g (%d-%d)\naverage |f-minf| = %g, max |f-minf| = %g\n", total_count * 1.0 / iterations, min_count, max_count, total_err / iterations, max_err); - free(x); - return 1; + free(x); + return 1; } -static void usage(FILE *f) +static void usage(FILE * f) { - fprintf(f, "Usage: testopt [OPTIONS]\n" - "Options:\n" - " -h : print this help\n" - " -L : list available algorithms and objective functions\n" - " -v : verbose mode\n" - " -a : use optimization algorithm \n" - " -o : use objective function \n" - " -0 : starting guess within + (1+) * optimum\n" - " -b : eliminate given dims by equating bounds\n" - " -c : starting guess at center of cell\n" - " -C : put optimum outside of bound constraints\n" - " -e : use at most evals (default: %d, 0 to disable)\n" - " -t : use at most seconds (default: disabled)\n" - " -x : relative tolerance on x (default: disabled)\n" - " -X : absolute tolerance on x (default: disabled)\n" - " -f : relative tolerance on f (default: disabled)\n" - " -F : absolute tolerance on f (default: disabled)\n" - " -m : stop when minf+ is reached (default: disabled)\n" - " -i : iterate optimization times (default: 1)\n" - " -r : use random seed for starting guesses\n" - , maxeval); + fprintf(f, "Usage: testopt [OPTIONS]\n" + "Options:\n" + " -h : print this help\n" + " -L : list available algorithms and objective functions\n" + " -v : verbose mode\n" + " -a : use optimization algorithm \n" + " -o : use objective function \n" + " -0 : starting guess within + (1+) * optimum\n" + " -b : eliminate given dims by equating bounds\n" + " -c : starting guess at center of cell\n" + " -C : put optimum outside of bound constraints\n" + " -e : use at most evals (default: %d, 0 to disable)\n" + " -t : use at most seconds (default: disabled)\n" + " -x : relative tolerance on x (default: disabled)\n" + " -X : absolute tolerance on x (default: disabled)\n" + " -f : relative tolerance on f (default: disabled)\n" + " -F : absolute tolerance on f (default: disabled)\n" + " -m : stop when minf+ is reached (default: disabled)\n" " -i : iterate optimization times (default: 1)\n" " -r : use random seed for starting guesses\n", maxeval); } int main(int argc, char **argv) { - int c; - - nlopt_srand_time(); - testfuncs_verbose = 0; - minf_max_delta = -HUGE_VAL; + int c; - if (argc <= 1) - usage(stdout); + nlopt_srand_time(); + testfuncs_verbose = 0; + minf_max_delta = -HUGE_VAL; + + if (argc <= 1) + usage(stdout); #if USE_FEENABLEEXCEPT - feenableexcept(FE_INVALID); + feenableexcept(FE_INVALID); #endif - - while ((c = getopt(argc, argv, "hLvCc0:r:a:o:i:e:t:x:X:f:F:m:b:")) != -1) - switch (c) { - case 'h': - usage(stdout); - return EXIT_SUCCESS; - case 'L': - listalgs(stdout); - listfuncs(stdout); - return EXIT_SUCCESS; - case 'v': - testfuncs_verbose = 1; - break; - case 'C': - force_constraints = 1; - break; - case 'r': - nlopt_srand((unsigned long) atoi(optarg)); - break; - case 'a': - c = atoi(optarg); - if (c < 0 || c >= NLOPT_NUM_ALGORITHMS) { - fprintf(stderr, "testopt: invalid algorithm %d\n", c); - listalgs(stderr); - return EXIT_FAILURE; - } - algorithm = (nlopt_algorithm) c; - break; - case 'o': - if (!test_function(atoi(optarg))) - return EXIT_FAILURE; - break; - case 'e': - maxeval = atoi(optarg); - break; - case 'i': - iterations = atoi(optarg); - break; - case 't': - maxtime = atof(optarg); - break; - case 'x': - xtol_rel = atof(optarg); - break; - case 'X': - xtol_abs = atof(optarg); - break; - case 'f': - ftol_rel = atof(optarg); - break; - case 'F': - ftol_abs = atof(optarg); - break; - case 'm': - minf_max_delta = atof(optarg); - break; - case 'c': - center_start = 1; - break; - case '0': - center_start = 0; - xinit_tol = atof(optarg); - break; - case 'b': { - const char *s = optarg; - while (s && *s) { - int b = atoi(s); - if (b < 0 || b >= 100) { - fprintf(stderr, "invalid -b argument"); - return EXIT_FAILURE; - } - fix_bounds[b] = 1; - s = strchr(s, ','); if (s) ++s; - } - break; - } - default: - fprintf(stderr, "harminv: invalid argument -%c\n", c); - usage(stderr); - return EXIT_FAILURE; - } - - return EXIT_SUCCESS; + + while ((c = getopt(argc, argv, "hLvCc0:r:a:o:i:e:t:x:X:f:F:m:b:")) != -1) + switch (c) { + case 'h': + usage(stdout); + return EXIT_SUCCESS; + case 'L': + listalgs(stdout); + listfuncs(stdout); + return EXIT_SUCCESS; + case 'v': + testfuncs_verbose = 1; + break; + case 'C': + force_constraints = 1; + break; + case 'r': + nlopt_srand((unsigned long) atoi(optarg)); + break; + case 'a': + c = atoi(optarg); + if (c < 0 || c >= NLOPT_NUM_ALGORITHMS) { + fprintf(stderr, "testopt: invalid algorithm %d\n", c); + listalgs(stderr); + return EXIT_FAILURE; + } + algorithm = (nlopt_algorithm) c; + break; + case 'o': + if (!test_function(atoi(optarg))) + return EXIT_FAILURE; + break; + case 'e': + maxeval = atoi(optarg); + break; + case 'i': + iterations = atoi(optarg); + break; + case 't': + maxtime = atof(optarg); + break; + case 'x': + xtol_rel = atof(optarg); + break; + case 'X': + xtol_abs = atof(optarg); + break; + case 'f': + ftol_rel = atof(optarg); + break; + case 'F': + ftol_abs = atof(optarg); + break; + case 'm': + minf_max_delta = atof(optarg); + break; + case 'c': + center_start = 1; + break; + case '0': + center_start = 0; + xinit_tol = atof(optarg); + break; + case 'b':{ + const char *s = optarg; + while (s && *s) { + int b = atoi(s); + if (b < 0 || b >= 100) { + fprintf(stderr, "invalid -b argument"); + return EXIT_FAILURE; + } + fix_bounds[b] = 1; + s = strchr(s, ','); + if (s) + ++s; + } + break; + } + default: + fprintf(stderr, "harminv: invalid argument -%c\n", c); + usage(stderr); + return EXIT_FAILURE; + } + + return EXIT_SUCCESS; } -- 2.30.2