chiark / gitweb /
01616211793799016df95ca45bf26ec0cd335e7b
[nlopt.git] / bobyqa / bobyqa.c
1 /* BOBYQA derivative-free optimization code by M. J. D. Powell.
2    Original Fortran code by Powell (2009).  Converted via v2c,
3    cleaned up, and incorporated into NLopt by S. G. Johnson (2009).
4    See README. */
5
6 #include <math.h>
7 #include <stdlib.h>
8 #include <string.h>
9
10 #include "bobyqa.h"
11
12 #define min(a,b) ((a) <= (b) ? (a) : (b))
13 #define max(a,b) ((a) >= (b) ? (a) : (b))
14 #define iabs(x) ((x) < 0 ? -(x) : (x))
15
16 static void update_(int *n, int *npt, double *bmat, 
17         double *zmat, int *ndim, double *vlag, double *beta, 
18         double *denom, int *knew, double *w)
19 {
20     /* System generated locals */
21     int bmat_dim1, bmat_offset, zmat_dim1, zmat_offset, i__1, i__2;
22     double d__1, d__2, d__3;
23
24     /* Local variables */
25     int i__, j, k, jl, jp;
26     double one, tau, temp;
27     int nptm;
28     double zero, alpha, tempa, tempb, ztest;
29
30
31 /*     The arrays BMAT and ZMAT are updated, as required by the new position */
32 /*     of the interpolation point that has the index KNEW. The vector VLAG has */
33 /*     N+NPT components, set on entry to the first NPT and last N components */
34 /*     of the product Hw in equation (4.11) of the Powell (2006) paper on */
35 /*     NEWUOA. Further, BETA is set on entry to the value of the parameter */
36 /*     with that name, and DENOM is set to the denominator of the updating */
37 /*     formula. Elements of ZMAT may be treated as zero if their moduli are */
38 /*     at most ZTEST. The first NDIM elements of W are used for working space. */
39
40 /*     Set some constants. */
41
42     /* Parameter adjustments */
43     zmat_dim1 = *npt;
44     zmat_offset = 1 + zmat_dim1;
45     zmat -= zmat_offset;
46     bmat_dim1 = *ndim;
47     bmat_offset = 1 + bmat_dim1;
48     bmat -= bmat_offset;
49     --vlag;
50     --w;
51
52     /* Function Body */
53     one = 1.;
54     zero = 0.;
55     nptm = *npt - *n - 1;
56     ztest = zero;
57     i__1 = *npt;
58     for (k = 1; k <= i__1; ++k) {
59         i__2 = nptm;
60         for (j = 1; j <= i__2; ++j) {
61 /* L10: */
62 /* Computing MAX */
63             d__2 = ztest, d__3 = (d__1 = zmat[k + j * zmat_dim1], fabs(d__1));
64             ztest = max(d__2,d__3);
65         }
66     }
67     ztest *= 1e-20;
68
69 /*     Apply the rotations that put zeros in the KNEW-th row of ZMAT. */
70
71     jl = 1;
72     i__2 = nptm;
73     for (j = 2; j <= i__2; ++j) {
74         if ((d__1 = zmat[*knew + j * zmat_dim1], fabs(d__1)) > ztest) {
75 /* Computing 2nd power */
76             d__1 = zmat[*knew + zmat_dim1];
77 /* Computing 2nd power */
78             d__2 = zmat[*knew + j * zmat_dim1];
79             temp = sqrt(d__1 * d__1 + d__2 * d__2);
80             tempa = zmat[*knew + zmat_dim1] / temp;
81             tempb = zmat[*knew + j * zmat_dim1] / temp;
82             i__1 = *npt;
83             for (i__ = 1; i__ <= i__1; ++i__) {
84                 temp = tempa * zmat[i__ + zmat_dim1] + tempb * zmat[i__ + j * 
85                         zmat_dim1];
86                 zmat[i__ + j * zmat_dim1] = tempa * zmat[i__ + j * zmat_dim1] 
87                         - tempb * zmat[i__ + zmat_dim1];
88 /* L20: */
89                 zmat[i__ + zmat_dim1] = temp;
90             }
91         }
92         zmat[*knew + j * zmat_dim1] = zero;
93 /* L30: */
94     }
95
96 /*     Put the first NPT components of the KNEW-th column of HLAG into W, */
97 /*     and calculate the parameters of the updating formula. */
98
99     i__2 = *npt;
100     for (i__ = 1; i__ <= i__2; ++i__) {
101         w[i__] = zmat[*knew + zmat_dim1] * zmat[i__ + zmat_dim1];
102 /* L40: */
103     }
104     alpha = w[*knew];
105     tau = vlag[*knew];
106     vlag[*knew] -= one;
107
108 /*     Complete the updating of ZMAT. */
109
110     temp = sqrt(*denom);
111     tempb = zmat[*knew + zmat_dim1] / temp;
112     tempa = tau / temp;
113     i__2 = *npt;
114     for (i__ = 1; i__ <= i__2; ++i__) {
115 /* L50: */
116         zmat[i__ + zmat_dim1] = tempa * zmat[i__ + zmat_dim1] - tempb * vlag[
117                 i__];
118     }
119
120 /*     Finally, update the matrix BMAT. */
121
122     i__2 = *n;
123     for (j = 1; j <= i__2; ++j) {
124         jp = *npt + j;
125         w[jp] = bmat[*knew + j * bmat_dim1];
126         tempa = (alpha * vlag[jp] - tau * w[jp]) / *denom;
127         tempb = (-(*beta) * w[jp] - tau * vlag[jp]) / *denom;
128         i__1 = jp;
129         for (i__ = 1; i__ <= i__1; ++i__) {
130             bmat[i__ + j * bmat_dim1] = bmat[i__ + j * bmat_dim1] + tempa * 
131                     vlag[i__] + tempb * w[i__];
132             if (i__ > *npt) {
133                 bmat[jp + (i__ - *npt) * bmat_dim1] = bmat[i__ + j * 
134                         bmat_dim1];
135             }
136 /* L60: */
137         }
138     }
139 } /* update_ */
140
141 static nlopt_result rescue_(int *n, int *npt, const double *xl, const double *xu, 
142                     /* int *maxfun */
143                     nlopt_stopping *stop,
144                     bobyqa_func calfun, void *calfun_data,
145         double *xbase, double *xpt, double *fval, double *xopt, double *gopt,
146          double *hq, double *pq, double *bmat, double *zmat, 
147         int *ndim, double *sl, double *su, /* int *nf,  */
148         double *delta, int *kopt, double *vlag, double *
149         ptsaux, double *ptsid, double *w)
150 {
151     /* System generated locals */
152     int xpt_dim1, xpt_offset, bmat_dim1, bmat_offset, zmat_dim1, 
153             zmat_offset, i__1, i__2, i__3;
154     double d__1, d__2, d__3, d__4;
155
156     /* Local variables */
157     double f;
158     int i__, j, k, ih, jp, ip, iq, np, iw;
159     double xp, xq, den;
160     int ihp;
161     double one;
162     int ihq, jpn, kpt;
163     double sum, diff, half, beta;
164     int kold;
165     double winc;
166     int nrem, knew;
167     double temp, bsum;
168     int nptm;
169     double zero, hdiag, fbase, sfrac, denom, vquad, sumpq;
170     double dsqmin, distsq, vlmxsq;
171
172
173 /*     The arguments N, NPT, XL, XU, MAXFUN, XBASE, XPT, FVAL, XOPT, */
174 /*       GOPT, HQ, PQ, BMAT, ZMAT, NDIM, SL and SU have the same meanings as */
175 /*       the corresponding arguments of BOBYQB on the entry to RESCUE. */
176 /*     NF is maintained as the number of calls of CALFUN so far, except that */
177 /*       NF is set to -1 if the value of MAXFUN prevents further progress. */
178 /*     KOPT is maintained so that FVAL(KOPT) is the least calculated function */
179 /*       value. Its correct value must be given on entry. It is updated if a */
180 /*       new least function value is found, but the corresponding changes to */
181 /*       XOPT and GOPT have to be made later by the calling program. */
182 /*     DELTA is the current trust region radius. */
183 /*     VLAG is a working space vector that will be used for the values of the */
184 /*       provisional Lagrange functions at each of the interpolation points. */
185 /*       They are part of a product that requires VLAG to be of length NDIM. */
186 /*     PTSAUX is also a working space array. For J=1,2,...,N, PTSAUX(1,J) and */
187 /*       PTSAUX(2,J) specify the two positions of provisional interpolation */
188 /*       points when a nonzero step is taken along e_J (the J-th coordinate */
189 /*       direction) through XBASE+XOPT, as specified below. Usually these */
190 /*       steps have length DELTA, but other lengths are chosen if necessary */
191 /*       in order to satisfy the given bounds on the variables. */
192 /*     PTSID is also a working space array. It has NPT components that denote */
193 /*       provisional new positions of the original interpolation points, in */
194 /*       case changes are needed to restore the linear independence of the */
195 /*       interpolation conditions. The K-th point is a candidate for change */
196 /*       if and only if PTSID(K) is nonzero. In this case let p and q be the */
197 /*       int parts of PTSID(K) and (PTSID(K)-p) multiplied by N+1. If p */
198 /*       and q are both positive, the step from XBASE+XOPT to the new K-th */
199 /*       interpolation point is PTSAUX(1,p)*e_p + PTSAUX(1,q)*e_q. Otherwise */
200 /*       the step is PTSAUX(1,p)*e_p or PTSAUX(2,q)*e_q in the cases q=0 or */
201 /*       p=0, respectively. */
202 /*     The first NDIM+NPT elements of the array W are used for working space. */
203 /*     The final elements of BMAT and ZMAT are set in a well-conditioned way */
204 /*       to the values that are appropriate for the new interpolation points. */
205 /*     The elements of GOPT, HQ and PQ are also revised to the values that are */
206 /*       appropriate to the final quadratic model. */
207
208 /*     Set some constants. */
209
210     /* Parameter adjustments */
211     zmat_dim1 = *npt;
212     zmat_offset = 1 + zmat_dim1;
213     zmat -= zmat_offset;
214     xpt_dim1 = *npt;
215     xpt_offset = 1 + xpt_dim1;
216     xpt -= xpt_offset;
217     --xl;
218     --xu;
219     --xbase;
220     --fval;
221     --xopt;
222     --gopt;
223     --hq;
224     --pq;
225     bmat_dim1 = *ndim;
226     bmat_offset = 1 + bmat_dim1;
227     bmat -= bmat_offset;
228     --sl;
229     --su;
230     --vlag;
231     ptsaux -= 3;
232     --ptsid;
233     --w;
234
235     /* Function Body */
236     half = .5;
237     one = 1.;
238     zero = 0.;
239     np = *n + 1;
240     sfrac = half / (double) np;
241     nptm = *npt - np;
242
243 /*     Shift the interpolation points so that XOPT becomes the origin, and set */
244 /*     the elements of ZMAT to zero. The value of SUMPQ is required in the */
245 /*     updating of HQ below. The squares of the distances from XOPT to the */
246 /*     other interpolation points are set at the end of W. Increments of WINC */
247 /*     may be added later to these squares to balance the consideration of */
248 /*     the choice of point that is going to become current. */
249
250     sumpq = zero;
251     winc = zero;
252     i__1 = *npt;
253     for (k = 1; k <= i__1; ++k) {
254         distsq = zero;
255         i__2 = *n;
256         for (j = 1; j <= i__2; ++j) {
257             xpt[k + j * xpt_dim1] -= xopt[j];
258 /* L10: */
259 /* Computing 2nd power */
260             d__1 = xpt[k + j * xpt_dim1];
261             distsq += d__1 * d__1;
262         }
263         sumpq += pq[k];
264         w[*ndim + k] = distsq;
265         winc = max(winc,distsq);
266         i__2 = nptm;
267         for (j = 1; j <= i__2; ++j) {
268 /* L20: */
269             zmat[k + j * zmat_dim1] = zero;
270         }
271     }
272
273 /*     Update HQ so that HQ and PQ define the second derivatives of the model */
274 /*     after XBASE has been shifted to the trust region centre. */
275
276     ih = 0;
277     i__2 = *n;
278     for (j = 1; j <= i__2; ++j) {
279         w[j] = half * sumpq * xopt[j];
280         i__1 = *npt;
281         for (k = 1; k <= i__1; ++k) {
282 /* L30: */
283             w[j] += pq[k] * xpt[k + j * xpt_dim1];
284         }
285         i__1 = j;
286         for (i__ = 1; i__ <= i__1; ++i__) {
287             ++ih;
288 /* L40: */
289             hq[ih] = hq[ih] + w[i__] * xopt[j] + w[j] * xopt[i__];
290         }
291     }
292
293 /*     Shift XBASE, SL, SU and XOPT. Set the elements of BMAT to zero, and */
294 /*     also set the elements of PTSAUX. */
295
296     i__1 = *n;
297     for (j = 1; j <= i__1; ++j) {
298         xbase[j] += xopt[j];
299         sl[j] -= xopt[j];
300         su[j] -= xopt[j];
301         xopt[j] = zero;
302 /* Computing MIN */
303         d__1 = *delta, d__2 = su[j];
304         ptsaux[(j << 1) + 1] = min(d__1,d__2);
305 /* Computing MAX */
306         d__1 = -(*delta), d__2 = sl[j];
307         ptsaux[(j << 1) + 2] = max(d__1,d__2);
308         if (ptsaux[(j << 1) + 1] + ptsaux[(j << 1) + 2] < zero) {
309             temp = ptsaux[(j << 1) + 1];
310             ptsaux[(j << 1) + 1] = ptsaux[(j << 1) + 2];
311             ptsaux[(j << 1) + 2] = temp;
312         }
313         if ((d__2 = ptsaux[(j << 1) + 2], fabs(d__2)) < half * (d__1 = ptsaux[(
314                 j << 1) + 1], fabs(d__1))) {
315             ptsaux[(j << 1) + 2] = half * ptsaux[(j << 1) + 1];
316         }
317         i__2 = *ndim;
318         for (i__ = 1; i__ <= i__2; ++i__) {
319 /* L50: */
320             bmat[i__ + j * bmat_dim1] = zero;
321         }
322     }
323     fbase = fval[*kopt];
324
325 /*     Set the identifiers of the artificial interpolation points that are */
326 /*     along a coordinate direction from XOPT, and set the corresponding */
327 /*     nonzero elements of BMAT and ZMAT. */
328
329     ptsid[1] = sfrac;
330     i__2 = *n;
331     for (j = 1; j <= i__2; ++j) {
332         jp = j + 1;
333         jpn = jp + *n;
334         ptsid[jp] = (double) j + sfrac;
335         if (jpn <= *npt) {
336             ptsid[jpn] = (double) j / (double) np + sfrac;
337             temp = one / (ptsaux[(j << 1) + 1] - ptsaux[(j << 1) + 2]);
338             bmat[jp + j * bmat_dim1] = -temp + one / ptsaux[(j << 1) + 1];
339             bmat[jpn + j * bmat_dim1] = temp + one / ptsaux[(j << 1) + 2];
340             bmat[j * bmat_dim1 + 1] = -bmat[jp + j * bmat_dim1] - bmat[jpn + 
341                     j * bmat_dim1];
342             zmat[j * zmat_dim1 + 1] = sqrt(2.) / (d__1 = ptsaux[(j << 1) + 1] 
343                     * ptsaux[(j << 1) + 2], fabs(d__1));
344             zmat[jp + j * zmat_dim1] = zmat[j * zmat_dim1 + 1] * ptsaux[(j << 
345                     1) + 2] * temp;
346             zmat[jpn + j * zmat_dim1] = -zmat[j * zmat_dim1 + 1] * ptsaux[(j 
347                     << 1) + 1] * temp;
348         } else {
349             bmat[j * bmat_dim1 + 1] = -one / ptsaux[(j << 1) + 1];
350             bmat[jp + j * bmat_dim1] = one / ptsaux[(j << 1) + 1];
351 /* Computing 2nd power */
352             d__1 = ptsaux[(j << 1) + 1];
353             bmat[j + *npt + j * bmat_dim1] = -half * (d__1 * d__1);
354         }
355 /* L60: */
356     }
357
358 /*     Set any remaining identifiers with their nonzero elements of ZMAT. */
359
360     if (*npt >= *n + np) {
361         i__2 = *npt;
362         for (k = np << 1; k <= i__2; ++k) {
363             iw = (int) (((double) (k - np) - half) / (double) (*n)
364                     );
365             ip = k - np - iw * *n;
366             iq = ip + iw;
367             if (iq > *n) {
368                 iq -= *n;
369             }
370             ptsid[k] = (double) ip + (double) iq / (double) np + 
371                     sfrac;
372             temp = one / (ptsaux[(ip << 1) + 1] * ptsaux[(iq << 1) + 1]);
373             zmat[(k - np) * zmat_dim1 + 1] = temp;
374             zmat[ip + 1 + (k - np) * zmat_dim1] = -temp;
375             zmat[iq + 1 + (k - np) * zmat_dim1] = -temp;
376 /* L70: */
377             zmat[k + (k - np) * zmat_dim1] = temp;
378         }
379     }
380     nrem = *npt;
381     kold = 1;
382     knew = *kopt;
383
384 /*     Reorder the provisional points in the way that exchanges PTSID(KOLD) */
385 /*     with PTSID(KNEW). */
386
387 L80:
388     i__2 = *n;
389     for (j = 1; j <= i__2; ++j) {
390         temp = bmat[kold + j * bmat_dim1];
391         bmat[kold + j * bmat_dim1] = bmat[knew + j * bmat_dim1];
392 /* L90: */
393         bmat[knew + j * bmat_dim1] = temp;
394     }
395     i__2 = nptm;
396     for (j = 1; j <= i__2; ++j) {
397         temp = zmat[kold + j * zmat_dim1];
398         zmat[kold + j * zmat_dim1] = zmat[knew + j * zmat_dim1];
399 /* L100: */
400         zmat[knew + j * zmat_dim1] = temp;
401     }
402     ptsid[kold] = ptsid[knew];
403     ptsid[knew] = zero;
404     w[*ndim + knew] = zero;
405     --nrem;
406     if (knew != *kopt) {
407         temp = vlag[kold];
408         vlag[kold] = vlag[knew];
409         vlag[knew] = temp;
410
411 /*     Update the BMAT and ZMAT matrices so that the status of the KNEW-th */
412 /*     interpolation point can be changed from provisional to original. The */
413 /*     branch to label 350 occurs if all the original points are reinstated. */
414 /*     The nonnegative values of W(NDIM+K) are required in the search below. */
415
416         update_(n, npt, &bmat[bmat_offset], &zmat[zmat_offset], ndim, &vlag[1]
417                 , &beta, &denom, &knew, &w[1]);
418         if (nrem == 0) {
419             goto L350;
420         }
421         i__2 = *npt;
422         for (k = 1; k <= i__2; ++k) {
423 /* L110: */
424             w[*ndim + k] = (d__1 = w[*ndim + k], fabs(d__1));
425         }
426     }
427
428 /*     Pick the index KNEW of an original interpolation point that has not */
429 /*     yet replaced one of the provisional interpolation points, giving */
430 /*     attention to the closeness to XOPT and to previous tries with KNEW. */
431
432 L120:
433     dsqmin = zero;
434     i__2 = *npt;
435     for (k = 1; k <= i__2; ++k) {
436         if (w[*ndim + k] > zero) {
437             if (dsqmin == zero || w[*ndim + k] < dsqmin) {
438                 knew = k;
439                 dsqmin = w[*ndim + k];
440             }
441         }
442 /* L130: */
443     }
444     if (dsqmin == zero) {
445         goto L260;
446     }
447
448 /*     Form the W-vector of the chosen original interpolation point. */
449
450     i__2 = *n;
451     for (j = 1; j <= i__2; ++j) {
452 /* L140: */
453         w[*npt + j] = xpt[knew + j * xpt_dim1];
454     }
455     i__2 = *npt;
456     for (k = 1; k <= i__2; ++k) {
457         sum = zero;
458         if (k == *kopt) {
459         } else if (ptsid[k] == zero) {
460             i__1 = *n;
461             for (j = 1; j <= i__1; ++j) {
462 /* L150: */
463                 sum += w[*npt + j] * xpt[k + j * xpt_dim1];
464             }
465         } else {
466             ip = (int) ptsid[k];
467             if (ip > 0) {
468                 sum = w[*npt + ip] * ptsaux[(ip << 1) + 1];
469             }
470             iq = (int) ((double) np * ptsid[k] - (double) (ip * 
471                     np));
472             if (iq > 0) {
473                 iw = 1;
474                 if (ip == 0) {
475                     iw = 2;
476                 }
477                 sum += w[*npt + iq] * ptsaux[iw + (iq << 1)];
478             }
479         }
480 /* L160: */
481         w[k] = half * sum * sum;
482     }
483
484 /*     Calculate VLAG and BETA for the required updating of the H matrix if */
485 /*     XPT(KNEW,.) is reinstated in the set of interpolation points. */
486
487     i__2 = *npt;
488     for (k = 1; k <= i__2; ++k) {
489         sum = zero;
490         i__1 = *n;
491         for (j = 1; j <= i__1; ++j) {
492 /* L170: */
493             sum += bmat[k + j * bmat_dim1] * w[*npt + j];
494         }
495 /* L180: */
496         vlag[k] = sum;
497     }
498     beta = zero;
499     i__2 = nptm;
500     for (j = 1; j <= i__2; ++j) {
501         sum = zero;
502         i__1 = *npt;
503         for (k = 1; k <= i__1; ++k) {
504 /* L190: */
505             sum += zmat[k + j * zmat_dim1] * w[k];
506         }
507         beta -= sum * sum;
508         i__1 = *npt;
509         for (k = 1; k <= i__1; ++k) {
510 /* L200: */
511             vlag[k] += sum * zmat[k + j * zmat_dim1];
512         }
513     }
514     bsum = zero;
515     distsq = zero;
516     i__1 = *n;
517     for (j = 1; j <= i__1; ++j) {
518         sum = zero;
519         i__2 = *npt;
520         for (k = 1; k <= i__2; ++k) {
521 /* L210: */
522             sum += bmat[k + j * bmat_dim1] * w[k];
523         }
524         jp = j + *npt;
525         bsum += sum * w[jp];
526         i__2 = *ndim;
527         for (ip = *npt + 1; ip <= i__2; ++ip) {
528 /* L220: */
529             sum += bmat[ip + j * bmat_dim1] * w[ip];
530         }
531         bsum += sum * w[jp];
532         vlag[jp] = sum;
533 /* L230: */
534 /* Computing 2nd power */
535         d__1 = xpt[knew + j * xpt_dim1];
536         distsq += d__1 * d__1;
537     }
538     beta = half * distsq * distsq + beta - bsum;
539     vlag[*kopt] += one;
540
541 /*     KOLD is set to the index of the provisional interpolation point that is */
542 /*     going to be deleted to make way for the KNEW-th original interpolation */
543 /*     point. The choice of KOLD is governed by the avoidance of a small value */
544 /*     of the denominator in the updating calculation of UPDATE. */
545
546     denom = zero;
547     vlmxsq = zero;
548     i__1 = *npt;
549     for (k = 1; k <= i__1; ++k) {
550         if (ptsid[k] != zero) {
551             hdiag = zero;
552             i__2 = nptm;
553             for (j = 1; j <= i__2; ++j) {
554 /* L240: */
555 /* Computing 2nd power */
556                 d__1 = zmat[k + j * zmat_dim1];
557                 hdiag += d__1 * d__1;
558             }
559 /* Computing 2nd power */
560             d__1 = vlag[k];
561             den = beta * hdiag + d__1 * d__1;
562             if (den > denom) {
563                 kold = k;
564                 denom = den;
565             }
566         }
567 /* L250: */
568 /* Computing MAX */
569 /* Computing 2nd power */
570         d__3 = vlag[k];
571         d__1 = vlmxsq, d__2 = d__3 * d__3;
572         vlmxsq = max(d__1,d__2);
573     }
574     if (denom <= vlmxsq * .01) {
575         w[*ndim + knew] = -w[*ndim + knew] - winc;
576         goto L120;
577     }
578     goto L80;
579
580 /*     When label 260 is reached, all the final positions of the interpolation */
581 /*     points have been chosen although any changes have not been included yet */
582 /*     in XPT. Also the final BMAT and ZMAT matrices are complete, but, apart */
583 /*     from the shift of XBASE, the updating of the quadratic model remains to */
584 /*     be done. The following cycle through the new interpolation points begins */
585 /*     by putting the new point in XPT(KPT,.) and by setting PQ(KPT) to zero, */
586 /*     except that a RETURN occurs if MAXFUN prohibits another value of F. */
587
588 L260:
589     i__1 = *npt;
590     for (kpt = 1; kpt <= i__1; ++kpt) {
591         if (ptsid[kpt] == zero) {
592             goto L340;
593         }
594
595         if (nlopt_stop_evals(stop)) return NLOPT_MAXEVAL_REACHED;
596         else if (nlopt_stop_time(stop)) return NLOPT_MAXTIME_REACHED;
597
598         ih = 0;
599         i__2 = *n;
600         for (j = 1; j <= i__2; ++j) {
601             w[j] = xpt[kpt + j * xpt_dim1];
602             xpt[kpt + j * xpt_dim1] = zero;
603             temp = pq[kpt] * w[j];
604             i__3 = j;
605             for (i__ = 1; i__ <= i__3; ++i__) {
606                 ++ih;
607 /* L270: */
608                 hq[ih] += temp * w[i__];
609             }
610         }
611         pq[kpt] = zero;
612         ip = (int) ptsid[kpt];
613         iq = (int) ((double) np * ptsid[kpt] - (double) (ip * np))
614                 ;
615         if (ip > 0) {
616             xp = ptsaux[(ip << 1) + 1];
617             xpt[kpt + ip * xpt_dim1] = xp;
618         }
619         if (iq > 0) {
620             xq = ptsaux[(iq << 1) + 1];
621             if (ip == 0) {
622                 xq = ptsaux[(iq << 1) + 2];
623             }
624             xpt[kpt + iq * xpt_dim1] = xq;
625         }
626
627 /*     Set VQUAD to the value of the current model at the new point. */
628
629         vquad = fbase;
630         if (ip > 0) {
631             ihp = (ip + ip * ip) / 2;
632             vquad += xp * (gopt[ip] + half * xp * hq[ihp]);
633         }
634         if (iq > 0) {
635             ihq = (iq + iq * iq) / 2;
636             vquad += xq * (gopt[iq] + half * xq * hq[ihq]);
637             if (ip > 0) {
638                 iw = max(ihp,ihq) - (i__3 = ip - iq, iabs(i__3));
639                 vquad += xp * xq * hq[iw];
640             }
641         }
642         i__3 = *npt;
643         for (k = 1; k <= i__3; ++k) {
644             temp = zero;
645             if (ip > 0) {
646                 temp += xp * xpt[k + ip * xpt_dim1];
647             }
648             if (iq > 0) {
649                 temp += xq * xpt[k + iq * xpt_dim1];
650             }
651 /* L280: */
652             vquad += half * pq[k] * temp * temp;
653         }
654
655 /*     Calculate F at the new interpolation point, and set DIFF to the factor */
656 /*     that is going to multiply the KPT-th Lagrange function when the model */
657 /*     is updated to provide interpolation to the new function value. */
658
659         i__3 = *n;
660         for (i__ = 1; i__ <= i__3; ++i__) {
661 /* Computing MIN */
662 /* Computing MAX */
663             d__3 = xl[i__], d__4 = xbase[i__] + xpt[kpt + i__ * xpt_dim1];
664             d__1 = max(d__3,d__4), d__2 = xu[i__];
665             w[i__] = min(d__1,d__2);
666             if (xpt[kpt + i__ * xpt_dim1] == sl[i__]) {
667                 w[i__] = xl[i__];
668             }
669             if (xpt[kpt + i__ * xpt_dim1] == su[i__]) {
670                 w[i__] = xu[i__];
671             }
672 /* L290: */
673         }
674
675         stop->nevals++;
676         f = calfun(*n, &w[1], calfun_data);
677         fval[kpt] = f;
678         if (f < fval[*kopt]) {
679             *kopt = kpt;
680         }
681         if (f < stop->minf_max) return NLOPT_MINF_MAX_REACHED;
682         else if (nlopt_stop_evals(stop)) return NLOPT_MAXEVAL_REACHED;
683         else if (nlopt_stop_time(stop)) return NLOPT_MAXTIME_REACHED;
684
685         diff = f - vquad;
686
687 /*     Update the quadratic model. The RETURN from the subroutine occurs when */
688 /*     all the new interpolation points are included in the model. */
689
690         i__3 = *n;
691         for (i__ = 1; i__ <= i__3; ++i__) {
692 /* L310: */
693             gopt[i__] += diff * bmat[kpt + i__ * bmat_dim1];
694         }
695         i__3 = *npt;
696         for (k = 1; k <= i__3; ++k) {
697             sum = zero;
698             i__2 = nptm;
699             for (j = 1; j <= i__2; ++j) {
700 /* L320: */
701                 sum += zmat[k + j * zmat_dim1] * zmat[kpt + j * zmat_dim1];
702             }
703             temp = diff * sum;
704             if (ptsid[k] == zero) {
705                 pq[k] += temp;
706             } else {
707                 ip = (int) ptsid[k];
708                 iq = (int) ((double) np * ptsid[k] - (double) (ip 
709                         * np));
710                 ihq = (iq * iq + iq) / 2;
711                 if (ip == 0) {
712 /* Computing 2nd power */
713                     d__1 = ptsaux[(iq << 1) + 2];
714                     hq[ihq] += temp * (d__1 * d__1);
715                 } else {
716                     ihp = (ip * ip + ip) / 2;
717 /* Computing 2nd power */
718                     d__1 = ptsaux[(ip << 1) + 1];
719                     hq[ihp] += temp * (d__1 * d__1);
720                     if (iq > 0) {
721 /* Computing 2nd power */
722                         d__1 = ptsaux[(iq << 1) + 1];
723                         hq[ihq] += temp * (d__1 * d__1);
724                         iw = max(ihp,ihq) - (i__2 = iq - ip, iabs(i__2));
725                         hq[iw] += temp * ptsaux[(ip << 1) + 1] * ptsaux[(iq <<
726                                  1) + 1];
727                     }
728                 }
729             }
730 /* L330: */
731         }
732         ptsid[kpt] = zero;
733 L340:
734         ;
735     }
736 L350:
737     return NLOPT_SUCCESS;
738 } /* rescue_ */
739
740 static void altmov_(int *n, int *npt, double *xpt, 
741         double *xopt, double *bmat, double *zmat, int *ndim, 
742         double *sl, double *su, int *kopt, int *knew, 
743         double *adelt, double *xnew, double *xalt, double *
744         alpha, double *cauchy, double *glag, double *hcol, 
745         double *w)
746 {
747     /* System generated locals */
748     int xpt_dim1, xpt_offset, bmat_dim1, bmat_offset, zmat_dim1, 
749             zmat_offset, i__1, i__2;
750     double d__1, d__2, d__3, d__4;
751
752     /* Local variables */
753     int i__, j, k;
754     double ha, gw, one, diff, half;
755     int ilbd, isbd;
756     double slbd;
757     int iubd;
758     double vlag, subd, temp;
759     int ksav;
760     double step, zero, curv;
761     int iflag;
762     double scale, csave, tempa, tempb, tempd, const__, sumin, ggfree;
763     int ibdsav;
764     double dderiv, bigstp, predsq, presav, distsq, stpsav, wfixsq, wsqsav;
765
766
767 /*     The arguments N, NPT, XPT, XOPT, BMAT, ZMAT, NDIM, SL and SU all have */
768 /*       the same meanings as the corresponding arguments of BOBYQB. */
769 /*     KOPT is the index of the optimal interpolation point. */
770 /*     KNEW is the index of the interpolation point that is going to be moved. */
771 /*     ADELT is the current trust region bound. */
772 /*     XNEW will be set to a suitable new position for the interpolation point */
773 /*       XPT(KNEW,.). Specifically, it satisfies the SL, SU and trust region */
774 /*       bounds and it should provide a large denominator in the next call of */
775 /*       UPDATE. The step XNEW-XOPT from XOPT is restricted to moves along the */
776 /*       straight lines through XOPT and another interpolation point. */
777 /*     XALT also provides a large value of the modulus of the KNEW-th Lagrange */
778 /*       function subject to the constraints that have been mentioned, its main */
779 /*       difference from XNEW being that XALT-XOPT is a constrained version of */
780 /*       the Cauchy step within the trust region. An exception is that XALT is */
781 /*       not calculated if all components of GLAG (see below) are zero. */
782 /*     ALPHA will be set to the KNEW-th diagonal element of the H matrix. */
783 /*     CAUCHY will be set to the square of the KNEW-th Lagrange function at */
784 /*       the step XALT-XOPT from XOPT for the vector XALT that is returned, */
785 /*       except that CAUCHY is set to zero if XALT is not calculated. */
786 /*     GLAG is a working space vector of length N for the gradient of the */
787 /*       KNEW-th Lagrange function at XOPT. */
788 /*     HCOL is a working space vector of length NPT for the second derivative */
789 /*       coefficients of the KNEW-th Lagrange function. */
790 /*     W is a working space vector of length 2N that is going to hold the */
791 /*       constrained Cauchy step from XOPT of the Lagrange function, followed */
792 /*       by the downhill version of XALT when the uphill step is calculated. */
793
794 /*     Set the first NPT components of W to the leading elements of the */
795 /*     KNEW-th column of the H matrix. */
796
797     /* Parameter adjustments */
798     zmat_dim1 = *npt;
799     zmat_offset = 1 + zmat_dim1;
800     zmat -= zmat_offset;
801     xpt_dim1 = *npt;
802     xpt_offset = 1 + xpt_dim1;
803     xpt -= xpt_offset;
804     --xopt;
805     bmat_dim1 = *ndim;
806     bmat_offset = 1 + bmat_dim1;
807     bmat -= bmat_offset;
808     --sl;
809     --su;
810     --xnew;
811     --xalt;
812     --glag;
813     --hcol;
814     --w;
815
816     /* Function Body */
817     half = .5;
818     one = 1.;
819     zero = 0.;
820     const__ = one + sqrt(2.);
821     i__1 = *npt;
822     for (k = 1; k <= i__1; ++k) {
823 /* L10: */
824         hcol[k] = zero;
825     }
826     i__1 = *npt - *n - 1;
827     for (j = 1; j <= i__1; ++j) {
828         temp = zmat[*knew + j * zmat_dim1];
829         i__2 = *npt;
830         for (k = 1; k <= i__2; ++k) {
831 /* L20: */
832             hcol[k] += temp * zmat[k + j * zmat_dim1];
833         }
834     }
835     *alpha = hcol[*knew];
836     ha = half * *alpha;
837
838 /*     Calculate the gradient of the KNEW-th Lagrange function at XOPT. */
839
840     i__2 = *n;
841     for (i__ = 1; i__ <= i__2; ++i__) {
842 /* L30: */
843         glag[i__] = bmat[*knew + i__ * bmat_dim1];
844     }
845     i__2 = *npt;
846     for (k = 1; k <= i__2; ++k) {
847         temp = zero;
848         i__1 = *n;
849         for (j = 1; j <= i__1; ++j) {
850 /* L40: */
851             temp += xpt[k + j * xpt_dim1] * xopt[j];
852         }
853         temp = hcol[k] * temp;
854         i__1 = *n;
855         for (i__ = 1; i__ <= i__1; ++i__) {
856 /* L50: */
857             glag[i__] += temp * xpt[k + i__ * xpt_dim1];
858         }
859     }
860
861 /*     Search for a large denominator along the straight lines through XOPT */
862 /*     and another interpolation point. SLBD and SUBD will be lower and upper */
863 /*     bounds on the step along each of these lines in turn. PREDSQ will be */
864 /*     set to the square of the predicted denominator for each line. PRESAV */
865 /*     will be set to the largest admissible value of PREDSQ that occurs. */
866
867     presav = zero;
868     i__1 = *npt;
869     for (k = 1; k <= i__1; ++k) {
870         if (k == *kopt) {
871             goto L80;
872         }
873         dderiv = zero;
874         distsq = zero;
875         i__2 = *n;
876         for (i__ = 1; i__ <= i__2; ++i__) {
877             temp = xpt[k + i__ * xpt_dim1] - xopt[i__];
878             dderiv += glag[i__] * temp;
879 /* L60: */
880             distsq += temp * temp;
881         }
882         subd = *adelt / sqrt(distsq);
883         slbd = -subd;
884         ilbd = 0;
885         iubd = 0;
886         sumin = min(one,subd);
887
888 /*     Revise SLBD and SUBD if necessary because of the bounds in SL and SU. */
889
890         i__2 = *n;
891         for (i__ = 1; i__ <= i__2; ++i__) {
892             temp = xpt[k + i__ * xpt_dim1] - xopt[i__];
893             if (temp > zero) {
894                 if (slbd * temp < sl[i__] - xopt[i__]) {
895                     slbd = (sl[i__] - xopt[i__]) / temp;
896                     ilbd = -i__;
897                 }
898                 if (subd * temp > su[i__] - xopt[i__]) {
899 /* Computing MAX */
900                     d__1 = sumin, d__2 = (su[i__] - xopt[i__]) / temp;
901                     subd = max(d__1,d__2);
902                     iubd = i__;
903                 }
904             } else if (temp < zero) {
905                 if (slbd * temp > su[i__] - xopt[i__]) {
906                     slbd = (su[i__] - xopt[i__]) / temp;
907                     ilbd = i__;
908                 }
909                 if (subd * temp < sl[i__] - xopt[i__]) {
910 /* Computing MAX */
911                     d__1 = sumin, d__2 = (sl[i__] - xopt[i__]) / temp;
912                     subd = max(d__1,d__2);
913                     iubd = -i__;
914                 }
915             }
916 /* L70: */
917         }
918
919 /*     Seek a large modulus of the KNEW-th Lagrange function when the index */
920 /*     of the other interpolation point on the line through XOPT is KNEW. */
921
922         if (k == *knew) {
923             diff = dderiv - one;
924             step = slbd;
925             vlag = slbd * (dderiv - slbd * diff);
926             isbd = ilbd;
927             temp = subd * (dderiv - subd * diff);
928             if (fabs(temp) > fabs(vlag)) {
929                 step = subd;
930                 vlag = temp;
931                 isbd = iubd;
932             }
933             tempd = half * dderiv;
934             tempa = tempd - diff * slbd;
935             tempb = tempd - diff * subd;
936             if (tempa * tempb < zero) {
937                 temp = tempd * tempd / diff;
938                 if (fabs(temp) > fabs(vlag)) {
939                     step = tempd / diff;
940                     vlag = temp;
941                     isbd = 0;
942                 }
943             }
944
945 /*     Search along each of the other lines through XOPT and another point. */
946
947         } else {
948             step = slbd;
949             vlag = slbd * (one - slbd);
950             isbd = ilbd;
951             temp = subd * (one - subd);
952             if (fabs(temp) > fabs(vlag)) {
953                 step = subd;
954                 vlag = temp;
955                 isbd = iubd;
956             }
957             if (subd > half) {
958                 if (fabs(vlag) < .25) {
959                     step = half;
960                     vlag = .25;
961                     isbd = 0;
962                 }
963             }
964             vlag *= dderiv;
965         }
966
967 /*     Calculate PREDSQ for the current line search and maintain PRESAV. */
968
969         temp = step * (one - step) * distsq;
970         predsq = vlag * vlag * (vlag * vlag + ha * temp * temp);
971         if (predsq > presav) {
972             presav = predsq;
973             ksav = k;
974             stpsav = step;
975             ibdsav = isbd;
976         }
977 L80:
978         ;
979     }
980
981 /*     Construct XNEW in a way that satisfies the bound constraints exactly. */
982
983     i__1 = *n;
984     for (i__ = 1; i__ <= i__1; ++i__) {
985         temp = xopt[i__] + stpsav * (xpt[ksav + i__ * xpt_dim1] - xopt[i__]);
986 /* L90: */
987 /* Computing MAX */
988 /* Computing MIN */
989         d__3 = su[i__];
990         d__1 = sl[i__], d__2 = min(d__3,temp);
991         xnew[i__] = max(d__1,d__2);
992     }
993     if (ibdsav < 0) {
994         xnew[-ibdsav] = sl[-ibdsav];
995     }
996     if (ibdsav > 0) {
997         xnew[ibdsav] = su[ibdsav];
998     }
999
1000 /*     Prepare for the iterative method that assembles the constrained Cauchy */
1001 /*     step in W. The sum of squares of the fixed components of W is formed in */
1002 /*     WFIXSQ, and the free components of W are set to BIGSTP. */
1003
1004     bigstp = *adelt + *adelt;
1005     iflag = 0;
1006 L100:
1007     wfixsq = zero;
1008     ggfree = zero;
1009     i__1 = *n;
1010     for (i__ = 1; i__ <= i__1; ++i__) {
1011         w[i__] = zero;
1012 /* Computing MIN */
1013         d__1 = xopt[i__] - sl[i__], d__2 = glag[i__];
1014         tempa = min(d__1,d__2);
1015 /* Computing MAX */
1016         d__1 = xopt[i__] - su[i__], d__2 = glag[i__];
1017         tempb = max(d__1,d__2);
1018         if (tempa > zero || tempb < zero) {
1019             w[i__] = bigstp;
1020 /* Computing 2nd power */
1021             d__1 = glag[i__];
1022             ggfree += d__1 * d__1;
1023         }
1024 /* L110: */
1025     }
1026     if (ggfree == zero) {
1027         *cauchy = zero;
1028         goto L200;
1029     }
1030
1031 /*     Investigate whether more components of W can be fixed. */
1032
1033 L120:
1034     temp = *adelt * *adelt - wfixsq;
1035     if (temp > zero) {
1036         wsqsav = wfixsq;
1037         step = sqrt(temp / ggfree);
1038         ggfree = zero;
1039         i__1 = *n;
1040         for (i__ = 1; i__ <= i__1; ++i__) {
1041             if (w[i__] == bigstp) {
1042                 temp = xopt[i__] - step * glag[i__];
1043                 if (temp <= sl[i__]) {
1044                     w[i__] = sl[i__] - xopt[i__];
1045 /* Computing 2nd power */
1046                     d__1 = w[i__];
1047                     wfixsq += d__1 * d__1;
1048                 } else if (temp >= su[i__]) {
1049                     w[i__] = su[i__] - xopt[i__];
1050 /* Computing 2nd power */
1051                     d__1 = w[i__];
1052                     wfixsq += d__1 * d__1;
1053                 } else {
1054 /* Computing 2nd power */
1055                     d__1 = glag[i__];
1056                     ggfree += d__1 * d__1;
1057                 }
1058             }
1059 /* L130: */
1060         }
1061         if (wfixsq > wsqsav && ggfree > zero) {
1062             goto L120;
1063         }
1064     }
1065
1066 /*     Set the remaining free components of W and all components of XALT, */
1067 /*     except that W may be scaled later. */
1068
1069     gw = zero;
1070     i__1 = *n;
1071     for (i__ = 1; i__ <= i__1; ++i__) {
1072         if (w[i__] == bigstp) {
1073             w[i__] = -step * glag[i__];
1074 /* Computing MAX */
1075 /* Computing MIN */
1076             d__3 = su[i__], d__4 = xopt[i__] + w[i__];
1077             d__1 = sl[i__], d__2 = min(d__3,d__4);
1078             xalt[i__] = max(d__1,d__2);
1079         } else if (w[i__] == zero) {
1080             xalt[i__] = xopt[i__];
1081         } else if (glag[i__] > zero) {
1082             xalt[i__] = sl[i__];
1083         } else {
1084             xalt[i__] = su[i__];
1085         }
1086 /* L140: */
1087         gw += glag[i__] * w[i__];
1088     }
1089
1090 /*     Set CURV to the curvature of the KNEW-th Lagrange function along W. */
1091 /*     Scale W by a factor less than one if that can reduce the modulus of */
1092 /*     the Lagrange function at XOPT+W. Set CAUCHY to the final value of */
1093 /*     the square of this function. */
1094
1095     curv = zero;
1096     i__1 = *npt;
1097     for (k = 1; k <= i__1; ++k) {
1098         temp = zero;
1099         i__2 = *n;
1100         for (j = 1; j <= i__2; ++j) {
1101 /* L150: */
1102             temp += xpt[k + j * xpt_dim1] * w[j];
1103         }
1104 /* L160: */
1105         curv += hcol[k] * temp * temp;
1106     }
1107     if (iflag == 1) {
1108         curv = -curv;
1109     }
1110     if (curv > -gw && curv < -const__ * gw) {
1111         scale = -gw / curv;
1112         i__1 = *n;
1113         for (i__ = 1; i__ <= i__1; ++i__) {
1114             temp = xopt[i__] + scale * w[i__];
1115 /* L170: */
1116 /* Computing MAX */
1117 /* Computing MIN */
1118             d__3 = su[i__];
1119             d__1 = sl[i__], d__2 = min(d__3,temp);
1120             xalt[i__] = max(d__1,d__2);
1121         }
1122 /* Computing 2nd power */
1123         d__1 = half * gw * scale;
1124         *cauchy = d__1 * d__1;
1125     } else {
1126 /* Computing 2nd power */
1127         d__1 = gw + half * curv;
1128         *cauchy = d__1 * d__1;
1129     }
1130
1131 /*     If IFLAG is zero, then XALT is calculated as before after reversing */
1132 /*     the sign of GLAG. Thus two XALT vectors become available. The one that */
1133 /*     is chosen is the one that gives the larger value of CAUCHY. */
1134
1135     if (iflag == 0) {
1136         i__1 = *n;
1137         for (i__ = 1; i__ <= i__1; ++i__) {
1138             glag[i__] = -glag[i__];
1139 /* L180: */
1140             w[*n + i__] = xalt[i__];
1141         }
1142         csave = *cauchy;
1143         iflag = 1;
1144         goto L100;
1145     }
1146     if (csave > *cauchy) {
1147         i__1 = *n;
1148         for (i__ = 1; i__ <= i__1; ++i__) {
1149 /* L190: */
1150             xalt[i__] = w[*n + i__];
1151         }
1152         *cauchy = csave;
1153     }
1154 L200:
1155     return;
1156 } /* altmov_ */
1157
1158 static void trsbox_(int *n, int *npt, double *xpt, 
1159         double *xopt, double *gopt, double *hq, double *pq, 
1160         double *sl, double *su, double *delta, double *xnew, 
1161         double *d__, double *gnew, double *xbdi, double *s, 
1162         double *hs, double *hred, double *dsq, double *crvmin)
1163 {
1164     /* System generated locals */
1165     int xpt_dim1, xpt_offset, i__1, i__2;
1166     double d__1, d__2, d__3, d__4;
1167
1168     /* Local variables */
1169     int i__, j, k, ih;
1170     double ds;
1171     int iu;
1172     double dhd, dhs, cth, one, shs, sth, ssq, half, beta, sdec, blen;
1173     int iact, nact;
1174     double angt, qred;
1175     int isav;
1176     double temp, zero, xsav, xsum, angbd, dredg, sredg;
1177     int iterc;
1178     double resid, delsq, ggsav, tempa, tempb, ratio, sqstp, redmax, 
1179             dredsq, redsav, onemin, gredsq, rednew;
1180     int itcsav;
1181     double rdprev, rdnext, stplen, stepsq;
1182     int itermax;
1183
1184
1185 /*     The arguments N, NPT, XPT, XOPT, GOPT, HQ, PQ, SL and SU have the same */
1186 /*       meanings as the corresponding arguments of BOBYQB. */
1187 /*     DELTA is the trust region radius for the present calculation, which */
1188 /*       seeks a small value of the quadratic model within distance DELTA of */
1189 /*       XOPT subject to the bounds on the variables. */
1190 /*     XNEW will be set to a new vector of variables that is approximately */
1191 /*       the one that minimizes the quadratic model within the trust region */
1192 /*       subject to the SL and SU constraints on the variables. It satisfies */
1193 /*       as equations the bounds that become active during the calculation. */
1194 /*     D is the calculated trial step from XOPT, generated iteratively from an */
1195 /*       initial value of zero. Thus XNEW is XOPT+D after the final iteration. */
1196 /*     GNEW holds the gradient of the quadratic model at XOPT+D. It is updated */
1197 /*       when D is updated. */
1198 /*     XBDI is a working space vector. For I=1,2,...,N, the element XBDI(I) is */
1199 /*       set to -1.0, 0.0, or 1.0, the value being nonzero if and only if the */
1200 /*       I-th variable has become fixed at a bound, the bound being SL(I) or */
1201 /*       SU(I) in the case XBDI(I)=-1.0 or XBDI(I)=1.0, respectively. This */
1202 /*       information is accumulated during the construction of XNEW. */
1203 /*     The arrays S, HS and HRED are also used for working space. They hold the */
1204 /*       current search direction, and the changes in the gradient of Q along S */
1205 /*       and the reduced D, respectively, where the reduced D is the same as D, */
1206 /*       except that the components of the fixed variables are zero. */
1207 /*     DSQ will be set to the square of the length of XNEW-XOPT. */
1208 /*     CRVMIN is set to zero if D reaches the trust region boundary. Otherwise */
1209 /*       it is set to the least curvature of H that occurs in the conjugate */
1210 /*       gradient searches that are not restricted by any constraints. The */
1211 /*       value CRVMIN=-1.0D0 is set, however, if all of these searches are */
1212 /*       constrained. */
1213
1214 /*     A version of the truncated conjugate gradient is applied. If a line */
1215 /*     search is restricted by a constraint, then the procedure is restarted, */
1216 /*     the values of the variables that are at their bounds being fixed. If */
1217 /*     the trust region boundary is reached, then further changes may be made */
1218 /*     to D, each one being in the two dimensional space that is spanned */
1219 /*     by the current D and the gradient of Q at XOPT+D, staying on the trust */
1220 /*     region boundary. Termination occurs when the reduction in Q seems to */
1221 /*     be close to the greatest reduction that can be achieved. */
1222
1223 /*     Set some constants. */
1224
1225     /* Parameter adjustments */
1226     xpt_dim1 = *npt;
1227     xpt_offset = 1 + xpt_dim1;
1228     xpt -= xpt_offset;
1229     --xopt;
1230     --gopt;
1231     --hq;
1232     --pq;
1233     --sl;
1234     --su;
1235     --xnew;
1236     --d__;
1237     --gnew;
1238     --xbdi;
1239     --s;
1240     --hs;
1241     --hred;
1242
1243     /* Function Body */
1244     half = .5;
1245     one = 1.;
1246     onemin = -1.;
1247     zero = 0.;
1248
1249 /*     The sign of GOPT(I) gives the sign of the change to the I-th variable */
1250 /*     that will reduce Q from its value at XOPT. Thus XBDI(I) shows whether */
1251 /*     or not to fix the I-th variable at one of its bounds initially, with */
1252 /*     NACT being set to the number of fixed variables. D and GNEW are also */
1253 /*     set for the first iteration. DELSQ is the upper bound on the sum of */
1254 /*     squares of the free variables. QRED is the reduction in Q so far. */
1255
1256     iterc = 0;
1257     nact = 0;
1258     sqstp = zero;
1259     i__1 = *n;
1260     for (i__ = 1; i__ <= i__1; ++i__) {
1261         xbdi[i__] = zero;
1262         if (xopt[i__] <= sl[i__]) {
1263             if (gopt[i__] >= zero) {
1264                 xbdi[i__] = onemin;
1265             }
1266         } else if (xopt[i__] >= su[i__]) {
1267             if (gopt[i__] <= zero) {
1268                 xbdi[i__] = one;
1269             }
1270         }
1271         if (xbdi[i__] != zero) {
1272             ++nact;
1273         }
1274         d__[i__] = zero;
1275 /* L10: */
1276         gnew[i__] = gopt[i__];
1277     }
1278     delsq = *delta * *delta;
1279     qred = zero;
1280     *crvmin = onemin;
1281
1282 /*     Set the next search direction of the conjugate gradient method. It is */
1283 /*     the steepest descent direction initially and when the iterations are */
1284 /*     restarted because a variable has just been fixed by a bound, and of */
1285 /*     course the components of the fixed variables are zero. ITERMAX is an */
1286 /*     upper bound on the indices of the conjugate gradient iterations. */
1287
1288 L20:
1289     beta = zero;
1290 L30:
1291     stepsq = zero;
1292     i__1 = *n;
1293     for (i__ = 1; i__ <= i__1; ++i__) {
1294         if (xbdi[i__] != zero) {
1295             s[i__] = zero;
1296         } else if (beta == zero) {
1297             s[i__] = -gnew[i__];
1298         } else {
1299             s[i__] = beta * s[i__] - gnew[i__];
1300         }
1301 /* L40: */
1302 /* Computing 2nd power */
1303         d__1 = s[i__];
1304         stepsq += d__1 * d__1;
1305     }
1306     if (stepsq == zero) {
1307         goto L190;
1308     }
1309     if (beta == zero) {
1310         gredsq = stepsq;
1311         itermax = iterc + *n - nact;
1312     }
1313     if (gredsq * delsq <= qred * 1e-4 * qred) {
1314         goto L190;
1315     }
1316
1317 /*     Multiply the search direction by the second derivative matrix of Q and */
1318 /*     calculate some scalars for the choice of steplength. Then set BLEN to */
1319 /*     the length of the the step to the trust region boundary and STPLEN to */
1320 /*     the steplength, ignoring the simple bounds. */
1321
1322     goto L210;
1323 L50:
1324     resid = delsq;
1325     ds = zero;
1326     shs = zero;
1327     i__1 = *n;
1328     for (i__ = 1; i__ <= i__1; ++i__) {
1329         if (xbdi[i__] == zero) {
1330 /* Computing 2nd power */
1331             d__1 = d__[i__];
1332             resid -= d__1 * d__1;
1333             ds += s[i__] * d__[i__];
1334             shs += s[i__] * hs[i__];
1335         }
1336 /* L60: */
1337     }
1338     if (resid <= zero) {
1339         goto L90;
1340     }
1341     temp = sqrt(stepsq * resid + ds * ds);
1342     if (ds < zero) {
1343         blen = (temp - ds) / stepsq;
1344     } else {
1345         blen = resid / (temp + ds);
1346     }
1347     stplen = blen;
1348     if (shs > zero) {
1349 /* Computing MIN */
1350         d__1 = blen, d__2 = gredsq / shs;
1351         stplen = min(d__1,d__2);
1352     }
1353
1354 /*     Reduce STPLEN if necessary in order to preserve the simple bounds, */
1355 /*     letting IACT be the index of the new constrained variable. */
1356
1357     iact = 0;
1358     i__1 = *n;
1359     for (i__ = 1; i__ <= i__1; ++i__) {
1360         if (s[i__] != zero) {
1361             xsum = xopt[i__] + d__[i__];
1362             if (s[i__] > zero) {
1363                 temp = (su[i__] - xsum) / s[i__];
1364             } else {
1365                 temp = (sl[i__] - xsum) / s[i__];
1366             }
1367             if (temp < stplen) {
1368                 stplen = temp;
1369                 iact = i__;
1370             }
1371         }
1372 /* L70: */
1373     }
1374
1375 /*     Update CRVMIN, GNEW and D. Set SDEC to the decrease that occurs in Q. */
1376
1377     sdec = zero;
1378     if (stplen > zero) {
1379         ++iterc;
1380         temp = shs / stepsq;
1381         if (iact == 0 && temp > zero) {
1382             *crvmin = min(*crvmin,temp);
1383             if (*crvmin == onemin) {
1384                 *crvmin = temp;
1385             }
1386         }
1387         ggsav = gredsq;
1388         gredsq = zero;
1389         i__1 = *n;
1390         for (i__ = 1; i__ <= i__1; ++i__) {
1391             gnew[i__] += stplen * hs[i__];
1392             if (xbdi[i__] == zero) {
1393 /* Computing 2nd power */
1394                 d__1 = gnew[i__];
1395                 gredsq += d__1 * d__1;
1396             }
1397 /* L80: */
1398             d__[i__] += stplen * s[i__];
1399         }
1400 /* Computing MAX */
1401         d__1 = stplen * (ggsav - half * stplen * shs);
1402         sdec = max(d__1,zero);
1403         qred += sdec;
1404     }
1405
1406 /*     Restart the conjugate gradient method if it has hit a new bound. */
1407
1408     if (iact > 0) {
1409         ++nact;
1410         xbdi[iact] = one;
1411         if (s[iact] < zero) {
1412             xbdi[iact] = onemin;
1413         }
1414 /* Computing 2nd power */
1415         d__1 = d__[iact];
1416         delsq -= d__1 * d__1;
1417         if (delsq <= zero) {
1418             goto L90;
1419         }
1420         goto L20;
1421     }
1422
1423 /*     If STPLEN is less than BLEN, then either apply another conjugate */
1424 /*     gradient iteration or RETURN. */
1425
1426     if (stplen < blen) {
1427         if (iterc == itermax) {
1428             goto L190;
1429         }
1430         if (sdec <= qred * .01) {
1431             goto L190;
1432         }
1433         beta = gredsq / ggsav;
1434         goto L30;
1435     }
1436 L90:
1437     *crvmin = zero;
1438
1439 /*     Prepare for the alternative iteration by calculating some scalars */
1440 /*     and by multiplying the reduced D by the second derivative matrix of */
1441 /*     Q, where S holds the reduced D in the call of GGMULT. */
1442
1443 L100:
1444     if (nact >= *n - 1) {
1445         goto L190;
1446     }
1447     dredsq = zero;
1448     dredg = zero;
1449     gredsq = zero;
1450     i__1 = *n;
1451     for (i__ = 1; i__ <= i__1; ++i__) {
1452         if (xbdi[i__] == zero) {
1453 /* Computing 2nd power */
1454             d__1 = d__[i__];
1455             dredsq += d__1 * d__1;
1456             dredg += d__[i__] * gnew[i__];
1457 /* Computing 2nd power */
1458             d__1 = gnew[i__];
1459             gredsq += d__1 * d__1;
1460             s[i__] = d__[i__];
1461         } else {
1462             s[i__] = zero;
1463         }
1464 /* L110: */
1465     }
1466     itcsav = iterc;
1467     goto L210;
1468
1469 /*     Let the search direction S be a linear combination of the reduced D */
1470 /*     and the reduced G that is orthogonal to the reduced D. */
1471
1472 L120:
1473     ++iterc;
1474     temp = gredsq * dredsq - dredg * dredg;
1475     if (temp <= qred * 1e-4 * qred) {
1476         goto L190;
1477     }
1478     temp = sqrt(temp);
1479     i__1 = *n;
1480     for (i__ = 1; i__ <= i__1; ++i__) {
1481         if (xbdi[i__] == zero) {
1482             s[i__] = (dredg * d__[i__] - dredsq * gnew[i__]) / temp;
1483         } else {
1484             s[i__] = zero;
1485         }
1486 /* L130: */
1487     }
1488     sredg = -temp;
1489
1490 /*     By considering the simple bounds on the variables, calculate an upper */
1491 /*     bound on the tangent of half the angle of the alternative iteration, */
1492 /*     namely ANGBD, except that, if already a free variable has reached a */
1493 /*     bound, there is a branch back to label 100 after fixing that variable. */
1494
1495     angbd = one;
1496     iact = 0;
1497     i__1 = *n;
1498     for (i__ = 1; i__ <= i__1; ++i__) {
1499         if (xbdi[i__] == zero) {
1500             tempa = xopt[i__] + d__[i__] - sl[i__];
1501             tempb = su[i__] - xopt[i__] - d__[i__];
1502             if (tempa <= zero) {
1503                 ++nact;
1504                 xbdi[i__] = onemin;
1505                 goto L100;
1506             } else if (tempb <= zero) {
1507                 ++nact;
1508                 xbdi[i__] = one;
1509                 goto L100;
1510             }
1511             ratio = one;
1512 /* Computing 2nd power */
1513             d__1 = d__[i__];
1514 /* Computing 2nd power */
1515             d__2 = s[i__];
1516             ssq = d__1 * d__1 + d__2 * d__2;
1517 /* Computing 2nd power */
1518             d__1 = xopt[i__] - sl[i__];
1519             temp = ssq - d__1 * d__1;
1520             if (temp > zero) {
1521                 temp = sqrt(temp) - s[i__];
1522                 if (angbd * temp > tempa) {
1523                     angbd = tempa / temp;
1524                     iact = i__;
1525                     xsav = onemin;
1526                 }
1527             }
1528 /* Computing 2nd power */
1529             d__1 = su[i__] - xopt[i__];
1530             temp = ssq - d__1 * d__1;
1531             if (temp > zero) {
1532                 temp = sqrt(temp) + s[i__];
1533                 if (angbd * temp > tempb) {
1534                     angbd = tempb / temp;
1535                     iact = i__;
1536                     xsav = one;
1537                 }
1538             }
1539         }
1540 /* L140: */
1541     }
1542
1543 /*     Calculate HHD and some curvatures for the alternative iteration. */
1544
1545     goto L210;
1546 L150:
1547     shs = zero;
1548     dhs = zero;
1549     dhd = zero;
1550     i__1 = *n;
1551     for (i__ = 1; i__ <= i__1; ++i__) {
1552         if (xbdi[i__] == zero) {
1553             shs += s[i__] * hs[i__];
1554             dhs += d__[i__] * hs[i__];
1555             dhd += d__[i__] * hred[i__];
1556         }
1557 /* L160: */
1558     }
1559
1560 /*     Seek the greatest reduction in Q for a range of equally spaced values */
1561 /*     of ANGT in [0,ANGBD], where ANGT is the tangent of half the angle of */
1562 /*     the alternative iteration. */
1563
1564     redmax = zero;
1565     isav = 0;
1566     redsav = zero;
1567     iu = (int) (angbd * 17. + 3.1);
1568     i__1 = iu;
1569     for (i__ = 1; i__ <= i__1; ++i__) {
1570         angt = angbd * (double) i__ / (double) iu;
1571         sth = (angt + angt) / (one + angt * angt);
1572         temp = shs + angt * (angt * dhd - dhs - dhs);
1573         rednew = sth * (angt * dredg - sredg - half * sth * temp);
1574         if (rednew > redmax) {
1575             redmax = rednew;
1576             isav = i__;
1577             rdprev = redsav;
1578         } else if (i__ == isav + 1) {
1579             rdnext = rednew;
1580         }
1581 /* L170: */
1582         redsav = rednew;
1583     }
1584
1585 /*     Return if the reduction is zero. Otherwise, set the sine and cosine */
1586 /*     of the angle of the alternative iteration, and calculate SDEC. */
1587
1588     if (isav == 0) {
1589         goto L190;
1590     }
1591     if (isav < iu) {
1592         temp = (rdnext - rdprev) / (redmax + redmax - rdprev - rdnext);
1593         angt = angbd * ((double) isav + half * temp) / (double) iu;
1594     }
1595     cth = (one - angt * angt) / (one + angt * angt);
1596     sth = (angt + angt) / (one + angt * angt);
1597     temp = shs + angt * (angt * dhd - dhs - dhs);
1598     sdec = sth * (angt * dredg - sredg - half * sth * temp);
1599     if (sdec <= zero) {
1600         goto L190;
1601     }
1602
1603 /*     Update GNEW, D and HRED. If the angle of the alternative iteration */
1604 /*     is restricted by a bound on a free variable, that variable is fixed */
1605 /*     at the bound. */
1606
1607     dredg = zero;
1608     gredsq = zero;
1609     i__1 = *n;
1610     for (i__ = 1; i__ <= i__1; ++i__) {
1611         gnew[i__] = gnew[i__] + (cth - one) * hred[i__] + sth * hs[i__];
1612         if (xbdi[i__] == zero) {
1613             d__[i__] = cth * d__[i__] + sth * s[i__];
1614             dredg += d__[i__] * gnew[i__];
1615 /* Computing 2nd power */
1616             d__1 = gnew[i__];
1617             gredsq += d__1 * d__1;
1618         }
1619 /* L180: */
1620         hred[i__] = cth * hred[i__] + sth * hs[i__];
1621     }
1622     qred += sdec;
1623     if (iact > 0 && isav == iu) {
1624         ++nact;
1625         xbdi[iact] = xsav;
1626         goto L100;
1627     }
1628
1629 /*     If SDEC is sufficiently small, then RETURN after setting XNEW to */
1630 /*     XOPT+D, giving careful attention to the bounds. */
1631
1632     if (sdec > qred * .01) {
1633         goto L120;
1634     }
1635 L190:
1636     *dsq = zero;
1637     i__1 = *n;
1638     for (i__ = 1; i__ <= i__1; ++i__) {
1639 /* Computing MAX */
1640 /* Computing MIN */
1641         d__3 = xopt[i__] + d__[i__], d__4 = su[i__];
1642         d__1 = min(d__3,d__4), d__2 = sl[i__];
1643         xnew[i__] = max(d__1,d__2);
1644         if (xbdi[i__] == onemin) {
1645             xnew[i__] = sl[i__];
1646         }
1647         if (xbdi[i__] == one) {
1648             xnew[i__] = su[i__];
1649         }
1650         d__[i__] = xnew[i__] - xopt[i__];
1651 /* L200: */
1652 /* Computing 2nd power */
1653         d__1 = d__[i__];
1654         *dsq += d__1 * d__1;
1655     }
1656     return;
1657 /*     The following instructions multiply the current S-vector by the second */
1658 /*     derivative matrix of the quadratic model, putting the product in HS. */
1659 /*     They are reached from three different parts of the software above and */
1660 /*     they can be regarded as an external subroutine. */
1661
1662 L210:
1663     ih = 0;
1664     i__1 = *n;
1665     for (j = 1; j <= i__1; ++j) {
1666         hs[j] = zero;
1667         i__2 = j;
1668         for (i__ = 1; i__ <= i__2; ++i__) {
1669             ++ih;
1670             if (i__ < j) {
1671                 hs[j] += hq[ih] * s[i__];
1672             }
1673 /* L220: */
1674             hs[i__] += hq[ih] * s[j];
1675         }
1676     }
1677     i__2 = *npt;
1678     for (k = 1; k <= i__2; ++k) {
1679         if (pq[k] != zero) {
1680             temp = zero;
1681             i__1 = *n;
1682             for (j = 1; j <= i__1; ++j) {
1683 /* L230: */
1684                 temp += xpt[k + j * xpt_dim1] * s[j];
1685             }
1686             temp *= pq[k];
1687             i__1 = *n;
1688             for (i__ = 1; i__ <= i__1; ++i__) {
1689 /* L240: */
1690                 hs[i__] += temp * xpt[k + i__ * xpt_dim1];
1691             }
1692         }
1693 /* L250: */
1694     }
1695     if (*crvmin != zero) {
1696         goto L50;
1697     }
1698     if (iterc > itcsav) {
1699         goto L150;
1700     }
1701     i__2 = *n;
1702     for (i__ = 1; i__ <= i__2; ++i__) {
1703 /* L260: */
1704         hred[i__] = hs[i__];
1705     }
1706     goto L120;
1707 } /* trsbox_ */
1708
1709 static nlopt_result prelim_(int *n, int *npt, double *x, 
1710         const double *xl, const double *xu, double *rhobeg, 
1711                     nlopt_stopping *stop,
1712                     bobyqa_func calfun, void *calfun_data,
1713          double *xbase, double *xpt, double *fval,
1714          double *gopt, double *hq, double *pq, double *bmat, 
1715         double *zmat, int *ndim, double *sl, double *su, 
1716                     int *kopt)
1717 {
1718     /* System generated locals */
1719     int xpt_dim1, xpt_offset, bmat_dim1, bmat_offset, zmat_dim1, 
1720             zmat_offset, i__1, i__2;
1721     double d__1, d__2, d__3, d__4;
1722
1723     /* Local variables */
1724     double f;
1725     int i__, j, k, ih, np, nfm;
1726     double one;
1727     int nfx, ipt, jpt;
1728     double two, fbeg, diff, half, temp, zero, recip, stepa, stepb;
1729     int itemp;
1730     double rhosq;
1731
1732     int nf;
1733
1734 /*     The arguments N, NPT, X, XL, XU, RHOBEG, and MAXFUN are the */
1735 /*       same as the corresponding arguments in SUBROUTINE BOBYQA. */
1736 /*     The arguments XBASE, XPT, FVAL, HQ, PQ, BMAT, ZMAT, NDIM, SL and SU */
1737 /*       are the same as the corresponding arguments in BOBYQB, the elements */
1738 /*       of SL and SU being set in BOBYQA. */
1739 /*     GOPT is usually the gradient of the quadratic model at XOPT+XBASE, but */
1740 /*       it is set by PRELIM to the gradient of the quadratic model at XBASE. */
1741 /*       If XOPT is nonzero, BOBYQB will change it to its usual value later. */
1742 /*     NF is maintaned as the number of calls of CALFUN so far. */
1743 /*     KOPT will be such that the least calculated value of F so far is at */
1744 /*       the point XPT(KOPT,.)+XBASE in the space of the variables. */
1745
1746 /*     SUBROUTINE PRELIM sets the elements of XBASE, XPT, FVAL, GOPT, HQ, PQ, */
1747 /*     BMAT and ZMAT for the first iteration, and it maintains the values of */
1748 /*     NF and KOPT. The vector X is also changed by PRELIM. */
1749
1750 /*     Set some constants. */
1751
1752     /* Parameter adjustments */
1753     zmat_dim1 = *npt;
1754     zmat_offset = 1 + zmat_dim1;
1755     zmat -= zmat_offset;
1756     xpt_dim1 = *npt;
1757     xpt_offset = 1 + xpt_dim1;
1758     xpt -= xpt_offset;
1759     --x;
1760     --xl;
1761     --xu;
1762     --xbase;
1763     --fval;
1764     --gopt;
1765     --hq;
1766     --pq;
1767     bmat_dim1 = *ndim;
1768     bmat_offset = 1 + bmat_dim1;
1769     bmat -= bmat_offset;
1770     --sl;
1771     --su;
1772
1773     /* Function Body */
1774     half = .5;
1775     one = 1.;
1776     two = 2.;
1777     zero = 0.;
1778     rhosq = *rhobeg * *rhobeg;
1779     recip = one / rhosq;
1780     np = *n + 1;
1781
1782 /*     Set XBASE to the initial vector of variables, and set the initial */
1783 /*     elements of XPT, BMAT, HQ, PQ and ZMAT to zero. */
1784
1785     i__1 = *n;
1786     for (j = 1; j <= i__1; ++j) {
1787         xbase[j] = x[j];
1788         i__2 = *npt;
1789         for (k = 1; k <= i__2; ++k) {
1790 /* L10: */
1791             xpt[k + j * xpt_dim1] = zero;
1792         }
1793         i__2 = *ndim;
1794         for (i__ = 1; i__ <= i__2; ++i__) {
1795 /* L20: */
1796             bmat[i__ + j * bmat_dim1] = zero;
1797         }
1798     }
1799     i__2 = *n * np / 2;
1800     for (ih = 1; ih <= i__2; ++ih) {
1801 /* L30: */
1802         hq[ih] = zero;
1803     }
1804     i__2 = *npt;
1805     for (k = 1; k <= i__2; ++k) {
1806         pq[k] = zero;
1807         i__1 = *npt - np;
1808         for (j = 1; j <= i__1; ++j) {
1809 /* L40: */
1810             zmat[k + j * zmat_dim1] = zero;
1811         }
1812     }
1813
1814 /*     Begin the initialization procedure. NF becomes one more than the number */
1815 /*     of function values so far. The coordinates of the displacement of the */
1816 /*     next initial interpolation point from XBASE are set in XPT(NF+1,.). */
1817
1818     nf = 0;
1819 L50:
1820     nfm = nf;
1821     nfx = nf - *n;
1822     ++(nf);
1823     if (nfm <= *n << 1) {
1824         if (nfm >= 1 && nfm <= *n) {
1825             stepa = *rhobeg;
1826             if (su[nfm] == zero) {
1827                 stepa = -stepa;
1828             }
1829             xpt[nf + nfm * xpt_dim1] = stepa;
1830         } else if (nfm > *n) {
1831             stepa = xpt[nf - *n + nfx * xpt_dim1];
1832             stepb = -(*rhobeg);
1833             if (sl[nfx] == zero) {
1834 /* Computing MIN */
1835                 d__1 = two * *rhobeg, d__2 = su[nfx];
1836                 stepb = min(d__1,d__2);
1837             }
1838             if (su[nfx] == zero) {
1839 /* Computing MAX */
1840                 d__1 = -two * *rhobeg, d__2 = sl[nfx];
1841                 stepb = max(d__1,d__2);
1842             }
1843             xpt[nf + nfx * xpt_dim1] = stepb;
1844         }
1845     } else {
1846         itemp = (nfm - np) / *n;
1847         jpt = nfm - itemp * *n - *n;
1848         ipt = jpt + itemp;
1849         if (ipt > *n) {
1850             itemp = jpt;
1851             jpt = ipt - *n;
1852             ipt = itemp;
1853         }
1854         xpt[nf + ipt * xpt_dim1] = xpt[ipt + 1 + ipt * xpt_dim1];
1855         xpt[nf + jpt * xpt_dim1] = xpt[jpt + 1 + jpt * xpt_dim1];
1856     }
1857
1858 /*     Calculate the next value of F. The least function value so far and */
1859 /*     its index are required. */
1860
1861     i__1 = *n;
1862     for (j = 1; j <= i__1; ++j) {
1863 /* Computing MIN */
1864 /* Computing MAX */
1865         d__3 = xl[j], d__4 = xbase[j] + xpt[nf + j * xpt_dim1];
1866         d__1 = max(d__3,d__4), d__2 = xu[j];
1867         x[j] = min(d__1,d__2);
1868         if (xpt[nf + j * xpt_dim1] == sl[j]) {
1869             x[j] = xl[j];
1870         }
1871         if (xpt[nf + j * xpt_dim1] == su[j]) {
1872             x[j] = xu[j];
1873         }
1874 /* L60: */
1875     }
1876     stop->nevals++;
1877     f = calfun(*n, &x[1], calfun_data);
1878     fval[nf] = f;
1879     if (nf == 1) {
1880         fbeg = f;
1881         *kopt = 1;
1882     } else if (f < fval[*kopt]) {
1883         *kopt = nf;
1884     }
1885
1886 /*     Set the nonzero initial elements of BMAT and the quadratic model in the */
1887 /*     cases when NF is at most 2*N+1. If NF exceeds N+1, then the positions */
1888 /*     of the NF-th and (NF-N)-th interpolation points may be switched, in */
1889 /*     order that the function value at the first of them contributes to the */
1890 /*     off-diagonal second derivative terms of the initial quadratic model. */
1891
1892     if (nf <= (*n << 1) + 1) {
1893         if (nf >= 2 && nf <= *n + 1) {
1894             gopt[nfm] = (f - fbeg) / stepa;
1895             if (*npt < nf + *n) {
1896                 bmat[nfm * bmat_dim1 + 1] = -one / stepa;
1897                 bmat[nf + nfm * bmat_dim1] = one / stepa;
1898                 bmat[*npt + nfm + nfm * bmat_dim1] = -half * rhosq;
1899             }
1900         } else if (nf >= *n + 2) {
1901             ih = nfx * (nfx + 1) / 2;
1902             temp = (f - fbeg) / stepb;
1903             diff = stepb - stepa;
1904             hq[ih] = two * (temp - gopt[nfx]) / diff;
1905             gopt[nfx] = (gopt[nfx] * stepb - temp * stepa) / diff;
1906             if (stepa * stepb < zero) {
1907                 if (f < fval[nf - *n]) {
1908                     fval[nf] = fval[nf - *n];
1909                     fval[nf - *n] = f;
1910                     if (*kopt == nf) {
1911                         *kopt = nf - *n;
1912                     }
1913                     xpt[nf - *n + nfx * xpt_dim1] = stepb;
1914                     xpt[nf + nfx * xpt_dim1] = stepa;
1915                 }
1916             }
1917             bmat[nfx * bmat_dim1 + 1] = -(stepa + stepb) / (stepa * stepb);
1918             bmat[nf + nfx * bmat_dim1] = -half / xpt[nf - *n + nfx * 
1919                     xpt_dim1];
1920             bmat[nf - *n + nfx * bmat_dim1] = -bmat[nfx * bmat_dim1 + 1] - 
1921                     bmat[nf + nfx * bmat_dim1];
1922             zmat[nfx * zmat_dim1 + 1] = sqrt(two) / (stepa * stepb);
1923             zmat[nf + nfx * zmat_dim1] = sqrt(half) / rhosq;
1924             zmat[nf - *n + nfx * zmat_dim1] = -zmat[nfx * zmat_dim1 + 1] - 
1925                     zmat[nf + nfx * zmat_dim1];
1926         }
1927
1928 /*     Set the off-diagonal second derivatives of the Lagrange functions and */
1929 /*     the initial quadratic model. */
1930
1931     } else {
1932         ih = ipt * (ipt - 1) / 2 + jpt;
1933         zmat[nfx * zmat_dim1 + 1] = recip;
1934         zmat[nf + nfx * zmat_dim1] = recip;
1935         zmat[ipt + 1 + nfx * zmat_dim1] = -recip;
1936         zmat[jpt + 1 + nfx * zmat_dim1] = -recip;
1937         temp = xpt[nf + ipt * xpt_dim1] * xpt[nf + jpt * xpt_dim1];
1938         hq[ih] = (fbeg - fval[ipt + 1] - fval[jpt + 1] + f) / temp;
1939     }
1940     if (f < stop->minf_max) return NLOPT_MINF_MAX_REACHED;
1941     else if (nlopt_stop_evals(stop)) return NLOPT_MAXEVAL_REACHED;
1942     else if (nlopt_stop_time(stop)) return NLOPT_MAXTIME_REACHED;
1943     if (nf < *npt) {
1944         goto L50;
1945     }
1946     return NLOPT_SUCCESS;
1947 } /* prelim_ */
1948
1949 static nlopt_result bobyqb_(int *n, int *npt, double *x, 
1950         const double *xl, const double *xu, double *rhobeg, double *
1951         rhoend, 
1952                             nlopt_stopping *stop,
1953                             bobyqa_func calfun, void *calfun_data,
1954                             double *minf,
1955         double *xbase, 
1956         double *xpt, double *fval, double *xopt, double *gopt,
1957          double *hq, double *pq, double *bmat, double *zmat, 
1958         int *ndim, double *sl, double *su, double *xnew, 
1959         double *xalt, double *d__, double *vlag, double *w)
1960 {
1961     /* System generated locals */
1962     int xpt_dim1, xpt_offset, bmat_dim1, bmat_offset, zmat_dim1, 
1963             zmat_offset, i__1, i__2, i__3;
1964     double d__1, d__2, d__3, d__4;
1965
1966     /* Local variables */
1967     double f;
1968     int i__, j, k, ih, jj, nh, ip, jp;
1969     double dx;
1970     int np;
1971     double den, one, ten, dsq, rho, sum, two, diff, half, beta, gisq;
1972     int knew;
1973     double temp, suma, sumb, bsum, fopt;
1974     int kopt, nptm;
1975     double zero, curv;
1976     int ksav;
1977     double gqsq, dist, sumw, sumz, diffa, diffb, diffc, hdiag;
1978     int kbase;
1979     double alpha, delta, adelt, denom, fsave, bdtol, delsq;
1980     int nresc, nfsav;
1981     double ratio, dnorm, vquad, pqold, tenth;
1982     int itest;
1983     double sumpq, scaden;
1984     double errbig, cauchy, fracsq, biglsq, densav;
1985     double bdtest;
1986     double crvmin, frhosq;
1987     double distsq;
1988     int ntrits;
1989     double xoptsq;
1990
1991     nlopt_result rc = NLOPT_SUCCESS, rc2;
1992
1993 /*     The arguments N, NPT, X, XL, XU, RHOBEG, RHOEND, and MAXFUN */
1994 /*       are identical to the corresponding arguments in SUBROUTINE BOBYQA. */
1995 /*     XBASE holds a shift of origin that should reduce the contributions */
1996 /*       from rounding errors to values of the model and Lagrange functions. */
1997 /*     XPT is a two-dimensional array that holds the coordinates of the */
1998 /*       interpolation points relative to XBASE. */
1999 /*     FVAL holds the values of F at the interpolation points. */
2000 /*     XOPT is set to the displacement from XBASE of the trust region centre. */
2001 /*     GOPT holds the gradient of the quadratic model at XBASE+XOPT. */
2002 /*     HQ holds the explicit second derivatives of the quadratic model. */
2003 /*     PQ contains the parameters of the implicit second derivatives of the */
2004 /*       quadratic model. */
2005 /*     BMAT holds the last N columns of H. */
2006 /*     ZMAT holds the factorization of the leading NPT by NPT submatrix of H, */
2007 /*       this factorization being ZMAT times ZMAT^T, which provides both the */
2008 /*       correct rank and positive semi-definiteness. */
2009 /*     NDIM is the first dimension of BMAT and has the value NPT+N. */
2010 /*     SL and SU hold the differences XL-XBASE and XU-XBASE, respectively. */
2011 /*       All the components of every XOPT are going to satisfy the bounds */
2012 /*       SL(I) .LEQ. XOPT(I) .LEQ. SU(I), with appropriate equalities when */
2013 /*       XOPT is on a constraint boundary. */
2014 /*     XNEW is chosen by SUBROUTINE TRSBOX or ALTMOV. Usually XBASE+XNEW is the */
2015 /*       vector of variables for the next call of CALFUN. XNEW also satisfies */
2016 /*       the SL and SU constraints in the way that has just been mentioned. */
2017 /*     XALT is an alternative to XNEW, chosen by ALTMOV, that may replace XNEW */
2018 /*       in order to increase the denominator in the updating of UPDATE. */
2019 /*     D is reserved for a trial step from XOPT, which is usually XNEW-XOPT. */
2020 /*     VLAG contains the values of the Lagrange functions at a new point X. */
2021 /*       They are part of a product that requires VLAG to be of length NDIM. */
2022 /*     W is a one-dimensional array that is used for working space. Its length */
2023 /*       must be at least 3*NDIM = 3*(NPT+N). */
2024
2025 /*     Set some constants. */
2026
2027     /* Parameter adjustments */
2028     zmat_dim1 = *npt;
2029     zmat_offset = 1 + zmat_dim1;
2030     zmat -= zmat_offset;
2031     xpt_dim1 = *npt;
2032     xpt_offset = 1 + xpt_dim1;
2033     xpt -= xpt_offset;
2034     --x;
2035     --xl;
2036     --xu;
2037     --xbase;
2038     --fval;
2039     --xopt;
2040     --gopt;
2041     --hq;
2042     --pq;
2043     bmat_dim1 = *ndim;
2044     bmat_offset = 1 + bmat_dim1;
2045     bmat -= bmat_offset;
2046     --sl;
2047     --su;
2048     --xnew;
2049     --xalt;
2050     --d__;
2051     --vlag;
2052     --w;
2053
2054     /* Function Body */
2055     half = .5;
2056     one = 1.;
2057     ten = 10.;
2058     tenth = .1;
2059     two = 2.;
2060     zero = 0.;
2061     np = *n + 1;
2062     nptm = *npt - np;
2063     nh = *n * np / 2;
2064
2065 /*     The call of PRELIM sets the elements of XBASE, XPT, FVAL, GOPT, HQ, PQ, */
2066 /*     BMAT and ZMAT for the first iteration, with the corresponding values of */
2067 /*     of NF and KOPT, which are the number of calls of CALFUN so far and the */
2068 /*     index of the interpolation point at the trust region centre. Then the */
2069 /*     initial XOPT is set too. The branch to label 720 occurs if MAXFUN is */
2070 /*     less than NPT. GOPT will be updated if KOPT is different from KBASE. */
2071
2072     rc2 = prelim_(n, npt, &x[1], &xl[1], &xu[1], rhobeg, 
2073                   stop, calfun, calfun_data,
2074             &xbase[1], &xpt[xpt_offset], &fval[1], &gopt[1], &hq[1], &pq[1], &bmat[
2075             bmat_offset], &zmat[zmat_offset], ndim, &sl[1], &su[1], &kopt);
2076     xoptsq = zero;
2077     i__1 = *n;
2078     for (i__ = 1; i__ <= i__1; ++i__) {
2079         xopt[i__] = xpt[kopt + i__ * xpt_dim1];
2080 /* L10: */
2081 /* Computing 2nd power */
2082         d__1 = xopt[i__];
2083         xoptsq += d__1 * d__1;
2084     }
2085     fsave = fval[1];
2086     if (rc2 != NLOPT_SUCCESS) {
2087       rc = rc2;
2088       goto L720;
2089     }
2090     kbase = 1;
2091
2092 /*     Complete the settings that are required for the iterative procedure. */
2093
2094     rho = *rhobeg;
2095     delta = rho;
2096     nresc = stop->nevals;
2097     ntrits = 0;
2098     diffa = zero;
2099     diffb = zero;
2100     itest = 0;
2101     nfsav = stop->nevals;
2102
2103 /*     Update GOPT if necessary before the first iteration and after each */
2104 /*     call of RESCUE that makes a call of CALFUN. */
2105
2106 L20:
2107     if (kopt != kbase) {
2108         ih = 0;
2109         i__1 = *n;
2110         for (j = 1; j <= i__1; ++j) {
2111             i__2 = j;
2112             for (i__ = 1; i__ <= i__2; ++i__) {
2113                 ++ih;
2114                 if (i__ < j) {
2115                     gopt[j] += hq[ih] * xopt[i__];
2116                 }
2117 /* L30: */
2118                 gopt[i__] += hq[ih] * xopt[j];
2119             }
2120         }
2121         if (stop->nevals > *npt) {
2122             i__2 = *npt;
2123             for (k = 1; k <= i__2; ++k) {
2124                 temp = zero;
2125                 i__1 = *n;
2126                 for (j = 1; j <= i__1; ++j) {
2127 /* L40: */
2128                     temp += xpt[k + j * xpt_dim1] * xopt[j];
2129                 }
2130                 temp = pq[k] * temp;
2131                 i__1 = *n;
2132                 for (i__ = 1; i__ <= i__1; ++i__) {
2133 /* L50: */
2134                     gopt[i__] += temp * xpt[k + i__ * xpt_dim1];
2135                 }
2136             }
2137         }
2138     }
2139
2140 /*     Generate the next point in the trust region that provides a small value */
2141 /*     of the quadratic model subject to the constraints on the variables. */
2142 /*     The int NTRITS is set to the number "trust region" iterations that */
2143 /*     have occurred since the last "alternative" iteration. If the length */
2144 /*     of XNEW-XOPT is less than HALF*RHO, however, then there is a branch to */
2145 /*     label 650 or 680 with NTRITS=-1, instead of calculating F at XNEW. */
2146
2147 L60:
2148     trsbox_(n, npt, &xpt[xpt_offset], &xopt[1], &gopt[1], &hq[1], &pq[1], &sl[
2149             1], &su[1], &delta, &xnew[1], &d__[1], &w[1], &w[np], &w[np + *n],
2150              &w[np + (*n << 1)], &w[np + *n * 3], &dsq, &crvmin);
2151 /* Computing MIN */
2152     d__1 = delta, d__2 = sqrt(dsq);
2153     dnorm = min(d__1,d__2);
2154     if (dnorm < half * rho) {
2155         ntrits = -1;
2156 /* Computing 2nd power */
2157         d__1 = ten * rho;
2158         distsq = d__1 * d__1;
2159         if (stop->nevals <= nfsav + 2) {
2160             goto L650;
2161         }
2162
2163 /*     The following choice between labels 650 and 680 depends on whether or */
2164 /*     not our work with the current RHO seems to be complete. Either RHO is */
2165 /*     decreased or termination occurs if the errors in the quadratic model at */
2166 /*     the last three interpolation points compare favourably with predictions */
2167 /*     of likely improvements to the model within distance HALF*RHO of XOPT. */
2168
2169 /* Computing MAX */
2170         d__1 = max(diffa,diffb);
2171         errbig = max(d__1,diffc);
2172         frhosq = rho * .125 * rho;
2173         if (crvmin > zero && errbig > frhosq * crvmin) {
2174             goto L650;
2175         }
2176         bdtol = errbig / rho;
2177         i__1 = *n;
2178         for (j = 1; j <= i__1; ++j) {
2179             bdtest = bdtol;
2180             if (xnew[j] == sl[j]) {
2181                 bdtest = w[j];
2182             }
2183             if (xnew[j] == su[j]) {
2184                 bdtest = -w[j];
2185             }
2186             if (bdtest < bdtol) {
2187                 curv = hq[(j + j * j) / 2];
2188                 i__2 = *npt;
2189                 for (k = 1; k <= i__2; ++k) {
2190 /* L70: */
2191 /* Computing 2nd power */
2192                     d__1 = xpt[k + j * xpt_dim1];
2193                     curv += pq[k] * (d__1 * d__1);
2194                 }
2195                 bdtest += half * curv * rho;
2196                 if (bdtest < bdtol) {
2197                     goto L650;
2198                 }
2199             }
2200 /* L80: */
2201         }
2202         goto L680;
2203     }
2204     ++ntrits;
2205
2206 /*     Severe cancellation is likely to occur if XOPT is too far from XBASE. */
2207 /*     If the following test holds, then XBASE is shifted so that XOPT becomes */
2208 /*     zero. The appropriate changes are made to BMAT and to the second */
2209 /*     derivatives of the current model, beginning with the changes to BMAT */
2210 /*     that do not depend on ZMAT. VLAG is used temporarily for working space. */
2211
2212 L90:
2213     if (dsq <= xoptsq * .001) {
2214         fracsq = xoptsq * .25;
2215         sumpq = zero;
2216         i__1 = *npt;
2217         for (k = 1; k <= i__1; ++k) {
2218             sumpq += pq[k];
2219             sum = -half * xoptsq;
2220             i__2 = *n;
2221             for (i__ = 1; i__ <= i__2; ++i__) {
2222 /* L100: */
2223                 sum += xpt[k + i__ * xpt_dim1] * xopt[i__];
2224             }
2225             w[*npt + k] = sum;
2226             temp = fracsq - half * sum;
2227             i__2 = *n;
2228             for (i__ = 1; i__ <= i__2; ++i__) {
2229                 w[i__] = bmat[k + i__ * bmat_dim1];
2230                 vlag[i__] = sum * xpt[k + i__ * xpt_dim1] + temp * xopt[i__];
2231                 ip = *npt + i__;
2232                 i__3 = i__;
2233                 for (j = 1; j <= i__3; ++j) {
2234 /* L110: */
2235                     bmat[ip + j * bmat_dim1] = bmat[ip + j * bmat_dim1] + w[
2236                             i__] * vlag[j] + vlag[i__] * w[j];
2237                 }
2238             }
2239         }
2240
2241 /*     Then the revisions of BMAT that depend on ZMAT are calculated. */
2242
2243         i__3 = nptm;
2244         for (jj = 1; jj <= i__3; ++jj) {
2245             sumz = zero;
2246             sumw = zero;
2247             i__2 = *npt;
2248             for (k = 1; k <= i__2; ++k) {
2249                 sumz += zmat[k + jj * zmat_dim1];
2250                 vlag[k] = w[*npt + k] * zmat[k + jj * zmat_dim1];
2251 /* L120: */
2252                 sumw += vlag[k];
2253             }
2254             i__2 = *n;
2255             for (j = 1; j <= i__2; ++j) {
2256                 sum = (fracsq * sumz - half * sumw) * xopt[j];
2257                 i__1 = *npt;
2258                 for (k = 1; k <= i__1; ++k) {
2259 /* L130: */
2260                     sum += vlag[k] * xpt[k + j * xpt_dim1];
2261                 }
2262                 w[j] = sum;
2263                 i__1 = *npt;
2264                 for (k = 1; k <= i__1; ++k) {
2265 /* L140: */
2266                     bmat[k + j * bmat_dim1] += sum * zmat[k + jj * zmat_dim1];
2267                 }
2268             }
2269             i__1 = *n;
2270             for (i__ = 1; i__ <= i__1; ++i__) {
2271                 ip = i__ + *npt;
2272                 temp = w[i__];
2273                 i__2 = i__;
2274                 for (j = 1; j <= i__2; ++j) {
2275 /* L150: */
2276                     bmat[ip + j * bmat_dim1] += temp * w[j];
2277                 }
2278             }
2279         }
2280
2281 /*     The following instructions complete the shift, including the changes */
2282 /*     to the second derivative parameters of the quadratic model. */
2283
2284         ih = 0;
2285         i__2 = *n;
2286         for (j = 1; j <= i__2; ++j) {
2287             w[j] = -half * sumpq * xopt[j];
2288             i__1 = *npt;
2289             for (k = 1; k <= i__1; ++k) {
2290                 w[j] += pq[k] * xpt[k + j * xpt_dim1];
2291 /* L160: */
2292                 xpt[k + j * xpt_dim1] -= xopt[j];
2293             }
2294             i__1 = j;
2295             for (i__ = 1; i__ <= i__1; ++i__) {
2296                 ++ih;
2297                 hq[ih] = hq[ih] + w[i__] * xopt[j] + xopt[i__] * w[j];
2298 /* L170: */
2299                 bmat[*npt + i__ + j * bmat_dim1] = bmat[*npt + j + i__ * 
2300                         bmat_dim1];
2301             }
2302         }
2303         i__1 = *n;
2304         for (i__ = 1; i__ <= i__1; ++i__) {
2305             xbase[i__] += xopt[i__];
2306             xnew[i__] -= xopt[i__];
2307             sl[i__] -= xopt[i__];
2308             su[i__] -= xopt[i__];
2309 /* L180: */
2310             xopt[i__] = zero;
2311         }
2312         xoptsq = zero;
2313     }
2314     if (ntrits == 0) {
2315         goto L210;
2316     }
2317     goto L230;
2318
2319 /*     XBASE is also moved to XOPT by a call of RESCUE. This calculation is */
2320 /*     more expensive than the previous shift, because new matrices BMAT and */
2321 /*     ZMAT are generated from scratch, which may include the replacement of */
2322 /*     interpolation points whose positions seem to be causing near linear */
2323 /*     dependence in the interpolation conditions. Therefore RESCUE is called */
2324 /*     only if rounding errors have reduced by at least a factor of two the */
2325 /*     denominator of the formula for updating the H matrix. It provides a */
2326 /*     useful safeguard, but is not invoked in most applications of BOBYQA. */
2327
2328 L190:
2329     nfsav = stop->nevals;
2330     kbase = kopt;
2331     rc2 = rescue_(n, npt, &xl[1], &xu[1], 
2332                   stop, calfun, calfun_data,
2333                   &xbase[1], &xpt[xpt_offset], &fval[1], &xopt[1], &gopt[1],
2334                   &hq[1], &pq[1], &bmat[bmat_offset], &zmat[zmat_offset], ndim,
2335                   &sl[1], &su[1], &delta, &kopt, &vlag[1],
2336                   &w[1], &w[*n + np], &w[*ndim + np]);
2337
2338 /*     XOPT is updated now in case the branch below to label 720 is taken. */
2339 /*     Any updating of GOPT occurs after the branch below to label 20, which */
2340 /*     leads to a trust region iteration as does the branch to label 60. */
2341
2342     xoptsq = zero;
2343     if (kopt != kbase) {
2344         i__1 = *n;
2345         for (i__ = 1; i__ <= i__1; ++i__) {
2346             xopt[i__] = xpt[kopt + i__ * xpt_dim1];
2347 /* L200: */
2348 /* Computing 2nd power */
2349             d__1 = xopt[i__];
2350             xoptsq += d__1 * d__1;
2351         }
2352     }
2353     if (rc2 != NLOPT_SUCCESS) { 
2354       rc = rc2;
2355       goto L720; 
2356     }
2357     nresc = stop->nevals;
2358     if (nfsav < stop->nevals) {
2359         nfsav = stop->nevals;
2360         goto L20;
2361     }
2362     if (ntrits > 0) {
2363         goto L60;
2364     }
2365
2366 /*     Pick two alternative vectors of variables, relative to XBASE, that */
2367 /*     are suitable as new positions of the KNEW-th interpolation point. */
2368 /*     Firstly, XNEW is set to the point on a line through XOPT and another */
2369 /*     interpolation point that minimizes the predicted value of the next */
2370 /*     denominator, subject to ||XNEW - XOPT|| .LEQ. ADELT and to the SL */
2371 /*     and SU bounds. Secondly, XALT is set to the best feasible point on */
2372 /*     a constrained version of the Cauchy step of the KNEW-th Lagrange */
2373 /*     function, the corresponding value of the square of this function */
2374 /*     being returned in CAUCHY. The choice between these alternatives is */
2375 /*     going to be made when the denominator is calculated. */
2376
2377 L210:
2378     altmov_(n, npt, &xpt[xpt_offset], &xopt[1], &bmat[bmat_offset], &zmat[
2379             zmat_offset], ndim, &sl[1], &su[1], &kopt, &knew, &adelt, &xnew[1]
2380             , &xalt[1], &alpha, &cauchy, &w[1], &w[np], &w[*ndim + 1]);
2381     i__1 = *n;
2382     for (i__ = 1; i__ <= i__1; ++i__) {
2383 /* L220: */
2384         d__[i__] = xnew[i__] - xopt[i__];
2385     }
2386
2387 /*     Calculate VLAG and BETA for the current choice of D. The scalar */
2388 /*     product of D with XPT(K,.) is going to be held in W(NPT+K) for */
2389 /*     use when VQUAD is calculated. */
2390
2391 L230:
2392     i__1 = *npt;
2393     for (k = 1; k <= i__1; ++k) {
2394         suma = zero;
2395         sumb = zero;
2396         sum = zero;
2397         i__2 = *n;
2398         for (j = 1; j <= i__2; ++j) {
2399             suma += xpt[k + j * xpt_dim1] * d__[j];
2400             sumb += xpt[k + j * xpt_dim1] * xopt[j];
2401 /* L240: */
2402             sum += bmat[k + j * bmat_dim1] * d__[j];
2403         }
2404         w[k] = suma * (half * suma + sumb);
2405         vlag[k] = sum;
2406 /* L250: */
2407         w[*npt + k] = suma;
2408     }
2409     beta = zero;
2410     i__1 = nptm;
2411     for (jj = 1; jj <= i__1; ++jj) {
2412         sum = zero;
2413         i__2 = *npt;
2414         for (k = 1; k <= i__2; ++k) {
2415 /* L260: */
2416             sum += zmat[k + jj * zmat_dim1] * w[k];
2417         }
2418         beta -= sum * sum;
2419         i__2 = *npt;
2420         for (k = 1; k <= i__2; ++k) {
2421 /* L270: */
2422             vlag[k] += sum * zmat[k + jj * zmat_dim1];
2423         }
2424     }
2425     dsq = zero;
2426     bsum = zero;
2427     dx = zero;
2428     i__2 = *n;
2429     for (j = 1; j <= i__2; ++j) {
2430 /* Computing 2nd power */
2431         d__1 = d__[j];
2432         dsq += d__1 * d__1;
2433         sum = zero;
2434         i__1 = *npt;
2435         for (k = 1; k <= i__1; ++k) {
2436 /* L280: */
2437             sum += w[k] * bmat[k + j * bmat_dim1];
2438         }
2439         bsum += sum * d__[j];
2440         jp = *npt + j;
2441         i__1 = *n;
2442         for (i__ = 1; i__ <= i__1; ++i__) {
2443 /* L290: */
2444             sum += bmat[jp + i__ * bmat_dim1] * d__[i__];
2445         }
2446         vlag[jp] = sum;
2447         bsum += sum * d__[j];
2448 /* L300: */
2449         dx += d__[j] * xopt[j];
2450     }
2451     beta = dx * dx + dsq * (xoptsq + dx + dx + half * dsq) + beta - bsum;
2452     vlag[kopt] += one;
2453
2454 /*     If NTRITS is zero, the denominator may be increased by replacing */
2455 /*     the step D of ALTMOV by a Cauchy step. Then RESCUE may be called if */
2456 /*     rounding errors have damaged the chosen denominator. */
2457
2458     if (ntrits == 0) {
2459 /* Computing 2nd power */
2460         d__1 = vlag[knew];
2461         denom = d__1 * d__1 + alpha * beta;
2462         if (denom < cauchy && cauchy > zero) {
2463             i__2 = *n;
2464             for (i__ = 1; i__ <= i__2; ++i__) {
2465                 xnew[i__] = xalt[i__];
2466 /* L310: */
2467                 d__[i__] = xnew[i__] - xopt[i__];
2468             }
2469             cauchy = zero;
2470             goto L230;
2471         }
2472 /* Computing 2nd power */
2473         d__1 = vlag[knew];
2474         if (denom <= half * (d__1 * d__1)) {
2475             if (stop->nevals > nresc) {
2476                 goto L190;
2477             }
2478             /* Return from BOBYQA because of much cancellation in a
2479                denominator. */
2480             rc = NLOPT_ROUNDOFF_LIMITED;
2481             goto L720;
2482         }
2483
2484 /*     Alternatively, if NTRITS is positive, then set KNEW to the index of */
2485 /*     the next interpolation point to be deleted to make room for a trust */
2486 /*     region step. Again RESCUE may be called if rounding errors have damaged */
2487 /*     the chosen denominator, which is the reason for attempting to select */
2488 /*     KNEW before calculating the next value of the objective function. */
2489
2490     } else {
2491         delsq = delta * delta;
2492         scaden = zero;
2493         biglsq = zero;
2494         knew = 0;
2495         i__2 = *npt;
2496         for (k = 1; k <= i__2; ++k) {
2497             if (k == kopt) {
2498                 goto L350;
2499             }
2500             hdiag = zero;
2501             i__1 = nptm;
2502             for (jj = 1; jj <= i__1; ++jj) {
2503 /* L330: */
2504 /* Computing 2nd power */
2505                 d__1 = zmat[k + jj * zmat_dim1];
2506                 hdiag += d__1 * d__1;
2507             }
2508 /* Computing 2nd power */
2509             d__1 = vlag[k];
2510             den = beta * hdiag + d__1 * d__1;
2511             distsq = zero;
2512             i__1 = *n;
2513             for (j = 1; j <= i__1; ++j) {
2514 /* L340: */
2515 /* Computing 2nd power */
2516                 d__1 = xpt[k + j * xpt_dim1] - xopt[j];
2517                 distsq += d__1 * d__1;
2518             }
2519 /* Computing MAX */
2520 /* Computing 2nd power */
2521             d__3 = distsq / delsq;
2522             d__1 = one, d__2 = d__3 * d__3;
2523             temp = max(d__1,d__2);
2524             if (temp * den > scaden) {
2525                 scaden = temp * den;
2526                 knew = k;
2527                 denom = den;
2528             }
2529 /* Computing MAX */
2530 /* Computing 2nd power */
2531             d__3 = vlag[k];
2532             d__1 = biglsq, d__2 = temp * (d__3 * d__3);
2533             biglsq = max(d__1,d__2);
2534 L350:
2535             ;
2536         }
2537         if (scaden <= half * biglsq) {
2538             if (stop->nevals > nresc) {
2539                 goto L190;
2540             }
2541             /* Return from BOBYQA because of much cancellation in a
2542                denominator. */
2543             rc = NLOPT_ROUNDOFF_LIMITED;
2544             goto L720;
2545         }
2546     }
2547
2548 /*     Put the variables for the next calculation of the objective function */
2549 /*       in XNEW, with any adjustments for the bounds. */
2550
2551
2552 /*     Calculate the value of the objective function at XBASE+XNEW, unless */
2553 /*       the limit on the number of calculations of F has been reached. */
2554
2555 L360:
2556     i__2 = *n;
2557     for (i__ = 1; i__ <= i__2; ++i__) {
2558 /* Computing MIN */
2559 /* Computing MAX */
2560         d__3 = xl[i__], d__4 = xbase[i__] + xnew[i__];
2561         d__1 = max(d__3,d__4), d__2 = xu[i__];
2562         x[i__] = min(d__1,d__2);
2563         if (xnew[i__] == sl[i__]) {
2564             x[i__] = xl[i__];
2565         }
2566         if (xnew[i__] == su[i__]) {
2567             x[i__] = xu[i__];
2568         }
2569 /* L380: */
2570     }
2571
2572     if (nlopt_stop_evals(stop)) rc = NLOPT_MAXEVAL_REACHED;
2573     else if (nlopt_stop_time(stop)) rc = NLOPT_MAXTIME_REACHED;
2574     if (rc != NLOPT_SUCCESS) goto L720;
2575
2576     stop->nevals++;
2577     f = calfun(*n, &x[1], calfun_data);
2578     if (ntrits == -1) {
2579         fsave = f;
2580         rc = NLOPT_XTOL_REACHED;
2581         if (fsave < fval[kopt]) { *minf = f; return rc; }
2582         goto L720;
2583     }
2584
2585     if (f < stop->minf_max) {
2586       *minf = f;
2587       return NLOPT_MINF_MAX_REACHED;
2588     }
2589
2590 /*     Use the quadratic model to predict the change in F due to the step D, */
2591 /*       and set DIFF to the error of this prediction. */
2592
2593     fopt = fval[kopt];
2594     vquad = zero;
2595     ih = 0;
2596     i__2 = *n;
2597     for (j = 1; j <= i__2; ++j) {
2598         vquad += d__[j] * gopt[j];
2599         i__1 = j;
2600         for (i__ = 1; i__ <= i__1; ++i__) {
2601             ++ih;
2602             temp = d__[i__] * d__[j];
2603             if (i__ == j) {
2604                 temp = half * temp;
2605             }
2606 /* L410: */
2607             vquad += hq[ih] * temp;
2608         }
2609     }
2610     i__1 = *npt;
2611     for (k = 1; k <= i__1; ++k) {
2612 /* L420: */
2613 /* Computing 2nd power */
2614         d__1 = w[*npt + k];
2615         vquad += half * pq[k] * (d__1 * d__1);
2616     }
2617     diff = f - fopt - vquad;
2618     diffc = diffb;
2619     diffb = diffa;
2620     diffa = fabs(diff);
2621     if (dnorm > rho) {
2622         nfsav = stop->nevals;
2623     }
2624
2625 /*     Pick the next value of DELTA after a trust region step. */
2626
2627     if (ntrits > 0) {
2628         if (vquad >= zero) {
2629           /* Return from BOBYQA because a trust region step has failed
2630              to reduce Q. */
2631           rc = NLOPT_ROUNDOFF_LIMITED; /* or FTOL_REACHED? */
2632           goto L720;
2633         }
2634         ratio = (f - fopt) / vquad;
2635         if (ratio <= tenth) {
2636 /* Computing MIN */
2637             d__1 = half * delta;
2638             delta = min(d__1,dnorm);
2639         } else if (ratio <= .7) {
2640 /* Computing MAX */
2641             d__1 = half * delta;
2642             delta = max(d__1,dnorm);
2643         } else {
2644 /* Computing MAX */
2645             d__1 = half * delta, d__2 = dnorm + dnorm;
2646             delta = max(d__1,d__2);
2647         }
2648         if (delta <= rho * 1.5) {
2649             delta = rho;
2650         }
2651
2652 /*     Recalculate KNEW and DENOM if the new F is less than FOPT. */
2653
2654         if (f < fopt) {
2655             ksav = knew;
2656             densav = denom;
2657             delsq = delta * delta;
2658             scaden = zero;
2659             biglsq = zero;
2660             knew = 0;
2661             i__1 = *npt;
2662             for (k = 1; k <= i__1; ++k) {
2663                 hdiag = zero;
2664                 i__2 = nptm;
2665                 for (jj = 1; jj <= i__2; ++jj) {
2666 /* L440: */
2667 /* Computing 2nd power */
2668                     d__1 = zmat[k + jj * zmat_dim1];
2669                     hdiag += d__1 * d__1;
2670                 }
2671 /* Computing 2nd power */
2672                 d__1 = vlag[k];
2673                 den = beta * hdiag + d__1 * d__1;
2674                 distsq = zero;
2675                 i__2 = *n;
2676                 for (j = 1; j <= i__2; ++j) {
2677 /* L450: */
2678 /* Computing 2nd power */
2679                     d__1 = xpt[k + j * xpt_dim1] - xnew[j];
2680                     distsq += d__1 * d__1;
2681                 }
2682 /* Computing MAX */
2683 /* Computing 2nd power */
2684                 d__3 = distsq / delsq;
2685                 d__1 = one, d__2 = d__3 * d__3;
2686                 temp = max(d__1,d__2);
2687                 if (temp * den > scaden) {
2688                     scaden = temp * den;
2689                     knew = k;
2690                     denom = den;
2691                 }
2692 /* L460: */
2693 /* Computing MAX */
2694 /* Computing 2nd power */
2695                 d__3 = vlag[k];
2696                 d__1 = biglsq, d__2 = temp * (d__3 * d__3);
2697                 biglsq = max(d__1,d__2);
2698             }
2699             if (scaden <= half * biglsq) {
2700                 knew = ksav;
2701                 denom = densav;
2702             }
2703         }
2704     }
2705
2706 /*     Update BMAT and ZMAT, so that the KNEW-th interpolation point can be */
2707 /*     moved. Also update the second derivative terms of the model. */
2708
2709     update_(n, npt, &bmat[bmat_offset], &zmat[zmat_offset], ndim, &vlag[1], &
2710             beta, &denom, &knew, &w[1]);
2711     ih = 0;
2712     pqold = pq[knew];
2713     pq[knew] = zero;
2714     i__1 = *n;
2715     for (i__ = 1; i__ <= i__1; ++i__) {
2716         temp = pqold * xpt[knew + i__ * xpt_dim1];
2717         i__2 = i__;
2718         for (j = 1; j <= i__2; ++j) {
2719             ++ih;
2720 /* L470: */
2721             hq[ih] += temp * xpt[knew + j * xpt_dim1];
2722         }
2723     }
2724     i__2 = nptm;
2725     for (jj = 1; jj <= i__2; ++jj) {
2726         temp = diff * zmat[knew + jj * zmat_dim1];
2727         i__1 = *npt;
2728         for (k = 1; k <= i__1; ++k) {
2729 /* L480: */
2730             pq[k] += temp * zmat[k + jj * zmat_dim1];
2731         }
2732     }
2733
2734 /*     Include the new interpolation point, and make the changes to GOPT at */
2735 /*     the old XOPT that are caused by the updating of the quadratic model. */
2736
2737     fval[knew] = f;
2738     i__1 = *n;
2739     for (i__ = 1; i__ <= i__1; ++i__) {
2740         xpt[knew + i__ * xpt_dim1] = xnew[i__];
2741 /* L490: */
2742         w[i__] = bmat[knew + i__ * bmat_dim1];
2743     }
2744     i__1 = *npt;
2745     for (k = 1; k <= i__1; ++k) {
2746         suma = zero;
2747         i__2 = nptm;
2748         for (jj = 1; jj <= i__2; ++jj) {
2749 /* L500: */
2750             suma += zmat[knew + jj * zmat_dim1] * zmat[k + jj * zmat_dim1];
2751         }
2752         if (nlopt_isinf(suma)) {
2753           /* SGJ: detect singularity here (happend if we run
2754              for too many iterations) ... is there another way to recover? */
2755           rc = NLOPT_ROUNDOFF_LIMITED;
2756           goto L720;
2757         }
2758         sumb = zero;
2759         i__2 = *n;
2760         for (j = 1; j <= i__2; ++j) {
2761 /* L510: */
2762             sumb += xpt[k + j * xpt_dim1] * xopt[j];
2763         }
2764         temp = suma * sumb;
2765         i__2 = *n;
2766         for (i__ = 1; i__ <= i__2; ++i__) {
2767 /* L520: */
2768             w[i__] += temp * xpt[k + i__ * xpt_dim1];
2769         }
2770     }
2771     i__2 = *n;
2772     for (i__ = 1; i__ <= i__2; ++i__) {
2773 /* L530: */
2774         gopt[i__] += diff * w[i__];
2775     }
2776
2777 /*     Update XOPT, GOPT and KOPT if the new calculated F is less than FOPT. */
2778
2779     if (f < fopt) {
2780         kopt = knew;
2781         xoptsq = zero;
2782         ih = 0;
2783         i__2 = *n;
2784         for (j = 1; j <= i__2; ++j) {
2785             xopt[j] = xnew[j];
2786 /* Computing 2nd power */
2787             d__1 = xopt[j];
2788             xoptsq += d__1 * d__1;
2789             i__1 = j;
2790             for (i__ = 1; i__ <= i__1; ++i__) {
2791                 ++ih;
2792                 if (i__ < j) {
2793                     gopt[j] += hq[ih] * d__[i__];
2794                 }
2795 /* L540: */
2796                 gopt[i__] += hq[ih] * d__[j];
2797             }
2798         }
2799         i__1 = *npt;
2800         for (k = 1; k <= i__1; ++k) {
2801             temp = zero;
2802             i__2 = *n;
2803             for (j = 1; j <= i__2; ++j) {
2804 /* L550: */
2805                 temp += xpt[k + j * xpt_dim1] * d__[j];
2806             }
2807             temp = pq[k] * temp;
2808             i__2 = *n;
2809             for (i__ = 1; i__ <= i__2; ++i__) {
2810 /* L560: */
2811                 gopt[i__] += temp * xpt[k + i__ * xpt_dim1];
2812             }
2813         }
2814         if (nlopt_stop_ftol(stop, f, fopt)) {
2815              rc = NLOPT_FTOL_REACHED;
2816              goto L720;
2817         }
2818     }
2819
2820 /*     Calculate the parameters of the least Frobenius norm interpolant to */
2821 /*     the current data, the gradient of this interpolant at XOPT being put */
2822 /*     into VLAG(NPT+I), I=1,2,...,N. */
2823
2824     if (ntrits > 0) {
2825         i__2 = *npt;
2826         for (k = 1; k <= i__2; ++k) {
2827             vlag[k] = fval[k] - fval[kopt];
2828 /* L570: */
2829             w[k] = zero;
2830         }
2831         i__2 = nptm;
2832         for (j = 1; j <= i__2; ++j) {
2833             sum = zero;
2834             i__1 = *npt;
2835             for (k = 1; k <= i__1; ++k) {
2836 /* L580: */
2837                 sum += zmat[k + j * zmat_dim1] * vlag[k];
2838             }
2839             i__1 = *npt;
2840             for (k = 1; k <= i__1; ++k) {
2841 /* L590: */
2842                 w[k] += sum * zmat[k + j * zmat_dim1];
2843             }
2844         }
2845         i__1 = *npt;
2846         for (k = 1; k <= i__1; ++k) {
2847             sum = zero;
2848             i__2 = *n;
2849             for (j = 1; j <= i__2; ++j) {
2850 /* L600: */
2851                 sum += xpt[k + j * xpt_dim1] * xopt[j];
2852             }
2853             w[k + *npt] = w[k];
2854 /* L610: */
2855             w[k] = sum * w[k];
2856         }
2857         gqsq = zero;
2858         gisq = zero;
2859         i__1 = *n;
2860         for (i__ = 1; i__ <= i__1; ++i__) {
2861             sum = zero;
2862             i__2 = *npt;
2863             for (k = 1; k <= i__2; ++k) {
2864 /* L620: */
2865                 sum = sum + bmat[k + i__ * bmat_dim1] * vlag[k] + xpt[k + i__ 
2866                         * xpt_dim1] * w[k];
2867             }
2868             if (xopt[i__] == sl[i__]) {
2869 /* Computing MIN */
2870                 d__2 = zero, d__3 = gopt[i__];
2871 /* Computing 2nd power */
2872                 d__1 = min(d__2,d__3);
2873                 gqsq += d__1 * d__1;
2874 /* Computing 2nd power */
2875                 d__1 = min(zero,sum);
2876                 gisq += d__1 * d__1;
2877             } else if (xopt[i__] == su[i__]) {
2878 /* Computing MAX */
2879                 d__2 = zero, d__3 = gopt[i__];
2880 /* Computing 2nd power */
2881                 d__1 = max(d__2,d__3);
2882                 gqsq += d__1 * d__1;
2883 /* Computing 2nd power */
2884                 d__1 = max(zero,sum);
2885                 gisq += d__1 * d__1;
2886             } else {
2887 /* Computing 2nd power */
2888                 d__1 = gopt[i__];
2889                 gqsq += d__1 * d__1;
2890                 gisq += sum * sum;
2891             }
2892 /* L630: */
2893             vlag[*npt + i__] = sum;
2894         }
2895
2896 /*     Test whether to replace the new quadratic model by the least Frobenius */
2897 /*     norm interpolant, making the replacement if the test is satisfied. */
2898
2899         ++itest;
2900         if (gqsq < ten * gisq) {
2901             itest = 0;
2902         }
2903         if (itest >= 3) {
2904             i__1 = max(*npt,nh);
2905             for (i__ = 1; i__ <= i__1; ++i__) {
2906                 if (i__ <= *n) {
2907                     gopt[i__] = vlag[*npt + i__];
2908                 }
2909                 if (i__ <= *npt) {
2910                     pq[i__] = w[*npt + i__];
2911                 }
2912                 if (i__ <= nh) {
2913                     hq[i__] = zero;
2914                 }
2915                 itest = 0;
2916 /* L640: */
2917             }
2918         }
2919     }
2920
2921 /*     If a trust region step has provided a sufficient decrease in F, then */
2922 /*     branch for another trust region calculation. The case NTRITS=0 occurs */
2923 /*     when the new interpolation point was reached by an alternative step. */
2924
2925     if (ntrits == 0) {
2926         goto L60;
2927     }
2928     if (f <= fopt + tenth * vquad) {
2929         goto L60;
2930     }
2931
2932 /*     Alternatively, find out if the interpolation points are close enough */
2933 /*       to the best point so far. */
2934
2935 /* Computing MAX */
2936 /* Computing 2nd power */
2937     d__3 = two * delta;
2938 /* Computing 2nd power */
2939     d__4 = ten * rho;
2940     d__1 = d__3 * d__3, d__2 = d__4 * d__4;
2941     distsq = max(d__1,d__2);
2942 L650:
2943     knew = 0;
2944     i__1 = *npt;
2945     for (k = 1; k <= i__1; ++k) {
2946         sum = zero;
2947         i__2 = *n;
2948         for (j = 1; j <= i__2; ++j) {
2949 /* L660: */
2950 /* Computing 2nd power */
2951             d__1 = xpt[k + j * xpt_dim1] - xopt[j];
2952             sum += d__1 * d__1;
2953         }
2954         if (sum > distsq) {
2955             knew = k;
2956             distsq = sum;
2957         }
2958 /* L670: */
2959     }
2960
2961 /*     If KNEW is positive, then ALTMOV finds alternative new positions for */
2962 /*     the KNEW-th interpolation point within distance ADELT of XOPT. It is */
2963 /*     reached via label 90. Otherwise, there is a branch to label 60 for */
2964 /*     another trust region iteration, unless the calculations with the */
2965 /*     current RHO are complete. */
2966
2967     if (knew > 0) {
2968         dist = sqrt(distsq);
2969         if (ntrits == -1) {
2970 /* Computing MIN */
2971             d__1 = tenth * delta, d__2 = half * dist;
2972             delta = min(d__1,d__2);
2973             if (delta <= rho * 1.5) {
2974                 delta = rho;
2975             }
2976         }
2977         ntrits = 0;
2978 /* Computing MAX */
2979 /* Computing MIN */
2980         d__2 = tenth * dist;
2981         d__1 = min(d__2,delta);
2982         adelt = max(d__1,rho);
2983         dsq = adelt * adelt;
2984         goto L90;
2985     }
2986     if (ntrits == -1) {
2987         goto L680;
2988     }
2989     if (ratio > zero) {
2990         goto L60;
2991     }
2992     if (max(delta,dnorm) > rho) {
2993         goto L60;
2994     }
2995
2996 /*     The calculations with the current value of RHO are complete. Pick the */
2997 /*       next values of RHO and DELTA. */
2998
2999 L680:
3000     if (rho > *rhoend) {
3001         delta = half * rho;
3002         ratio = rho / *rhoend;
3003         if (ratio <= 16.) {
3004             rho = *rhoend;
3005         } else if (ratio <= 250.) {
3006             rho = sqrt(ratio) * *rhoend;
3007         } else {
3008             rho = tenth * rho;
3009         }
3010         delta = max(delta,rho);
3011         ntrits = 0;
3012         nfsav = stop->nevals;
3013         goto L60;
3014     }
3015
3016 /*     Return from the calculation, after another Newton-Raphson step, if */
3017 /*       it is too short to have been tried before. */
3018
3019     if (ntrits == -1) {
3020         goto L360;
3021     }
3022 L720:
3023     /* originally: if (fval[kopt] <= fsave) -- changed by SGJ, since
3024        this seems like a slight optimization to not update x[]
3025        unnecessarily, at the expense of possibly not returning the
3026        best x[] found so far if the algorithm is stopped suddenly
3027        (e.g. runs out of time) ... it seems safer to execute this
3028        unconditionally, and the efficiency loss seems negligible. */
3029     {
3030         i__1 = *n;
3031         for (i__ = 1; i__ <= i__1; ++i__) {
3032 /* Computing MIN */
3033 /* Computing MAX */
3034             d__3 = xl[i__], d__4 = xbase[i__] + xopt[i__];
3035             d__1 = max(d__3,d__4), d__2 = xu[i__];
3036             x[i__] = min(d__1,d__2);
3037             if (xopt[i__] == sl[i__]) {
3038                 x[i__] = xl[i__];
3039             }
3040             if (xopt[i__] == su[i__]) {
3041                 x[i__] = xu[i__];
3042             }
3043 /* L730: */
3044         }
3045         f = fval[kopt];
3046     }
3047     *minf = f;
3048     return rc;
3049 } /* bobyqb_ */
3050
3051 /**************************************************************************/
3052
3053 nlopt_result bobyqa(int n, int npt, double *x, 
3054                     const double *xl, const double *xu, double rhobeg, 
3055                     nlopt_stopping *stop, double *minf,
3056                     bobyqa_func calfun, void *calfun_data)
3057 {
3058     /* System generated locals */
3059     int i__1;
3060     double d__1, d__2;
3061
3062     /* Local variables */
3063     int j, id, np, iw, igo, ihq, ixb, ixa, ifv, isl, jsl, ipq, ivl, ixn, 
3064             ixo, ixp, isu, jsu, ndim;
3065     double temp, zero;
3066     int ibmat, izmat;
3067
3068     double rhoend;
3069     double *w;
3070     nlopt_result ret;
3071
3072 /* SGJ, 2009: compute rhoend from NLopt stop info */
3073     rhoend = stop->xtol_rel * (rhobeg);
3074     for (j = 0; j < n; ++j)
3075          if (rhoend < stop->xtol_abs[j])
3076               rhoend = stop->xtol_abs[j];
3077
3078
3079 /*     This subroutine seeks the least value of a function of many variables, */
3080 /*     by applying a trust region method that forms quadratic models by */
3081 /*     interpolation. There is usually some freedom in the interpolation */
3082 /*     conditions, which is taken up by minimizing the Frobenius norm of */
3083 /*     the change to the second derivative of the model, beginning with the */
3084 /*     zero matrix. The values of the variables are constrained by upper and */
3085 /*     lower bounds. The arguments of the subroutine are as follows. */
3086
3087 /*     N must be set to the number of variables and must be at least two. */
3088 /*     NPT is the number of interpolation conditions. Its value must be in */
3089 /*       the interval [N+2,(N+1)(N+2)/2]. Choices that exceed 2*N+1 are not */
3090 /*       recommended. */
3091 /*     Initial values of the variables must be set in X(1),X(2),...,X(N). They */
3092 /*       will be changed to the values that give the least calculated F. */
3093 /*     For I=1,2,...,N, XL(I) and XU(I) must provide the lower and upper */
3094 /*       bounds, respectively, on X(I). The construction of quadratic models */
3095 /*       requires XL(I) to be strictly less than XU(I) for each I. Further, */
3096 /*       the contribution to a model from changes to the I-th variable is */
3097 /*       damaged severely by rounding errors if XU(I)-XL(I) is too small. */
3098 /*     RHOBEG and RHOEND must be set to the initial and final values of a trust */
3099 /*       region radius, so both must be positive with RHOEND no greater than */
3100 /*       RHOBEG. Typically, RHOBEG should be about one tenth of the greatest */
3101 /*       expected change to a variable, while RHOEND should indicate the */
3102 /*       accuracy that is required in the final values of the variables. An */
3103 /*       error return occurs if any of the differences XU(I)-XL(I), I=1,...,N, */
3104 /*       is less than 2*RHOBEG. */
3105 /*     MAXFUN must be set to an upper bound on the number of calls of CALFUN. */
3106 /*     The array W will be used for working space. Its length must be at least */
3107 /*       (NPT+5)*(NPT+N)+3*N*(N+5)/2. */
3108
3109 /*     SUBROUTINE CALFUN (N,X,F) has to be provided by the user. It must set */
3110 /*     F to the value of the objective function for the current values of the */
3111 /*     variables X(1),X(2),...,X(N), which are generated automatically in a */
3112 /*     way that satisfies the bounds given in XL and XU. */
3113
3114 /*     Return if the value of NPT is unacceptable. */
3115
3116     /* Parameter adjustments */
3117     --xu;
3118     --xl;
3119     --x;
3120
3121     /* Function Body */
3122     np = n + 1;
3123     if (npt < n + 2 || npt > (n + 2) * np / 2) {
3124       /* Return from BOBYQA because NPT is not in the required interval */
3125       return NLOPT_INVALID_ARGS;
3126     }
3127
3128 /*     Partition the working space array, so that different parts of it can */
3129 /*     be treated separately during the calculation of BOBYQB. The partition */
3130 /*     requires the first (NPT+2)*(NPT+N)+3*N*(N+5)/2 elements of W plus the */
3131 /*     space that is taken by the last array in the argument list of BOBYQB. */
3132
3133     ndim = npt + n;
3134     ixb = 1;
3135     ixp = ixb + n;
3136     ifv = ixp + n * npt;
3137     ixo = ifv + npt;
3138     igo = ixo + n;
3139     ihq = igo + n;
3140     ipq = ihq + n * np / 2;
3141     ibmat = ipq + npt;
3142     izmat = ibmat + ndim * n;
3143     isl = izmat + npt * (npt - np);
3144     isu = isl + n;
3145     ixn = isu + n;
3146     ixa = ixn + n;
3147     id = ixa + n;
3148     ivl = id + n;
3149     iw = ivl + ndim;
3150
3151     w = (double *) malloc(sizeof(double) * ((npt+5)*(npt+n)+3*n*(n+5)/2));
3152     if (!w) return NLOPT_OUT_OF_MEMORY;
3153     --w;
3154
3155 /*   Return if there is insufficient space between the bounds. Modify the */
3156 /*   initial X if necessary in order to avoid conflicts between the bounds */
3157 /*   and the construction of the first quadratic model. The lower and upper */
3158 /*   bounds on moves from the updated X are set now, in the ISL and ISU */
3159 /*   partitions of W, in order to provide useful and exact information about */
3160 /*   components of X that become within distance RHOBEG from their bounds. */
3161
3162     zero = 0.;
3163     i__1 = n;
3164     for (j = 1; j <= i__1; ++j) {
3165         temp = xu[j] - xl[j];
3166         if (temp < rhobeg + rhobeg) {
3167           /* Return from BOBYQA because one of the differences
3168              XU(I)-XL(I)s is less than 2*RHOBEG. */
3169           free(w+1);
3170           return NLOPT_INVALID_ARGS;
3171         }
3172         jsl = isl + j - 1;
3173         jsu = jsl + n;
3174         w[jsl] = xl[j] - x[j];
3175         w[jsu] = xu[j] - x[j];
3176         if (w[jsl] >= -(rhobeg)) {
3177             if (w[jsl] >= zero) {
3178                 x[j] = xl[j];
3179                 w[jsl] = zero;
3180                 w[jsu] = temp;
3181             } else {
3182                 x[j] = xl[j] + rhobeg;
3183                 w[jsl] = -(rhobeg);
3184 /* Computing MAX */
3185                 d__1 = xu[j] - x[j];
3186                 w[jsu] = max(d__1,rhobeg);
3187             }
3188         } else if (w[jsu] <= rhobeg) {
3189             if (w[jsu] <= zero) {
3190                 x[j] = xu[j];
3191                 w[jsl] = -temp;
3192                 w[jsu] = zero;
3193             } else {
3194                 x[j] = xu[j] - rhobeg;
3195 /* Computing MIN */
3196                 d__1 = xl[j] - x[j], d__2 = -(rhobeg);
3197                 w[jsl] = min(d__1,d__2);
3198                 w[jsu] = rhobeg;
3199             }
3200         }
3201 /* L30: */
3202     }
3203
3204 /*     Make the call of BOBYQB. */
3205
3206     ret = bobyqb_(&n, &npt, &x[1], &xl[1], &xu[1], &rhobeg, &rhoend,
3207                   stop, calfun, calfun_data, minf,
3208                   &w[ixb], &w[ixp], &w[ifv], &w[ixo], &w[igo], &w[ihq], &w[ipq], 
3209                   &w[ibmat], &w[izmat], &ndim, &w[isl], &w[isu], &w[ixn], &w[ixa],
3210                   &w[id], &w[ivl], &w[iw]);
3211     free(w+1);
3212     return ret;
3213 } /* bobyqa_ */
3214