chiark / gitweb /
use HUGE_VAL instead of 1e6 for "infinity" in DIRECT
[nlopt.git] / direct / DIRsubrout.c
1 /* DIRsubrout.f -- translated by f2c (version 20050501).
2
3    f2c output hand-cleaned by SGJ (August 2007).
4 */
5
6 #include <math.h>
7 #include "direct-internal.h"
8
9 /* Table of constant values */
10
11 static integer c__1 = 1;
12 static integer c__32 = 32;
13 static integer c__0 = 0;
14
15 /* +-----------------------------------------------------------------------+ */
16 /* | INTEGER Function DIRGetlevel                                          | */
17 /* | Returns the level of the hyperrectangle. Depending on the value of the| */
18 /* | global variable JONES. IF JONES equals 0, the level is given by       | */
19 /* |               kN + p, where the rectangle has p sides with a length of| */
20 /* |             1/3^(k+1), and N-p sides with a length of 1/3^k.          | */
21 /* | If JONES equals 1, the level is the power of 1/3 of the length of the | */
22 /* | longest side hyperrectangle.                                          | */
23 /* |                                                                       | */
24 /* | On Return :                                                           | */
25 /* |    the maximal length                                                 | */
26 /* |                                                                       | */
27 /* | pos     -- the position of the midpoint in the array length           | */
28 /* | length  -- the array with the dimensions                              | */
29 /* | maxfunc -- the leading dimension of length                            | */
30 /* | n     -- the dimension of the problem                                  | */
31 /* |                                                                       | */
32 /* +-----------------------------------------------------------------------+ */
33 integer direct_dirgetlevel_(integer *pos, integer *length, integer *maxfunc, integer 
34         *n, integer jones)
35 {
36     /* System generated locals */
37     integer length_dim1, length_offset, ret_val, i__1;
38
39     /* Local variables */
40     integer i__, k, p, help;
41
42 /* JG 09/15/00 Added variable JONES (see above) */
43     /* Parameter adjustments */
44     length_dim1 = *n;
45     length_offset = 1 + length_dim1;
46     length -= length_offset;
47
48     /* Function Body */
49     if (jones == 0) {
50         help = length[*pos * length_dim1 + 1];
51         k = help;
52         p = 1;
53         i__1 = *n;
54         for (i__ = 2; i__ <= i__1; ++i__) {
55             if (length[i__ + *pos * length_dim1] < k) {
56                 k = length[i__ + *pos * length_dim1];
57             }
58             if (length[i__ + *pos * length_dim1] == help) {
59                 ++p;
60             }
61 /* L100: */
62         }
63         if (k == help) {
64             ret_val = k * *n + *n - p;
65         } else {
66             ret_val = k * *n + p;
67         }
68     } else {
69         help = length[*pos * length_dim1 + 1];
70         i__1 = *n;
71         for (i__ = 2; i__ <= i__1; ++i__) {
72             if (length[i__ + *pos * length_dim1] < help) {
73                 help = length[i__ + *pos * length_dim1];
74             }
75 /* L10: */
76         }
77         ret_val = help;
78     }
79     return ret_val;
80 } /* dirgetlevel_ */
81
82 /* +-----------------------------------------------------------------------+ */
83 /* | Program       : Direct.f (subfile DIRsubrout.f)                       | */
84 /* | Last modified : 07-16-2001                                            | */
85 /* | Written by    : Joerg Gablonsky                                       | */
86 /* | Subroutines used by the algorithm DIRECT.                             | */
87 /* +-----------------------------------------------------------------------+ */
88 /* +-----------------------------------------------------------------------+ */
89 /* |    SUBROUTINE DIRChoose                                               | */
90 /* |    Decide, which is the next sampling point.                          | */
91 /* |    Changed 09/25/00 JG                                                | */
92 /* |         Added maxdiv to call and changed S to size maxdiv.            | */
93 /* |    Changed 01/22/01 JG                                                | */
94 /* |         Added Ifeasiblef to call to keep track if a feasible point has| */
95 /* |         been found.                                                   | */
96 /* |    Changed 07/16/01 JG                                                | */
97 /* |         Changed if statement to prevent run-time errors.              |                                  
98                  | */
99 /* +-----------------------------------------------------------------------+ */
100 /* Subroutine */ void direct_dirchoose_(integer *anchor, integer *s, integer *actdeep,
101          doublereal *f, doublereal *fmin, doublereal epsrel, doublereal epsabs, doublereal *thirds,
102          integer *maxpos, integer *length, integer *maxfunc, integer *maxdeep,
103          integer *maxdiv, integer *n, FILE *logfile,
104         integer *cheat, doublereal *kmax, integer *ifeasiblef, integer jones)
105 {
106     /* System generated locals */
107     integer s_dim1, s_offset, length_dim1, length_offset, i__1;
108
109     /* Local variables */
110     integer i__, j, k;
111     doublereal helplower;
112     integer i___, j___;
113     doublereal helpgreater;
114     integer novaluedeep = 0;
115     doublereal help2;
116     integer novalue;
117
118     /* Parameter adjustments */
119     f -= 3;
120     ++anchor;
121     s_dim1 = *maxdiv;
122     s_offset = 1 + s_dim1;
123     s -= s_offset;
124     length_dim1 = *n;
125     length_offset = 1 + length_dim1;
126     length -= length_offset;
127
128     /* Function Body */
129     helplower = 1e20;
130     helpgreater = 0.;
131     k = 1;
132     if (*ifeasiblef >= 1) {
133         i__1 = *actdeep;
134         for (j = 0; j <= i__1; ++j) {
135             if (anchor[j] > 0) {
136                 s[k + s_dim1] = anchor[j];
137                 s[k + (s_dim1 << 1)] = direct_dirgetlevel_(&s[k + s_dim1], &length[
138                         length_offset], maxfunc, n, jones);
139                 goto L12;
140             }
141 /* L1001: */
142         }
143 L12:
144         ++k;
145         *maxpos = 1;
146         return;
147     } else {
148         i__1 = *actdeep;
149         for (j = 0; j <= i__1; ++j) {
150             if (anchor[j] > 0) {
151                 s[k + s_dim1] = anchor[j];
152                 s[k + (s_dim1 << 1)] = direct_dirgetlevel_(&s[k + s_dim1], &length[
153                         length_offset], maxfunc, n, jones);
154                 ++k;
155             }
156 /* L10: */
157         }
158     }
159     novalue = 0;
160     if (anchor[-1] > 0) {
161         novalue = anchor[-1];
162         novaluedeep = direct_dirgetlevel_(&novalue, &length[length_offset], maxfunc, 
163                 n, jones);
164     }
165     *maxpos = k - 1;
166     i__1 = *maxdeep;
167     for (j = k - 1; j <= i__1; ++j) {
168         s[k + s_dim1] = 0;
169 /* L11: */
170     }
171     for (j = *maxpos; j >= 1; --j) {
172         helplower = 1e20;
173         helpgreater = 0.;
174         j___ = s[j + s_dim1];
175         i__1 = j - 1;
176         for (i__ = 1; i__ <= i__1; ++i__) {
177             i___ = s[i__ + s_dim1];
178 /* +-----------------------------------------------------------------------+ */
179 /* | JG 07/16/01 Changed IF statement into two to prevent run-time errors  | */
180 /* |             which could occur if the compiler checks the second       | */
181 /* |             expression in an .AND. statement although the first       | */
182 /* |             statement is already not true.                            | */
183 /* +-----------------------------------------------------------------------+ */
184             if (i___ > 0 && ! (i__ == j)) {
185                 if (f[(i___ << 1) + 2] <= 1.) {
186                     help2 = thirds[s[i__ + (s_dim1 << 1)]] - thirds[s[j + (
187                             s_dim1 << 1)]];
188                     help2 = (f[(i___ << 1) + 1] - f[(j___ << 1) + 1]) / help2;
189                     if (help2 <= 0.) {
190                          if (logfile)
191                               fprintf(logfile, "thirds > 0, help2 <= 0\n");
192                         goto L60;
193                     }
194                     if (help2 < helplower) {
195                          if (logfile)
196                               fprintf(logfile, "helplower = %g\n", help2);
197                         helplower = help2;
198                     }
199                 }
200             }
201 /* L30: */
202         }
203         i__1 = *maxpos;
204         for (i__ = j + 1; i__ <= i__1; ++i__) {
205             i___ = s[i__ + s_dim1];
206 /* +-----------------------------------------------------------------------+ */
207 /* | JG 07/16/01 Changed IF statement into two to prevent run-time errors  | */
208 /* |             which could occur if the compiler checks the second       | */
209 /* |             expression in an .AND. statement although the first       | */
210 /* |             statement is already not true.                            | */
211 /* +-----------------------------------------------------------------------+ */
212             if (i___ > 0 && ! (i__ == j)) {
213                 if (f[(i___ << 1) + 2] <= 1.) {
214                     help2 = thirds[s[i__ + (s_dim1 << 1)]] - thirds[s[j + (
215                             s_dim1 << 1)]];
216                     help2 = (f[(i___ << 1) + 1] - f[(j___ << 1) + 1]) / help2;
217                     if (help2 <= 0.) {
218                         if (logfile)
219                              fprintf(logfile, "thirds < 0, help2 <= 0\n");
220                         goto L60;
221                     }
222                     if (help2 > helpgreater) {
223                         if (logfile)
224                               fprintf(logfile, "helpgreater = %g\n", help2);
225                         helpgreater = help2;
226                     }
227                 }
228             }
229 /* L31: */
230         }
231         if (helplower > 1e20 && helpgreater > 0.) {
232             helplower = helpgreater;
233             helpgreater += -1.;
234         }
235         if (helpgreater <= helplower) {
236             if (*cheat == 1 && helplower > *kmax) {
237                 helplower = *kmax;
238             }
239             if (f[(j___ << 1) + 1] - helplower * thirds[s[j + (s_dim1 << 1)]] >
240                      MIN(*fmin - epsrel * fabs(*fmin), 
241                          *fmin - epsabs)) {
242                 if (logfile)
243                      fprintf(logfile, "> fmin - epslfminl\n");
244                 goto L60;
245             }
246         } else {
247             if (logfile)
248                  fprintf(logfile, "helpgreater > helplower: %g  %g  %g\n",
249                          helpgreater, helplower, helpgreater - helplower);
250             goto L60;
251         }
252         goto L40;
253 L60:
254         s[j + s_dim1] = 0;
255 L40:
256         ;
257     }
258     if (novalue > 0) {
259         ++(*maxpos);
260         s[*maxpos + s_dim1] = novalue;
261         s[*maxpos + (s_dim1 << 1)] = novaluedeep;
262     }
263 } /* dirchoose_ */
264
265 /* +-----------------------------------------------------------------------+ */
266 /* |    SUBROUTINE DIRDoubleInsert                                         | */
267 /* |      Routine to make sure that if there are several potential optimal | */
268 /* |      hyperrectangles of the same level (i.e. hyperrectangles that have| */
269 /* |      the same level and the same function value at the center), all of| */
270 /* |      them are divided. This is the way as originally described in     | */
271 /* |      Jones et.al.                                                     | */
272 /* | JG 07/16/01 Added errorflag to calling sequence. We check if more     | */
273 /* |             we reach the capacity of the array S. If this happens, we | */
274 /* |             return to the main program with an error.                 | */
275 /* +-----------------------------------------------------------------------+ */
276 /* Subroutine */ void direct_dirdoubleinsert_(integer *anchor, integer *s, integer *
277         maxpos, integer *point, doublereal *f, integer *maxdeep, integer *
278         maxfunc, integer *maxdiv, integer *ierror)
279 {
280     /* System generated locals */
281     integer s_dim1, s_offset, i__1;
282
283     /* Local variables */
284     integer i__, oldmaxpos, pos, help, iflag, actdeep;
285
286 /* +-----------------------------------------------------------------------+ */
287 /* | JG 07/16/01 Added flag to prevent run time-errors on some systems.    | */
288 /* +-----------------------------------------------------------------------+ */
289     /* Parameter adjustments */
290     ++anchor;
291     f -= 3;
292     --point;
293     s_dim1 = *maxdiv;
294     s_offset = 1 + s_dim1;
295     s -= s_offset;
296
297     /* Function Body */
298     oldmaxpos = *maxpos;
299     i__1 = oldmaxpos;
300     for (i__ = 1; i__ <= i__1; ++i__) {
301         if (s[i__ + s_dim1] > 0) {
302             actdeep = s[i__ + (s_dim1 << 1)];
303             help = anchor[actdeep];
304             pos = point[help];
305             iflag = 0;
306 /* +-----------------------------------------------------------------------+ */
307 /* | JG 07/16/01 Added flag to prevent run time-errors on some systems. On | */
308 /* |             some systems the second conditions in an AND statement is | */
309 /* |             evaluated even if the first one is already not true.      | */
310 /* +-----------------------------------------------------------------------+ */
311             while(pos > 0 && iflag == 0) {
312                 if (f[(pos << 1) + 1] - f[(help << 1) + 1] <= 1e-13) {
313                     if (*maxpos < *maxdiv) {
314                         ++(*maxpos);
315                         s[*maxpos + s_dim1] = pos;
316                         s[*maxpos + (s_dim1 << 1)] = actdeep;
317                         pos = point[pos];
318                     } else {
319 /* +-----------------------------------------------------------------------+ */
320 /* | JG 07/16/01 Maximum number of elements possible in S has been reached!| */
321 /* +-----------------------------------------------------------------------+ */
322                         *ierror = -6;
323                         return;
324                     }
325                 } else {
326                     iflag = 1;
327                 }
328             }
329         }
330 /* L10: */
331     }
332 } /* dirdoubleinsert_ */
333
334 /* +-----------------------------------------------------------------------+ */
335 /* | INTEGER Function GetmaxDeep                                           | */
336 /* | function to get the maximal length (1/length) of the n-dimensional    | */
337 /* | rectangle with midpoint pos.                                          | */
338 /* |                                                                       | */
339 /* | On Return :                                                           | */
340 /* |    the maximal length                                                 | */
341 /* |                                                                       | */
342 /* | pos     -- the position of the midpoint in the array length           | */
343 /* | length  -- the array with the dimensions                              | */
344 /* | maxfunc -- the leading dimension of length                            | */
345 /* | n     -- the dimension of the problem                                  | */
346 /* |                                                                       | */
347 /* +-----------------------------------------------------------------------+ */
348 integer direct_dirgetmaxdeep_(integer *pos, integer *length, integer *maxfunc, 
349         integer *n)
350 {
351     /* System generated locals */
352     integer length_dim1, length_offset, i__1, i__2, i__3;
353
354     /* Local variables */
355     integer i__, help;
356
357     /* Parameter adjustments */
358     length_dim1 = *n;
359     length_offset = 1 + length_dim1;
360     length -= length_offset;
361
362     /* Function Body */
363     help = length[*pos * length_dim1 + 1];
364     i__1 = *n;
365     for (i__ = 2; i__ <= i__1; ++i__) {
366 /* Computing MIN */
367         i__2 = help, i__3 = length[i__ + *pos * length_dim1];
368         help = MIN(i__2,i__3);
369 /* L10: */
370     }
371     return help;
372 } /* dirgetmaxdeep_ */
373
374 static integer isinbox_(doublereal *x, doublereal *a, doublereal *b, integer *n, 
375         integer *lmaxdim)
376 {
377     /* System generated locals */
378     integer ret_val, i__1;
379
380     /* Local variables */
381     integer outofbox, i__;
382
383     /* Parameter adjustments */
384     --b;
385     --a;
386     --x;
387
388     /* Function Body */
389     outofbox = 1;
390     i__1 = *n;
391     for (i__ = 1; i__ <= i__1; ++i__) {
392         if (a[i__] > x[i__] || b[i__] < x[i__]) {
393             outofbox = 0;
394             goto L1010;
395         }
396 /* L1000: */
397     }
398 L1010:
399     ret_val = outofbox;
400     return ret_val;
401 } /* isinbox_ */
402
403 /* +-----------------------------------------------------------------------+ */
404 /* | JG Added 09/25/00                                                     | */
405 /* |                                                                       | */
406 /* |                       SUBROUTINE DIRResortlist                        | */
407 /* |                                                                       | */
408 /* | Resort the list so that the infeasible point is in the list with the  | */
409 /* | replaced value.                                                       | */
410 /* +-----------------------------------------------------------------------+ */
411 /* Subroutine */ static void dirresortlist_(integer *replace, integer *anchor, 
412         doublereal *f, integer *point, integer *length, integer *n, integer *
413         maxfunc, integer *maxdim, integer *maxdeep, FILE *logfile,
414                                             integer jones)
415 {
416     /* System generated locals */
417     integer length_dim1, length_offset, i__1;
418
419     /* Local variables */
420     integer i__, l, pos;
421     integer start;
422
423 /* +-----------------------------------------------------------------------+ */
424 /* | Get the length of the hyper rectangle with infeasible mid point and   | */
425 /* | Index of the corresponding list.                                      | */
426 /* +-----------------------------------------------------------------------+ */
427 /* JG 09/25/00 Replaced with DIRgetlevel */
428 /*      l = DIRgetmaxDeep(replace,length,maxfunc,n) */
429     /* Parameter adjustments */
430     --point;
431     f -= 3;
432     length_dim1 = *n;
433     length_offset = 1 + length_dim1;
434     length -= length_offset;
435     ++anchor;
436
437     /* Function Body */
438     l = direct_dirgetlevel_(replace, &length[length_offset], maxfunc, n, jones);
439     start = anchor[l];
440 /* +-----------------------------------------------------------------------+ */
441 /* | If the hyper rectangle with infeasibel midpoint is already the start  | */
442 /* | of the list, give out message, nothing to do.                         | */
443 /* +-----------------------------------------------------------------------+ */
444     if (*replace == start) {
445 /*         write(logfile,*) 'No resorting of list necessarry, since new ', */
446 /*     + 'point is already anchor of list .',l */
447     } else {
448 /* +-----------------------------------------------------------------------+ */
449 /* | Take the hyper rectangle with infeasible midpoint out of the list.    | */
450 /* +-----------------------------------------------------------------------+ */
451         pos = start;
452         i__1 = *maxfunc;
453         for (i__ = 1; i__ <= i__1; ++i__) {
454             if (point[pos] == *replace) {
455                 point[pos] = point[*replace];
456                 goto L20;
457             } else {
458                 pos = point[pos];
459             }
460             if (pos == 0) {
461                 if (logfile)
462                      fprintf(logfile, "Error in DIRREsortlist: "
463                              "We went through the whole list\n"
464                              "and could not find the point to replace!!\n");
465                 goto L20;
466             }
467 /* L10: */
468         }
469 /* +-----------------------------------------------------------------------+ */
470 /* | If the anchor of the list has a higher value than the value of a      | */
471 /* | nearby point, put the infeasible point at the beginning of the list.  | */
472 /* +-----------------------------------------------------------------------+ */
473 L20:
474         if (f[(start << 1) + 1] > f[(*replace << 1) + 1]) {
475             anchor[l] = *replace;
476             point[*replace] = start;
477 /*            write(logfile,*) 'Point is replacing current anchor for ' */
478 /*     +             , 'this list ',l,replace,start */
479         } else {
480 /* +-----------------------------------------------------------------------+ */
481 /* | Insert the point into the list according to its (replaced) function   | */
482 /* | value.                                                                | */
483 /* +-----------------------------------------------------------------------+ */
484             pos = start;
485             i__1 = *maxfunc;
486             for (i__ = 1; i__ <= i__1; ++i__) {
487 /* +-----------------------------------------------------------------------+ */
488 /* | The point has to be added at the end of the list.                     | */
489 /* +-----------------------------------------------------------------------+ */
490                 if (point[pos] == 0) {
491                     point[*replace] = point[pos];
492                     point[pos] = *replace;
493 /*                  write(logfile,*) 'Point is added at the end of the ' */
494 /*     +             , 'list ',l, replace */
495                     goto L40;
496                 } else {
497                     if (f[(point[pos] << 1) + 1] > f[(*replace << 1) + 1]) {
498                         point[*replace] = point[pos];
499                         point[pos] = *replace;
500 /*                     write(logfile,*) 'There are points with a higher ' */
501 /*     +               ,'f-value in the list ',l,replace, pos */
502                         goto L40;
503                     }
504                     pos = point[pos];
505                 }
506 /* L30: */
507             }
508 L40:
509             pos = pos;
510         }
511     }
512 } /* dirresortlist_ */
513
514 /* +-----------------------------------------------------------------------+ */
515 /* | JG Added 09/25/00                                                     | */
516 /* |                       SUBROUTINE DIRreplaceInf                        | */
517 /* |                                                                       | */
518 /* | Find out if there are infeasible points which are near feasible ones. | */
519 /* | If this is the case, replace the function value at the center of the  | */
520 /* | hyper rectangle by the lowest function value of a nearby function.    | */
521 /* +-----------------------------------------------------------------------+ */
522 /* Subroutine */ void direct_dirreplaceinf_(integer *free, integer *freeold, 
523         doublereal *f, doublereal *c__, doublereal *thirds, integer *length, 
524         integer *anchor, integer *point, doublereal *c1, doublereal *c2, 
525         integer *maxfunc, integer *maxdeep, integer *maxdim, integer *n, 
526         FILE *logfile, doublereal *fmax, integer jones)
527 {
528     /* System generated locals */
529     integer c_dim1, c_offset, length_dim1, length_offset, i__1, i__2, i__3;
530     doublereal d__1, d__2;
531
532     /* Local variables */
533     doublereal a[32], b[32];
534     integer i__, j, k, l;
535     doublereal x[32], sidelength;
536     integer help;
537
538 /* +-----------------------------------------------------------------------+ */
539 /* | JG 01/22/01 Added variable to keep track of the maximum value found.  | */
540 /* +-----------------------------------------------------------------------+ */
541     /* Parameter adjustments */
542     --point;
543     f -= 3;
544     ++anchor;
545     length_dim1 = *maxdim;
546     length_offset = 1 + length_dim1;
547     length -= length_offset;
548     c_dim1 = *maxdim;
549     c_offset = 1 + c_dim1;
550     c__ -= c_offset;
551     --c2;
552     --c1;
553
554     /* Function Body */
555     i__1 = *free - 1;
556     for (i__ = 1; i__ <= i__1; ++i__) {
557         if (f[(i__ << 1) + 2] > 0.) {
558 /* +-----------------------------------------------------------------------+ */
559 /* | Get the maximum side length of the hyper rectangle and then set the   | */
560 /* | new side length to this lengths times the growth factor.              | */
561 /* +-----------------------------------------------------------------------+ */
562             help = direct_dirgetmaxdeep_(&i__, &length[length_offset], maxfunc, n);
563             sidelength = thirds[help] * 2.;
564 /* +-----------------------------------------------------------------------+ */
565 /* | Set the Center and the upper and lower bounds of the rectangles.      | */
566 /* +-----------------------------------------------------------------------+ */
567             i__2 = *n;
568             for (j = 1; j <= i__2; ++j) {
569                 sidelength = thirds[length[i__ + j * length_dim1]];
570                 a[j - 1] = c__[j + i__ * c_dim1] - sidelength;
571                 b[j - 1] = c__[j + i__ * c_dim1] + sidelength;
572 /* L20: */
573             }
574 /* +-----------------------------------------------------------------------+ */
575 /* | The function value is reset to 'Inf', since it may have been changed  | */
576 /* | in an earlier iteration and now the feasible point which was close    | */
577 /* | is not close anymore (since the hyper rectangle surrounding the       | */
578 /* | current point may have shrunk).                                       | */
579 /* +-----------------------------------------------------------------------+ */
580             f[(i__ << 1) + 1] = HUGE_VAL;
581             f[(i__ << 1) + 2] = 2.;
582 /* +-----------------------------------------------------------------------+ */
583 /* | Check if any feasible point is near this infeasible point.            | */
584 /* +-----------------------------------------------------------------------+ */
585             i__2 = *free - 1;
586             for (k = 1; k <= i__2; ++k) {
587 /* +-----------------------------------------------------------------------+ */
588 /* | If the point k is feasible, check if it is near.                      | */
589 /* +-----------------------------------------------------------------------+ */
590                 if (f[(k << 1) + 2] == 0.) {
591 /* +-----------------------------------------------------------------------+ */
592 /* | Copy the coordinates of the point k into x.                           | */
593 /* +-----------------------------------------------------------------------+ */
594                     i__3 = *n;
595                     for (l = 1; l <= i__3; ++l) {
596                         x[l - 1] = c__[l + k * c_dim1];
597 /* L40: */
598                     }
599 /* +-----------------------------------------------------------------------+ */
600 /* | Check if the point k is near the infeasible point, if so, replace the | */
601 /* | value at */
602 /* +-----------------------------------------------------------------------+ */
603                     if (isinbox_(x, a, b, n, &c__32) == 1) {
604 /* Computing MIN */
605                          d__1 = f[(i__ << 1) + 1], d__2 = f[(k << 1) + 1];
606                          f[(i__ << 1) + 1] = MIN(d__1,d__2);
607                          f[(i__ << 1) + 2] = 1.; 
608                     }
609                 }
610 /* L30: */
611             }
612             if (f[(i__ << 1) + 2] == 1.) {
613                 f[(i__ << 1) + 1] += (d__1 = f[(i__ << 1) + 1], fabs(d__1)) *
614                         1e-6f;
615                 i__2 = *n;
616                 for (l = 1; l <= i__2; ++l) {
617                     x[l - 1] = c__[l + i__ * c_dim1] * c1[l] + c__[l + i__ *
618                             c_dim1] * c2[l];
619 /* L200: */
620                 }
621                 dirresortlist_(&i__, &anchor[-1], &f[3], &point[1], 
622                                &length[length_offset], n, 
623                                maxfunc, maxdim, maxdeep, logfile, jones);
624             } else {
625 /* +-----------------------------------------------------------------------+ */
626 /* | JG 01/22/01                                                           | */
627 /* | Replaced fixed value for infeasible points with maximum value found,  | */
628 /* | increased by 1.                                                       | */
629 /* +-----------------------------------------------------------------------+ */
630                 if (! (*fmax == f[(i__ << 1) + 1])) {
631 /* Computing MAX */
632                     d__1 = *fmax + 1., d__2 = f[(i__ << 1) + 1];
633                     f[(i__ << 1) + 1] = MAX(d__1,d__2);
634                 }
635             }
636         }
637 /* L10: */
638     }
639 /* L1000: */
640 } /* dirreplaceinf_ */
641
642 /* +-----------------------------------------------------------------------+ */
643 /* |    SUBROUTINE DIRInsert                                               | */
644 /* +-----------------------------------------------------------------------+ */
645 /* Subroutine */ static void dirinsert_(integer *start, integer *ins, integer *point, 
646         doublereal *f, integer *maxfunc)
647 {
648     /* System generated locals */
649     integer i__1;
650
651     /* Local variables */
652     integer i__, help;
653
654 /* JG 09/17/00 Rewrote this routine. */
655 /*      DO 10,i = 1,maxfunc */
656 /*        IF (f(ins,1) .LT. f(point(start),1)) THEN */
657 /*          help = point(start) */
658 /*          point(start) = ins */
659 /*          point(ins) = help */
660 /*          GOTO 20 */
661 /*        END IF */
662 /*        IF (point(start) .EQ. 0) THEN */
663 /*           point(start) = ins */
664 /*           point(ins) = 0 */
665 /*           GOTO 20 */
666 /*        END IF */
667 /*        start = point(start) */
668 /* 10    CONTINUE */
669 /* 20    END */
670     /* Parameter adjustments */
671     f -= 3;
672     --point;
673
674     /* Function Body */
675     i__1 = *maxfunc;
676     for (i__ = 1; i__ <= i__1; ++i__) {
677         if (point[*start] == 0) {
678             point[*start] = *ins;
679             point[*ins] = 0;
680             return;
681         } else if (f[(*ins << 1) + 1] < f[(point[*start] << 1) + 1]) {
682              help = point[*start];
683              point[*start] = *ins;
684              point[*ins] = help;
685              return;
686         }
687         *start = point[*start];
688 /* L10: */
689     }
690 } /* dirinsert_ */
691
692 /* +-----------------------------------------------------------------------+ */
693 /* |    SUBROUTINE DIRInsertList                                           | */
694 /* |    Changed 02-24-2000                                                 | */
695 /* |      Got rid of the distinction between feasible and infeasible points| */
696 /* |      I could do this since infeasible points get set to a high        | */
697 /* |      function value, which may be replaced by a function value of a   | */
698 /* |      nearby function at the end of the main loop.                     | */
699 /* +-----------------------------------------------------------------------+ */
700 /* Subroutine */ void direct_dirinsertlist_(integer *new__, integer *anchor, integer *
701         point, doublereal *f, integer *maxi, integer *length, integer *
702         maxfunc, integer *maxdeep, integer *n, integer *samp,
703                                             integer jones)
704 {
705     /* System generated locals */
706     integer length_dim1, length_offset, i__1;
707
708     /* Local variables */
709     integer j;
710     integer pos;
711     integer pos1, pos2, deep;
712
713 /* JG 09/24/00 Changed this to Getlevel */
714     /* Parameter adjustments */
715     f -= 3;
716     --point;
717     ++anchor;
718     length_dim1 = *n;
719     length_offset = 1 + length_dim1;
720     length -= length_offset;
721
722     /* Function Body */
723     i__1 = *maxi;
724     for (j = 1; j <= i__1; ++j) {
725         pos1 = *new__;
726         pos2 = point[pos1];
727         *new__ = point[pos2];
728 /* JG 09/24/00 Changed this to Getlevel */
729 /*        deep = DIRGetMaxdeep(pos1,length,maxfunc,n) */
730         deep = direct_dirgetlevel_(&pos1, &length[length_offset], maxfunc, n, jones);
731         if (anchor[deep] == 0) {
732             if (f[(pos2 << 1) + 1] < f[(pos1 << 1) + 1]) {
733                 anchor[deep] = pos2;
734                 point[pos2] = pos1;
735                 point[pos1] = 0;
736             } else {
737                 anchor[deep] = pos1;
738                 point[pos2] = 0;
739             }
740         } else {
741             pos = anchor[deep];
742             if (f[(pos2 << 1) + 1] < f[(pos1 << 1) + 1]) {
743                 if (f[(pos2 << 1) + 1] < f[(pos << 1) + 1]) {
744                     anchor[deep] = pos2;
745 /* JG 08/30/00 Fixed bug. Sorting was not correct when */
746 /*      f(1,pos2) < f(1,pos1) < f(1,pos) */
747                     if (f[(pos1 << 1) + 1] < f[(pos << 1) + 1]) {
748                         point[pos2] = pos1;
749                         point[pos1] = pos;
750                     } else {
751                         point[pos2] = pos;
752                         dirinsert_(&pos, &pos1, &point[1], &f[3], maxfunc);
753                     }
754                 } else {
755                     dirinsert_(&pos, &pos2, &point[1], &f[3], maxfunc);
756                     dirinsert_(&pos, &pos1, &point[1], &f[3], maxfunc);
757                 }
758             } else {
759                 if (f[(pos1 << 1) + 1] < f[(pos << 1) + 1]) {
760 /* JG 08/30/00 Fixed bug. Sorting was not correct when */
761 /*      f(pos1,1) < f(pos2,1) < f(pos,1) */
762                     anchor[deep] = pos1;
763                     if (f[(pos << 1) + 1] < f[(pos2 << 1) + 1]) {
764                         point[pos1] = pos;
765                         dirinsert_(&pos, &pos2, &point[1], &f[3], maxfunc);
766                     } else {
767                         point[pos1] = pos2;
768                         point[pos2] = pos;
769                     }
770                 } else {
771                     dirinsert_(&pos, &pos1, &point[1], &f[3], maxfunc);
772                     dirinsert_(&pos, &pos2, &point[1], &f[3], maxfunc);
773                 }
774             }
775         }
776 /* L10: */
777     }
778 /* JG 09/24/00 Changed this to Getlevel */
779 /*      deep = DIRGetMaxdeep(samp,length,maxfunc,n) */
780     deep = direct_dirgetlevel_(samp, &length[length_offset], maxfunc, n, jones);
781     pos = anchor[deep];
782     if (f[(*samp << 1) + 1] < f[(pos << 1) + 1]) {
783         anchor[deep] = *samp;
784         point[*samp] = pos;
785     } else {
786         dirinsert_(&pos, samp, &point[1], &f[3], maxfunc);
787     }
788 } /* dirinsertlist_ */
789
790 /* +-----------------------------------------------------------------------+ */
791 /* |    SUBROUTINE DIRInsertList2  (Old way to do it.)                     | */
792 /* +-----------------------------------------------------------------------+ */
793 /* Subroutine */ static void dirinsertlist_2__(integer *start, integer *j, integer *k,
794          integer *list2, doublereal *w, integer *maxi, integer *n)
795 {
796     /* System generated locals */
797     integer list2_dim1, list2_offset, i__1;
798
799     /* Local variables */
800     integer i__, pos;
801
802     /* Parameter adjustments */
803     --w;
804     list2_dim1 = *n;
805     list2_offset = 1 + list2_dim1;
806     list2 -= list2_offset;
807
808     /* Function Body */
809     pos = *start;
810     if (*start == 0) {
811         list2[*j + list2_dim1] = 0;
812         *start = *j;
813         goto L50;
814     }
815     if (w[*start] > w[*j]) {
816         list2[*j + list2_dim1] = *start;
817         *start = *j;
818     } else {
819         i__1 = *maxi;
820         for (i__ = 1; i__ <= i__1; ++i__) {
821             if (list2[pos + list2_dim1] == 0) {
822                 list2[*j + list2_dim1] = 0;
823                 list2[pos + list2_dim1] = *j;
824                 goto L50;
825             } else {
826                 if (w[*j] < w[list2[pos + list2_dim1]]) {
827                     list2[*j + list2_dim1] = list2[pos + list2_dim1];
828                     list2[pos + list2_dim1] = *j;
829                     goto L50;
830                 }
831             }
832             pos = list2[pos + list2_dim1];
833 /* L10: */
834         }
835     }
836 L50:
837     list2[*j + (list2_dim1 << 1)] = *k;
838 } /* dirinsertlist_2__ */
839
840 /* +-----------------------------------------------------------------------+ */
841 /* |    SUBROUTINE DIRSearchmin                                            | */
842 /* |    Search for the minimum in the list.                                ! */
843 /* +-----------------------------------------------------------------------+ */
844 /* Subroutine */ static void dirsearchmin_(integer *start, integer *list2, integer *
845         pos, integer *k, integer *n)
846 {
847     /* System generated locals */
848     integer list2_dim1, list2_offset;
849
850     /* Parameter adjustments */
851     list2_dim1 = *n;
852     list2_offset = 1 + list2_dim1;
853     list2 -= list2_offset;
854
855     /* Function Body */
856     *k = *start;
857     *pos = list2[*start + (list2_dim1 << 1)];
858     *start = list2[*start + list2_dim1];
859 } /* dirsearchmin_ */
860
861 /* +-----------------------------------------------------------------------+ */
862 /* |    SUBROUTINE DIRSamplepoints                                         | */
863 /* |    Subroutine to sample the new points.                               | */
864 /* +-----------------------------------------------------------------------+ */
865 /* Subroutine */ void direct_dirsamplepoints_(doublereal *c__, integer *arrayi, 
866         doublereal *delta, integer *sample, integer *start, integer *length, 
867         FILE *logfile, doublereal *f, integer *free, 
868         integer *maxi, integer *point, doublereal *x, doublereal *l,
869          doublereal *fmin, integer *minpos, doublereal *u, integer *n, 
870         integer *maxfunc, integer *maxdeep, integer *oops)
871 {
872     /* System generated locals */
873     integer length_dim1, length_offset, c_dim1, c_offset, i__1, i__2;
874
875     /* Local variables */
876     integer j, k, pos;
877
878
879     /* Parameter adjustments */
880     --u;
881     --l;
882     --x;
883     --arrayi;
884     --point;
885     f -= 3;
886     length_dim1 = *n;
887     length_offset = 1 + length_dim1;
888     length -= length_offset;
889     c_dim1 = *n;
890     c_offset = 1 + c_dim1;
891     c__ -= c_offset;
892
893     /* Function Body */
894     *oops = 0;
895     pos = *free;
896     *start = *free;
897     i__1 = *maxi + *maxi;
898     for (k = 1; k <= i__1; ++k) {
899         i__2 = *n;
900         for (j = 1; j <= i__2; ++j) {
901             length[j + *free * length_dim1] = length[j + *sample *
902                     length_dim1];
903             c__[j + *free * c_dim1] = c__[j + *sample * c_dim1];
904 /* L20: */
905         }
906         pos = *free;
907         *free = point[*free];
908         if (*free == 0) {
909              if (logfile)
910                   fprintf(logfile, "Error, no more free positions! "
911                           "Increase maxfunc!\n");
912             *oops = 1;
913             return;
914         }
915 /* L10: */
916     }
917     point[pos] = 0;
918     pos = *start;
919     i__1 = *maxi;
920     for (j = 1; j <= i__1; ++j) {
921         c__[arrayi[j] + pos * c_dim1] = c__[arrayi[j] + *sample * c_dim1] + *
922                 delta;
923         pos = point[pos];
924         c__[arrayi[j] + pos * c_dim1] = c__[arrayi[j] + *sample * c_dim1] - *
925                 delta;
926         pos = point[pos];
927 /* L30: */
928     }
929     ASRT(pos <= 0);
930 } /* dirsamplepoints_ */
931
932 /* +-----------------------------------------------------------------------+ */
933 /* |    SUBROUTINE DIRDivide                                               | */
934 /* |    Subroutine to divide the hyper rectangles according to the rules.  | */
935 /* |    Changed 02-24-2000                                                 | */
936 /* |      Replaced if statement by min (line 367)                          | */
937 /* +-----------------------------------------------------------------------+ */
938 /* Subroutine */ void direct_dirdivide_(integer *new__, integer *currentlength, 
939         integer *length, integer *point, integer *arrayi, integer *sample, 
940         integer *list2, doublereal *w, integer *maxi, doublereal *f, integer *
941         maxfunc, integer *maxdeep, integer *n)
942 {
943     /* System generated locals */
944     integer length_dim1, length_offset, list2_dim1, list2_offset, i__1, i__2;
945     doublereal d__1, d__2;
946
947     /* Local variables */
948     integer i__, j, k, pos, pos2;
949     integer start;
950
951
952     /* Parameter adjustments */
953     f -= 3;
954     --point;
955     --w;
956     list2_dim1 = *n;
957     list2_offset = 1 + list2_dim1;
958     list2 -= list2_offset;
959     --arrayi;
960     length_dim1 = *n;
961     length_offset = 1 + length_dim1;
962     length -= length_offset;
963
964     /* Function Body */
965     start = 0;
966     pos = *new__;
967     i__1 = *maxi;
968     for (i__ = 1; i__ <= i__1; ++i__) {
969         j = arrayi[i__];
970         w[j] = f[(pos << 1) + 1];
971         k = pos;
972         pos = point[pos];
973 /* Computing MIN */
974         d__1 = f[(pos << 1) + 1], d__2 = w[j];
975         w[j] = MIN(d__1,d__2);
976         pos = point[pos];
977         dirinsertlist_2__(&start, &j, &k, &list2[list2_offset], &w[1], maxi, 
978                 n);
979 /* L10: */
980     }
981     ASRT(pos <= 0);
982     i__1 = *maxi;
983     for (j = 1; j <= i__1; ++j) {
984         dirsearchmin_(&start, &list2[list2_offset], &pos, &k, n);
985         pos2 = start;
986         length[k + *sample * length_dim1] = *currentlength + 1; 
987         i__2 = *maxi - j + 1;
988         for (i__ = 1; i__ <= i__2; ++i__) {
989             length[k + pos * length_dim1] = *currentlength + 1; 
990             pos = point[pos];
991             length[k + pos * length_dim1] = *currentlength + 1;
992 /* JG 07/10/01 pos2 = 0 at the end of the 30-loop. Since we end */
993 /*             the loop now, we do not need to reassign pos and pos2. */
994             if (pos2 > 0) {
995                 pos = list2[pos2 + (list2_dim1 << 1)];
996                 pos2 = list2[pos2 + list2_dim1];
997             }
998 /* L30: */
999         }
1000 /* L20: */
1001     }
1002 } /* dirdivide_ */
1003
1004 /* +-----------------------------------------------------------------------+ */
1005 /* |                                                                       | */
1006 /* |                       SUBROUTINE DIRINFCN                             | */
1007 /* |                                                                       | */
1008 /* | Subroutine DIRinfcn unscales the variable x for use in the            | */
1009 /* | user-supplied function evaluation subroutine fcn. After fcn returns   | */
1010 /* | to DIRinfcn, DIRinfcn then rescales x for use by DIRECT.              | */
1011 /* |                                                                       | */
1012 /* | On entry                                                              | */
1013 /* |                                                                       | */
1014 /* |        fcn -- The argument containing the name of the user-supplied   | */
1015 /* |               subroutine that returns values for the function to be   | */
1016 /* |               minimized.                                              | */
1017 /* |                                                                       | */
1018 /* |          x -- A double-precision vector of length n. The point at     | */
1019 /* |               which the derivative is to be evaluated.                | */
1020 /* |                                                                       | */
1021 /* |        xs1 -- A double-precision vector of length n. Used for         | */
1022 /* |               scaling and unscaling the vector x by DIRinfcn.         | */
1023 /* |                                                                       | */
1024 /* |        xs2 -- A double-precision vector of length n. Used for         | */
1025 /* |               scaling and unscaling the vector x by DIRinfcn.         | */
1026 /* |                                                                       | */
1027 /* |          n -- An integer. The dimension of the problem.               | */
1028 /* |       kret -- An Integer. If kret =  1, the point is infeasible,      | */
1029 /* |                              kret = -1, bad problem set up,           | */
1030 /* |                              kret =  0, feasible.                     | */
1031 /* |                                                                       | */
1032 /* | On return                                                             | */
1033 /* |                                                                       | */
1034 /* |          f -- A double-precision scalar.                              | */
1035 /* |                                                                       | */
1036 /* | Subroutines and Functions                                             | */
1037 /* |                                                                       | */
1038 /* | The subroutine whose name is passed through the argument fcn.         | */
1039 /* |                                                                       | */
1040 /* +-----------------------------------------------------------------------+ */
1041 /* Subroutine */ void direct_dirinfcn_(fp fcn, doublereal *x, doublereal *c1, 
1042         doublereal *c2, integer *n, doublereal *f, integer *flag__, 
1043                                        void *fcn_data)
1044 {
1045     /* System generated locals */
1046     integer i__1;
1047
1048     /* Local variables */
1049     integer i__;
1050
1051 /* +-----------------------------------------------------------------------+ */
1052 /* | Variables to pass user defined data to the function to be optimized.  | */
1053 /* +-----------------------------------------------------------------------+ */
1054 /* +-----------------------------------------------------------------------+ */
1055 /* | Unscale the variable x.                                               | */
1056 /* +-----------------------------------------------------------------------+ */
1057     /* Parameter adjustments */
1058     --c2;
1059     --c1;
1060     --x;
1061
1062     /* Function Body */
1063     i__1 = *n;
1064     for (i__ = 1; i__ <= i__1; ++i__) {
1065         x[i__] = (x[i__] + c2[i__]) * c1[i__];
1066 /* L20: */
1067     }
1068 /* +-----------------------------------------------------------------------+ */
1069 /* | Call the function-evaluation subroutine fcn.                          | */
1070 /* +-----------------------------------------------------------------------+ */
1071     *flag__ = 0;
1072     *f = fcn(*n, &x[1], flag__, fcn_data);
1073 /* +-----------------------------------------------------------------------+ */
1074 /* | Rescale the variable x.                                               | */
1075 /* +-----------------------------------------------------------------------+ */
1076     i__1 = *n;
1077     for (i__ = 1; i__ <= i__1; ++i__) {
1078         x[i__] = x[i__] / c1[i__] - c2[i__];
1079 /* L30: */
1080     }
1081 } /* dirinfcn_ */
1082
1083 /* +-----------------------------------------------------------------------+ */
1084 /* |    SUBROUTINE DIRGet_I                                                | */
1085 /* +-----------------------------------------------------------------------+ */
1086 /* Subroutine */ void direct_dirget_i__(integer *length, integer *pos, integer *
1087         arrayi, integer *maxi, integer *n, integer *maxfunc)
1088 {
1089     /* System generated locals */
1090     integer length_dim1, length_offset, i__1;
1091
1092     /* Local variables */
1093     integer i__, j, help;
1094
1095     /* Parameter adjustments */
1096     --arrayi;
1097     length_dim1 = *n;
1098     length_offset = 1 + length_dim1;
1099     length -= length_offset;
1100
1101     /* Function Body */
1102     j = 1;
1103     help = length[*pos * length_dim1 + 1];
1104     i__1 = *n;
1105     for (i__ = 2; i__ <= i__1; ++i__) {
1106         if (length[i__ + *pos * length_dim1] < help) {
1107             help = length[i__ + *pos * length_dim1];
1108         }
1109 /* L10: */
1110     }
1111     i__1 = *n;
1112     for (i__ = 1; i__ <= i__1; ++i__) {
1113         if (length[i__ + *pos * length_dim1] == help) {
1114             arrayi[j] = i__;
1115             ++j;
1116         }
1117 /* L20: */
1118     }
1119     *maxi = j - 1;
1120 } /* dirget_i__ */
1121
1122 /* +-----------------------------------------------------------------------+ */
1123 /* |    SUBROUTINE DIRInit                                                 | */
1124 /* |    Initialise all needed variables and do the first run of the        | */
1125 /* |    algorithm.                                                         | */
1126 /* |    Changed 02/24/2000                                                 | */
1127 /* |       Changed fcn Double precision to fcn external!                   | */
1128 /* |    Changed 09/15/2000                                                 | */
1129 /* |       Added distinction between Jones way to characterize rectangles  | */
1130 /* |       and our way. Common variable JONES controls which way we use.   | */
1131 /* |          JONES = 0    Jones way (Distance from midpoint to corner)    | */
1132 /* |          JONES = 1    Our way (Length of longest side)                | */
1133 /* |    Changed 09/24/00                                                   | */
1134 /* |       Added array levels. Levels contain the values to characterize   | */
1135 /* |       the hyperrectangles.                                            | */
1136 /* |    Changed 01/22/01                                                   | */
1137 /* |       Added variable fmax to keep track of maximum value found.       | */
1138 /* |       Added variable Ifeasiblef to keep track if feasibel point has   | */
1139 /* |       been found.                                                     | */
1140 /* |    Changed 01/23/01                                                   | */
1141 /* |       Added variable Ierror to keep track of errors.                  | */
1142 /* +-----------------------------------------------------------------------+ */
1143 /* Subroutine */ void direct_dirinit_(doublereal *f, fp fcn, doublereal *c__, 
1144         integer *length, integer *actdeep, integer *point, integer *anchor, 
1145         integer *free, FILE *logfile, integer *arrayi, 
1146         integer *maxi, integer *list2, doublereal *w, doublereal *x, 
1147         doublereal *l, doublereal *u, doublereal *fmin, integer *minpos, 
1148         doublereal *thirds, doublereal *levels, integer *maxfunc, integer *
1149         maxdeep, integer *n, integer *maxor, doublereal *fmax, integer *
1150         ifeasiblef, integer *iinfeasible, integer *ierror, void *fcndata,
1151                                       integer jones)
1152 {
1153     /* System generated locals */
1154     integer c_dim1, c_offset, length_dim1, length_offset, list2_dim1, 
1155             list2_offset, i__1, i__2;
1156
1157     /* Local variables */
1158     integer i__, j;
1159     integer new__, help, oops;
1160     doublereal help2, delta;
1161     doublereal costmin;
1162
1163 /* +-----------------------------------------------------------------------+ */
1164 /* | JG 01/22/01 Added variable to keep track of the maximum value found.  | */
1165 /* +-----------------------------------------------------------------------+ */
1166 /* +-----------------------------------------------------------------------+ */
1167 /* | JG 01/22/01 Added variable Ifeasiblef to keep track if feasibel point | */
1168 /* |             has been found.                                           | */
1169 /* | JG 01/23/01 Added variable Ierror to keep track of errors.            | */
1170 /* | JG 03/09/01 Added IInfeasible to keep track if an infeasible point has| */
1171 /* |             been found.                                               | */
1172 /* +-----------------------------------------------------------------------+ */
1173 /* JG 09/15/00 Added variable JONES (see above) */
1174 /* +-----------------------------------------------------------------------+ */
1175 /* | Variables to pass user defined data to the function to be optimized.  | */
1176 /* +-----------------------------------------------------------------------+ */
1177     /* Parameter adjustments */
1178     --point;
1179     f -= 3;
1180     ++anchor;
1181     --u;
1182     --l;
1183     --x;
1184     --w;
1185     list2_dim1 = *maxor;
1186     list2_offset = 1 + list2_dim1;
1187     list2 -= list2_offset;
1188     --arrayi;
1189     length_dim1 = *n;
1190     length_offset = 1 + length_dim1;
1191     length -= length_offset;
1192     c_dim1 = *maxor;
1193     c_offset = 1 + c_dim1;
1194     c__ -= c_offset;
1195
1196     /* Function Body */
1197     *fmin = 1e20;
1198     costmin = *fmin;
1199 /* JG 09/15/00 If Jones way of characterising rectangles is used, */
1200 /*             initialise thirds to reflect this. */
1201     if (jones == 0) {
1202         i__1 = *n - 1;
1203         for (j = 0; j <= i__1; ++j) {
1204             w[j + 1] = sqrt(*n - j + j / 9.) * .5;
1205 /* L5: */
1206         }
1207         help2 = 1.;
1208         i__1 = *maxdeep / *n;
1209         for (i__ = 1; i__ <= i__1; ++i__) {
1210             i__2 = *n - 1;
1211             for (j = 0; j <= i__2; ++j) {
1212                 levels[(i__ - 1) * *n + j] = w[j + 1] / help2;
1213 /* L8: */
1214             }
1215             help2 *= 3.;
1216 /* L10: */
1217         }
1218     } else {
1219 /* JG 09/15/00 Initialiase levels to contain 1/j */
1220         help2 = 3.;
1221         i__1 = *maxdeep;
1222         for (i__ = 1; i__ <= i__1; ++i__) {
1223             levels[i__] = 1. / help2;
1224             help2 *= 3.;
1225 /* L11: */
1226         }
1227         levels[0] = 1.;
1228     }
1229     help2 = 3.;
1230     i__1 = *maxdeep;
1231     for (i__ = 1; i__ <= i__1; ++i__) {
1232         thirds[i__] = 1. / help2;
1233         help2 *= 3.;
1234 /* L21: */
1235     }
1236     thirds[0] = 1.;
1237     i__1 = *n;
1238     for (i__ = 1; i__ <= i__1; ++i__) {
1239         c__[i__ + c_dim1] = .5;
1240         x[i__] = .5;
1241         length[i__ + length_dim1] = 0;
1242 /* L20: */
1243     }
1244     direct_dirinfcn_(fcn, &x[1], &l[1], &u[1], n, &f[3], &help, fcndata);
1245     f[4] = (doublereal) help;
1246     *iinfeasible = help;
1247     *fmax = f[3];
1248 /* 09/25/00 Added this */
1249 /*      if (f(1,1) .ge. 1.E+6) then */
1250     if (f[4] > 0.) {
1251         f[3] = HUGE_VAL;
1252         *fmax = f[3];
1253         *ifeasiblef = 1;
1254     } else {
1255         *ifeasiblef = 0;
1256     }
1257 /* JG 09/25/00 Remove IF */
1258     *fmin = f[3];
1259     costmin = f[3];
1260     *minpos = 1;
1261     *actdeep = 2;
1262     point[1] = 0;
1263     *free = 2;
1264     delta = thirds[1];
1265     direct_dirget_i__(&length[length_offset], &c__1, &arrayi[1], maxi, n, maxfunc);
1266     new__ = *free;
1267     direct_dirsamplepoints_(&c__[c_offset], &arrayi[1], &delta, &c__1, &new__, &
1268             length[length_offset], logfile, &f[3], free, maxi, &
1269             point[1], &x[1], &l[1], fmin, minpos, &u[1], n, 
1270             maxfunc, maxdeep, &oops);
1271 /* +-----------------------------------------------------------------------+ */
1272 /* | JG 01/23/01 Added error checking.                                     | */
1273 /* +-----------------------------------------------------------------------+ */
1274     if (oops > 0) {
1275         *ierror = -4;
1276         return;
1277     }
1278 /* +-----------------------------------------------------------------------+ */
1279 /* | JG 01/22/01 Added variable to keep track of the maximum value found.  | */
1280 /* |             Added variable to keep track if feasible point was found. | */
1281 /* +-----------------------------------------------------------------------+ */
1282     direct_dirsamplef_(&c__[c_offset], &arrayi[1], &delta, &c__1, &new__, &length[
1283             length_offset], logfile, &f[3], free, maxi, &point[
1284             1], fcn, &x[1], &l[1], fmin, minpos, &u[1], n, maxfunc, 
1285             maxdeep, &oops, fmax, ifeasiblef, iinfeasible, fcndata);
1286 /* +-----------------------------------------------------------------------+ */
1287 /* | JG 01/23/01 Added error checking.                                     | */
1288 /* +-----------------------------------------------------------------------+ */
1289     if (oops > 0) {
1290         *ierror = -5;
1291         return;
1292     }
1293     direct_dirdivide_(&new__, &c__0, &length[length_offset], &point[1], &arrayi[1], &
1294             c__1, &list2[list2_offset], &w[1], maxi, &f[3], maxfunc, 
1295             maxdeep, n);
1296     direct_dirinsertlist_(&new__, &anchor[-1], &point[1], &f[3], maxi, &
1297             length[length_offset], maxfunc, maxdeep, n, &c__1, jones);
1298 } /* dirinit_ */
1299
1300 /* +-----------------------------------------------------------------------+ */
1301 /* |    SUBROUTINE DIRInitList                                             | */
1302 /* |    Initialise the list.                                               | */
1303 /* +-----------------------------------------------------------------------+ */
1304 /* Subroutine */ void direct_dirinitlist_(integer *anchor, integer *free, integer *
1305         point, doublereal *f, integer *maxfunc, integer *maxdeep)
1306 {
1307     /* System generated locals */
1308     integer i__1;
1309
1310     /* Local variables */
1311     integer i__;
1312
1313 /*   f -- values of functions. */
1314 /*   anchor -- anchors of lists with deep i */
1315 /*   point -- lists */
1316 /*   free  -- first free position */
1317     /* Parameter adjustments */
1318     f -= 3;
1319     --point;
1320     ++anchor;
1321
1322     /* Function Body */
1323     i__1 = *maxdeep;
1324     for (i__ = -1; i__ <= i__1; ++i__) {
1325         anchor[i__] = 0;
1326 /* L10: */
1327     }
1328     i__1 = *maxfunc;
1329     for (i__ = 1; i__ <= i__1; ++i__) {
1330         f[(i__ << 1) + 1] = 0.;
1331         f[(i__ << 1) + 2] = 0.;
1332         point[i__] = i__ + 1;
1333 /*       point(i) = 0 */
1334 /* L20: */
1335     }
1336     point[*maxfunc] = 0;
1337     *free = 1;
1338 } /* dirinitlist_ */
1339
1340 /* +-----------------------------------------------------------------------+ */
1341 /* |                                                                       | */
1342 /* |                       SUBROUTINE DIRPREPRC                            | */
1343 /* |                                                                       | */
1344 /* | Subroutine DIRpreprc uses an afine mapping to map the hyper-box given | */
1345 /* | by the constraints on the variable x onto the n-dimensional unit cube.| */
1346 /* | This mapping is done using the following equation:                    | */
1347 /* |                                                                       | */
1348 /* |               x(i)=x(i)/(u(i)-l(i))-l(i)/(u(i)-l(i)).                 | */
1349 /* |                                                                       | */
1350 /* | DIRpreprc checks if the bounds l and u are well-defined. That is, if  | */
1351 /* |                                                                       | */
1352 /* |               l(i) < u(i) forevery i.                                 | */
1353 /* |                                                                       | */
1354 /* | On entry                                                              | */
1355 /* |                                                                       | */
1356 /* |          u -- A double-precision vector of length n. The vector       | */
1357 /* |               containing the upper bounds for the n independent       | */
1358 /* |               variables.                                              | */
1359 /* |                                                                       | */
1360 /* |          l -- A double-precision vector of length n. The vector       | */
1361 /* |               containing the lower bounds for the n independent       | */
1362 /* |               variables.                                              | */
1363 /* |                                                                       | */
1364 /* |          n -- An integer. The dimension of the problem.               | */
1365 /* |                                                                       | */
1366 /* | On return                                                             | */
1367 /* |                                                                       | */
1368 /* |        xs1 -- A double-precision vector of length n, used for scaling | */
1369 /* |               and unscaling the vector x.                             | */
1370 /* |                                                                       | */
1371 /* |        xs2 -- A double-precision vector of length n, used for scaling | */
1372 /* |               and unscaling the vector x.                             | */
1373 /* |                                                                       | */
1374 /* |                                                                       | */
1375 /* |       oops -- An integer. If an upper bound is less than a lower      | */
1376 /* |               bound or if the initial point is not in the             | */
1377 /* |               hyper-box oops is set to 1 and iffco terminates.        | */
1378 /* |                                                                       | */
1379 /* +-----------------------------------------------------------------------+ */
1380 /* Subroutine */ void direct_dirpreprc_(doublereal *u, doublereal *l, integer *n, 
1381         doublereal *xs1, doublereal *xs2, integer *oops)
1382 {
1383     /* System generated locals */
1384     integer i__1;
1385
1386     /* Local variables */
1387     integer i__;
1388     doublereal help;
1389
1390     /* Parameter adjustments */
1391     --xs2;
1392     --xs1;
1393     --l;
1394     --u;
1395
1396     /* Function Body */
1397     *oops = 0;
1398     i__1 = *n;
1399     for (i__ = 1; i__ <= i__1; ++i__) {
1400 /* +-----------------------------------------------------------------------+ */
1401 /* | Check if the hyper-box is well-defined.                               | */
1402 /* +-----------------------------------------------------------------------+ */
1403         if (u[i__] <= l[i__]) {
1404             *oops = 1;
1405             return;
1406         }
1407 /* L20: */
1408     }
1409 /* +-----------------------------------------------------------------------+ */
1410 /* | Scale the initial iterate so that it is in the unit cube.             | */
1411 /* +-----------------------------------------------------------------------+ */
1412     i__1 = *n;
1413     for (i__ = 1; i__ <= i__1; ++i__) {
1414         help = u[i__] - l[i__];
1415         xs2[i__] = l[i__] / help;
1416         xs1[i__] = help;
1417 /* L50: */
1418     }
1419 } /* dirpreprc_ */
1420
1421 /* Subroutine */ void direct_dirheader_(FILE *logfile, integer *version, 
1422         doublereal *x, integer *n, doublereal *eps, integer *maxf, integer *
1423         maxt, doublereal *l, doublereal *u, integer *algmethod, integer *
1424         maxfunc, integer *maxdeep, doublereal *fglobal, doublereal *fglper, 
1425         integer *ierror, doublereal *epsfix, integer *iepschange, doublereal *
1426         volper, doublereal *sigmaper)
1427 {
1428     /* System generated locals */
1429     integer i__1;
1430
1431     /* Local variables */
1432     integer imainver, i__, numerrors, isubsubver, ihelp, isubver;
1433
1434
1435 /* +-----------------------------------------------------------------------+ */
1436 /* | Variables to pass user defined data to the function to be optimized.  | */
1437 /* +-----------------------------------------------------------------------+ */
1438     /* Parameter adjustments */
1439     --u;
1440     --l;
1441     --x;
1442
1443     /* Function Body */
1444     if (logfile)
1445          fprintf(logfile, "------------------- Log file ------------------\n");
1446
1447     numerrors = 0;
1448     *ierror = 0;
1449     imainver = *version / 100;
1450     ihelp = *version - imainver * 100;
1451     isubver = ihelp / 10;
1452     ihelp -= isubver * 10;
1453     isubsubver = ihelp;
1454 /* +-----------------------------------------------------------------------+ */
1455 /* | JG 01/13/01 Added check for epsilon. If epsilon is smaller 0, we use  | */
1456 /* |             the update formula from Jones. We then set the flag       | */
1457 /* |             iepschange to 1, and store the absolute value of eps in   | */
1458 /* |             epsfix. epsilon is then changed after each iteration.     | */
1459 /* +-----------------------------------------------------------------------+ */
1460     if (*eps < 0.) {
1461         *iepschange = 1;
1462         *epsfix = -(*eps);
1463         *eps = -(*eps);
1464     } else {
1465         *iepschange = 0;
1466         *epsfix = 1e100;
1467     }
1468
1469 /* +-----------------------------------------------------------------------+ */
1470 /* | JG 07/16/01 Removed printout of contents in cdata(1).                 | */
1471 /* +-----------------------------------------------------------------------+ */
1472 /*      write(logfile,*) cdata(1) */
1473
1474     if (logfile) {
1475          fprintf(logfile, "DIRECT Version %d.%d.%d\n"
1476                  " Problem dimension n: %d\n"
1477                  " Eps value: %e\n"
1478                  " Maximum number of f-evaluations (maxf): %d\n"
1479                  " Maximum number of iterations (MaxT): %d\n"
1480                  " Value of f_global: %e\n"
1481                  " Global percentage wanted: %e\n"
1482                  " Volume percentage wanted: %e\n"
1483                  " Measure percentage wanted: %e\n",
1484                  imainver, isubver, isubsubver, *n, *eps, *maxf, *maxt,
1485                  *fglobal, *fglper, *volper, *sigmaper);
1486          fprintf(logfile, *iepschange == 1 
1487                  ? "Epsilon is changed using the Jones formula.\n" 
1488                  : "Epsilon is constant.\n");
1489          fprintf(logfile, *algmethod == 0
1490                  ? "Jones original DIRECT algorithm is used.\n"
1491                  : "Our modification of the DIRECT algorithm is used.\n");
1492     }
1493
1494     i__1 = *n;
1495     for (i__ = 1; i__ <= i__1; ++i__) {
1496         if (u[i__] <= l[i__]) {
1497             *ierror = -1;
1498             if (logfile)
1499                  fprintf(logfile, "WARNING: bounds on variable x%d: "
1500                          "%g <= xi <= %g\n", i__, l[i__], u[i__]);
1501             ++numerrors;
1502         } else {
1503             if (logfile)
1504                  fprintf(logfile, "Bounds on variable x%d: "
1505                          "%g <= xi <= %g\n", i__, l[i__], u[i__]);
1506         }
1507 /* L1010: */
1508     }
1509 /* +-----------------------------------------------------------------------+ */
1510 /* | If there are to many function evaluations or to many iteration, note  | */
1511 /* | this and set the error flag accordingly. Note: If more than one error | */
1512 /* | occurred, we give out an extra message.                               | */
1513 /* +-----------------------------------------------------------------------+ */
1514     if (*maxf + 20 > *maxfunc) {
1515         if (logfile)
1516              fprintf(logfile,
1517 "WARNING: The maximum number of function evaluations (%d) is higher than\n"
1518 "         the constant maxfunc (%d).  Increase maxfunc in subroutine DIRECT\n"
1519 "         or decrease the maximum number of function evaluations.\n",
1520                      *maxf, *maxfunc);
1521         ++numerrors;
1522         *ierror = -2;
1523     }
1524     if (*ierror < 0) {
1525         if (logfile) fprintf(logfile, "----------------------------------\n");
1526         if (numerrors == 1) {
1527              if (logfile) 
1528                   fprintf(logfile, "WARNING: One error in the input!\n");
1529         } else {
1530              if (logfile) 
1531                   fprintf(logfile, "WARNING: %d errors in the input!\n",
1532                           numerrors);
1533         }
1534     }
1535     if (logfile) fprintf(logfile, "----------------------------------\n");
1536     if (*ierror >= 0) {
1537          if (logfile)
1538               fprintf(logfile, "Iteration # of f-eval. fmin\n");
1539     }
1540 /* L10005: */
1541 } /* dirheader_ */
1542
1543 /* Subroutine */ void direct_dirsummary_(FILE *logfile, doublereal *x, doublereal *
1544         l, doublereal *u, integer *n, doublereal *fmin, doublereal *fglobal, 
1545         integer *numfunc, integer *ierror)
1546 {
1547     /* Local variables */
1548     integer i__;
1549
1550     /* Parameter adjustments */
1551     --u;
1552     --l;
1553     --x;
1554
1555     /* Function Body */
1556     if (logfile) {
1557          fprintf(logfile, "-----------------------Summary------------------\n"
1558                  "Final function value: %g\n"
1559                  "Number of function evaluations: %d\n", *fmin, *numfunc);
1560          if (*fglobal > -1e99)
1561               fprintf(logfile, "Final function value is within %g%% of global optimum\n", 100*(*fmin - *fglobal) / MAX(1.0, fabs(*fglobal)));
1562          fprintf(logfile, "Index, final solution, x(i)-l(i), u(i)-x(i)\n");
1563          for (i__ = 1; i__ <= *n; ++i__)
1564               fprintf(logfile, "%d, %g, %g, %g\n", i__, x[i__], 
1565                       x[i__]-l[i__], u[i__] - x[i__]);
1566          fprintf(logfile, "-----------------------------------------------\n");
1567               
1568     }
1569 } /* dirsummary_ */