/* interface calling into the fortran routine */ static int lbfgs(index_t *x0, at *f, at *g, double gtol, htable_t *p, at *vargs) { /* argument checking and setup */ extern void lbfgs_(int *n, int *m, double *x, double *fval, double *gval, \ int *diagco, double *diag, int iprint[2], double *gtol, \ double *xtol, double *w, int *iflag); ifn (IND_STTYPE(x0) == ST_DOUBLE) error(NIL, "not an array of doubles", x0->backptr); ifn (Class(f)->listeval) error(NIL, "not a function", f); ifn (Class(f)->listeval) error(NIL, "not a function", g); ifn (gtol > 0) error(NIL, "threshold value not positive", NEW_NUMBER(gtol)); at *gx = copy_array(x0)->backptr; at *(*listeval_f)(at *, at *) = Class(f)->listeval; at *(*listeval_g)(at *, at *) = Class(g)->listeval; at *callf = new_cons(f, new_cons(x0->backptr, vargs)); at *callg = new_cons(g, new_cons(gx, new_cons(x0->backptr, vargs))); htable_t *params = lbfgs_params(); if (p) htable_update(params, p); int iprint[2]; iprint[0] = (int)Number(htable_get(params, NEW_SYMBOL("iprint-1"))); iprint[1] = (int)Number(htable_get(params, NEW_SYMBOL("iprint-2"))); lb3_.gtol = Number(htable_get(params, NEW_SYMBOL("ls-gtol"))); lb3_.stpmin = Number(htable_get(params, NEW_SYMBOL("ls-stpmin"))); lb3_.stpmax = Number(htable_get(params, NEW_SYMBOL("ls-stpmax"))); int m = (int)Number(htable_get(params, NEW_SYMBOL("lbfgs-m"))); int n = index_nelems(x0); double *x = IND_ST(x0)->data; double fval; double *gval = IND_ST(Mptr(gx))->data; int diagco = false; double *diag = mm_blob(n*sizeof(double)); double *w = mm_blob((n*(m+m+1)+m+m)*sizeof(double)); double xtol = eps(1); /* machine precision */ int iflag = 0; ifn (n>0) error(NIL, "empty array", x0->backptr); ifn (m>0) error(NIL, "m-parameter must be positive", NEW_NUMBER(m)); /* reverse communication loop */ do { fval = Number(listeval_f(Car(callf), callf)); listeval_g(Car(callg), callg); lbfgs_(&n, &m, x, &fval, gval, &diagco, diag, iprint, >ol, &xtol, w, &iflag); assert(iflag<2); } while (iflag > 0); return iflag; }
void storage_realloc(storage_t *st, size_t size, at *init) { if (size < st->size) RAISEF("storage size cannot be reduced", st->backptr); size_t s = size*storage_sizeof[st->type]; size_t olds = st->size*storage_sizeof[st->type]; gptr olddata = st->data; if (st->kind == STS_NULL) { /* empty storage */ assert(st->data == NULL); storage_alloc(st, size, init); return; } else { /* reallocate memory and update srg */ if (st->kind == STS_MANAGED) MM_ANCHOR(olddata); if (st->type==ST_AT || st->type==ST_MPTR) st->data = mm_allocv(mt_refs, s); else st->data = mm_blob(s); if (st->data) { memcpy(st->data, olddata, olds); st->kind = STS_MANAGED; } } if (st->data == NULL) { st->data = olddata; RAISEF("not enough memory", NIL); } size_t oldsize = st->size; st->size = size; if (init) { /* temporarily clear read only flag to allow initialization */ bool isreadonly = st->isreadonly; storage_clear(st, init, oldsize); st->isreadonly = isreadonly; } }