/* DIRsubrout.f -- translated by f2c (version 20050501).

   f2c output hand-cleaned by SGJ (August 2007).
*/

#include <math.h>
#include "direct-internal.h"

/* Table of constant values */

static integer c__1 = 1;
static integer c__32 = 32;
static integer c__0 = 0;

/* +-----------------------------------------------------------------------+ */
/* | INTEGER Function DIRGetlevel                                          | */
/* | Returns the level of the hyperrectangle. Depending on the value of the| */
/* | global variable JONES. IF JONES equals 0, the level is given by       | */
/* |               kN + p, where the rectangle has p sides with a length of| */
/* |             1/3^(k+1), and N-p sides with a length of 1/3^k.          | */
/* | If JONES equals 1, the level is the power of 1/3 of the length of the | */
/* | longest side hyperrectangle.                                          | */
/* |                                                                       | */
/* | On Return :                                                           | */
/* |    the maximal length                                                 | */
/* |                                                                       | */
/* | pos     -- the position of the midpoint in the array length           | */
/* | length  -- the array with the dimensions                              | */
/* | maxfunc -- the leading dimension of length                            | */
/* | n	   -- the dimension of the problem                                  | */
/* |                                                                       | */
/* +-----------------------------------------------------------------------+ */
integer direct_dirgetlevel_(integer *pos, integer *length, integer *maxfunc, integer 
	*n, integer jones)
{
    /* System generated locals */
    integer length_dim1, length_offset, ret_val, i__1;

    /* Local variables */
    integer i__, k, p, help;

/* JG 09/15/00 Added variable JONES (see above) */
    /* Parameter adjustments */
    length_dim1 = *n;
    length_offset = 1 + length_dim1;
    length -= length_offset;

    /* Function Body */
    if (jones == 0) {
	help = length[*pos * length_dim1 + 1];
	k = help;
	p = 1;
	i__1 = *n;
	for (i__ = 2; i__ <= i__1; ++i__) {
	    if (length[i__ + *pos * length_dim1] < k) {
		k = length[i__ + *pos * length_dim1];
	    }
	    if (length[i__ + *pos * length_dim1] == help) {
		++p;
	    }
/* L100: */
	}
	if (k == help) {
	    ret_val = k * *n + *n - p;
	} else {
	    ret_val = k * *n + p;
	}
    } else {
	help = length[*pos * length_dim1 + 1];
	i__1 = *n;
	for (i__ = 2; i__ <= i__1; ++i__) {
	    if (length[i__ + *pos * length_dim1] < help) {
		help = length[i__ + *pos * length_dim1];
	    }
/* L10: */
	}
	ret_val = help;
    }
    return ret_val;
} /* dirgetlevel_ */

/* +-----------------------------------------------------------------------+ */
/* | Program       : Direct.f (subfile DIRsubrout.f)                       | */
/* | Last modified : 07-16-2001                                            | */
/* | Written by    : Joerg Gablonsky                                       | */
/* | Subroutines used by the algorithm DIRECT.                             | */
/* +-----------------------------------------------------------------------+ */
/* +-----------------------------------------------------------------------+ */
/* |    SUBROUTINE DIRChoose                                               | */
/* |    Decide, which is the next sampling point.                          | */
/* |    Changed 09/25/00 JG                                                | */
/* |         Added maxdiv to call and changed S to size maxdiv.            | */
/* |    Changed 01/22/01 JG                                                | */
/* |         Added Ifeasiblef to call to keep track if a feasible point has| */
/* |         been found.                                                   | */
/* |    Changed 07/16/01 JG                                                | */
/* |         Changed if statement to prevent run-time errors.              |                                  
                 | */
/* +-----------------------------------------------------------------------+ */
/* Subroutine */ void direct_dirchoose_(integer *anchor, integer *s, integer *actdeep,
	 doublereal *f, doublereal *minf, doublereal epsrel, doublereal epsabs, doublereal *thirds,
	 integer *maxpos, integer *length, integer *maxfunc, const integer *maxdeep,
	 const integer *maxdiv, integer *n, FILE *logfile,
	integer *cheat, doublereal *kmax, integer *ifeasiblef, integer jones)
{
    /* System generated locals */
    integer s_dim1, s_offset, length_dim1, length_offset, i__1;

    /* Local variables */
    integer i__, j, k;
    doublereal helplower;
    integer i___, j___;
    doublereal helpgreater;
    integer novaluedeep = 0;
    doublereal help2;
    integer novalue;

    /* Parameter adjustments */
    f -= 3;
    ++anchor;
    s_dim1 = *maxdiv;
    s_offset = 1 + s_dim1;
    s -= s_offset;
    length_dim1 = *n;
    length_offset = 1 + length_dim1;
    length -= length_offset;

    /* Function Body */
    helplower = HUGE_VAL;
    helpgreater = 0.;
    k = 1;
    if (*ifeasiblef >= 1) {
	i__1 = *actdeep;
	for (j = 0; j <= i__1; ++j) {
	    if (anchor[j] > 0) {
		s[k + s_dim1] = anchor[j];
		s[k + (s_dim1 << 1)] = direct_dirgetlevel_(&s[k + s_dim1], &length[
			length_offset], maxfunc, n, jones);
		goto L12;
	    }
/* L1001: */
	}
L12:
	++k;
	*maxpos = 1;
	return;
    } else {
	i__1 = *actdeep;
	for (j = 0; j <= i__1; ++j) {
	    if (anchor[j] > 0) {
		s[k + s_dim1] = anchor[j];
		s[k + (s_dim1 << 1)] = direct_dirgetlevel_(&s[k + s_dim1], &length[
			length_offset], maxfunc, n, jones);
		++k;
	    }
/* L10: */
	}
    }
    novalue = 0;
    if (anchor[-1] > 0) {
	novalue = anchor[-1];
	novaluedeep = direct_dirgetlevel_(&novalue, &length[length_offset], maxfunc, 
		n, jones);
    }
    *maxpos = k - 1;
    i__1 = *maxdeep;
    for (j = k - 1; j <= i__1; ++j) {
	s[k + s_dim1] = 0;
/* L11: */
    }
    for (j = *maxpos; j >= 1; --j) {
	helplower = HUGE_VAL;
	helpgreater = 0.;
	j___ = s[j + s_dim1];
	i__1 = j - 1;
	for (i__ = 1; i__ <= i__1; ++i__) {
	    i___ = s[i__ + s_dim1];
/* +-----------------------------------------------------------------------+ */
/* | JG 07/16/01 Changed IF statement into two to prevent run-time errors  | */
/* |             which could occur if the compiler checks the second       | */
/* |             expression in an .AND. statement although the first       | */
/* |             statement is already not true.                            | */
/* +-----------------------------------------------------------------------+ */
	    if (i___ > 0 && ! (i__ == j)) {
		if (f[(i___ << 1) + 2] <= 1.) {
		    help2 = thirds[s[i__ + (s_dim1 << 1)]] - thirds[s[j + (
			    s_dim1 << 1)]];
		    help2 = (f[(i___ << 1) + 1] - f[(j___ << 1) + 1]) / help2;
		    if (help2 <= 0.) {
			 if (logfile)
			      fprintf(logfile, "thirds > 0, help2 <= 0\n");
			goto L60;
		    }
		    if (help2 < helplower) {
			 if (logfile)
			      fprintf(logfile, "helplower = %g\n", help2);
			helplower = help2;
		    }
		}
	    }
/* L30: */
	}
	i__1 = *maxpos;
	for (i__ = j + 1; i__ <= i__1; ++i__) {
	    i___ = s[i__ + s_dim1];
/* +-----------------------------------------------------------------------+ */
/* | JG 07/16/01 Changed IF statement into two to prevent run-time errors  | */
/* |             which could occur if the compiler checks the second       | */
/* |             expression in an .AND. statement although the first       | */
/* |             statement is already not true.                            | */
/* +-----------------------------------------------------------------------+ */
	    if (i___ > 0 && ! (i__ == j)) {
		if (f[(i___ << 1) + 2] <= 1.) {
		    help2 = thirds[s[i__ + (s_dim1 << 1)]] - thirds[s[j + (
			    s_dim1 << 1)]];
		    help2 = (f[(i___ << 1) + 1] - f[(j___ << 1) + 1]) / help2;
		    if (help2 <= 0.) {
			if (logfile)
			     fprintf(logfile, "thirds < 0, help2 <= 0\n");
			goto L60;
		    }
		    if (help2 > helpgreater) {
			if (logfile)
                              fprintf(logfile, "helpgreater = %g\n", help2);
			helpgreater = help2;
		    }
		}
	    }
/* L31: */
	}
	if (helpgreater <= helplower) {
	    if (*cheat == 1 && helplower > *kmax) {
		helplower = *kmax;
	    }
	    if (f[(j___ << 1) + 1] - helplower * thirds[s[j + (s_dim1 << 1)]] >
		     MIN(*minf - epsrel * fabs(*minf), 
			 *minf - epsabs)) {
		if (logfile)
		     fprintf(logfile, "> minf - epslminfl\n");
		goto L60;
	    }
	} else {
	    if (logfile)
		 fprintf(logfile, "helpgreater > helplower: %g  %g  %g\n",
			 helpgreater, helplower, helpgreater - helplower);
	    goto L60;
	}
	goto L40;
L60:
	s[j + s_dim1] = 0;
L40:
	;
    }
    if (novalue > 0) {
	++(*maxpos);
	s[*maxpos + s_dim1] = novalue;
	s[*maxpos + (s_dim1 << 1)] = novaluedeep;
    }
} /* dirchoose_ */

/* +-----------------------------------------------------------------------+ */
/* |    SUBROUTINE DIRDoubleInsert                                         | */
/* |      Routine to make sure that if there are several potential optimal | */
/* |      hyperrectangles of the same level (i.e. hyperrectangles that have| */
/* |      the same level and the same function value at the center), all of| */
/* |      them are divided. This is the way as originally described in     | */
/* |      Jones et.al.                                                     | */
/* | JG 07/16/01 Added errorflag to calling sequence. We check if more     | */
/* |             we reach the capacity of the array S. If this happens, we | */
/* |             return to the main program with an error.                 | */
/* +-----------------------------------------------------------------------+ */
/* Subroutine */ void direct_dirdoubleinsert_(integer *anchor, integer *s, integer *
	maxpos, integer *point, doublereal *f, const integer *maxdeep, integer *
	maxfunc, const integer *maxdiv, integer *ierror)
{
    /* System generated locals */
    integer s_dim1, s_offset, i__1;

    /* Local variables */
    integer i__, oldmaxpos, pos, help, iflag, actdeep;

/* +-----------------------------------------------------------------------+ */
/* | JG 07/16/01 Added flag to prevent run time-errors on some systems.    | */
/* +-----------------------------------------------------------------------+ */
    /* Parameter adjustments */
    ++anchor;
    f -= 3;
    --point;
    s_dim1 = *maxdiv;
    s_offset = 1 + s_dim1;
    s -= s_offset;

    /* Function Body */
    oldmaxpos = *maxpos;
    i__1 = oldmaxpos;
    for (i__ = 1; i__ <= i__1; ++i__) {
	if (s[i__ + s_dim1] > 0) {
	    actdeep = s[i__ + (s_dim1 << 1)];
	    help = anchor[actdeep];
	    pos = point[help];
	    iflag = 0;
/* +-----------------------------------------------------------------------+ */
/* | JG 07/16/01 Added flag to prevent run time-errors on some systems. On | */
/* |             some systems the second conditions in an AND statement is | */
/* |             evaluated even if the first one is already not true.      | */
/* +-----------------------------------------------------------------------+ */
	    while(pos > 0 && iflag == 0) {
		if (f[(pos << 1) + 1] - f[(help << 1) + 1] <= 1e-13) {
		    if (*maxpos < *maxdiv) {
			++(*maxpos);
			s[*maxpos + s_dim1] = pos;
			s[*maxpos + (s_dim1 << 1)] = actdeep;
			pos = point[pos];
		    } else {
/* +-----------------------------------------------------------------------+ */
/* | JG 07/16/01 Maximum number of elements possible in S has been reached!| */
/* +-----------------------------------------------------------------------+ */
			*ierror = -6;
			return;
		    }
		} else {
		    iflag = 1;
		}
	    }
	}
/* L10: */
    }
} /* dirdoubleinsert_ */

/* +-----------------------------------------------------------------------+ */
/* | INTEGER Function GetmaxDeep                                           | */
/* | function to get the maximal length (1/length) of the n-dimensional    | */
/* | rectangle with midpoint pos.                                          | */
/* |                                                                       | */
/* | On Return :                                                           | */
/* |    the maximal length                                                 | */
/* |                                                                       | */
/* | pos     -- the position of the midpoint in the array length           | */
/* | length  -- the array with the dimensions                              | */
/* | maxfunc -- the leading dimension of length                            | */
/* | n	   -- the dimension of the problem                                  | */
/* |                                                                       | */
/* +-----------------------------------------------------------------------+ */
integer direct_dirgetmaxdeep_(integer *pos, integer *length, integer *maxfunc, 
	integer *n)
{
    /* System generated locals */
    integer length_dim1, length_offset, i__1, i__2, i__3;

    /* Local variables */
    integer i__, help;

    /* Parameter adjustments */
    length_dim1 = *n;
    length_offset = 1 + length_dim1;
    length -= length_offset;

    /* Function Body */
    help = length[*pos * length_dim1 + 1];
    i__1 = *n;
    for (i__ = 2; i__ <= i__1; ++i__) {
/* Computing MIN */
	i__2 = help, i__3 = length[i__ + *pos * length_dim1];
	help = MIN(i__2,i__3);
/* L10: */
    }
    return help;
} /* dirgetmaxdeep_ */

static integer isinbox_(doublereal *x, doublereal *a, doublereal *b, integer *n, 
	integer *lmaxdim)
{
    /* System generated locals */
    integer ret_val, i__1;

    /* Local variables */
    integer outofbox, i__;

    /* Parameter adjustments */
    --b;
    --a;
    --x;

    /* Function Body */
    outofbox = 1;
    i__1 = *n;
    for (i__ = 1; i__ <= i__1; ++i__) {
	if (a[i__] > x[i__] || b[i__] < x[i__]) {
	    outofbox = 0;
	    goto L1010;
	}
/* L1000: */
    }
L1010:
    ret_val = outofbox;
    return ret_val;
} /* isinbox_ */

/* +-----------------------------------------------------------------------+ */
/* | JG Added 09/25/00                                                     | */
/* |                                                                       | */
/* |                       SUBROUTINE DIRResortlist                        | */
/* |                                                                       | */
/* | Resort the list so that the infeasible point is in the list with the  | */
/* | replaced value.                                                       | */
/* +-----------------------------------------------------------------------+ */
/* Subroutine */ static void dirresortlist_(integer *replace, integer *anchor, 
	doublereal *f, integer *point, integer *length, integer *n, integer *
	maxfunc, integer *maxdim, const integer *maxdeep, FILE *logfile,
					    integer jones)
{
    /* System generated locals */
    integer length_dim1, length_offset, i__1;

    /* Local variables */
    integer i__, l, pos;
    integer start;

/* +-----------------------------------------------------------------------+ */
/* | Get the length of the hyper rectangle with infeasible mid point and   | */
/* | Index of the corresponding list.                                      | */
/* +-----------------------------------------------------------------------+ */
/* JG 09/25/00 Replaced with DIRgetlevel */
/*      l = DIRgetmaxDeep(replace,length,maxfunc,n) */
    /* Parameter adjustments */
    --point;
    f -= 3;
    length_dim1 = *n;
    length_offset = 1 + length_dim1;
    length -= length_offset;
    ++anchor;

    /* Function Body */
    l = direct_dirgetlevel_(replace, &length[length_offset], maxfunc, n, jones);
    start = anchor[l];
/* +-----------------------------------------------------------------------+ */
/* | If the hyper rectangle with infeasibel midpoint is already the start  | */
/* | of the list, give out message, nothing to do.                         | */
/* +-----------------------------------------------------------------------+ */
    if (*replace == start) {
/*         write(logfile,*) 'No resorting of list necessarry, since new ', */
/*     + 'point is already anchor of list .',l */
    } else {
/* +-----------------------------------------------------------------------+ */
/* | Take the hyper rectangle with infeasible midpoint out of the list.    | */
/* +-----------------------------------------------------------------------+ */
	pos = start;
	i__1 = *maxfunc;
	for (i__ = 1; i__ <= i__1; ++i__) {
	    if (point[pos] == *replace) {
		point[pos] = point[*replace];
		goto L20;
	    } else {
		pos = point[pos];
	    }
	    if (pos == 0) {
		if (logfile)
		     fprintf(logfile, "Error in DIRREsortlist: "
			     "We went through the whole list\n"
			     "and could not find the point to replace!!\n");
		goto L20;
	    }
/* L10: */
	}
/* +-----------------------------------------------------------------------+ */
/* | If the anchor of the list has a higher value than the value of a      | */
/* | nearby point, put the infeasible point at the beginning of the list.  | */
/* +-----------------------------------------------------------------------+ */
L20:
	if (f[(start << 1) + 1] > f[(*replace << 1) + 1]) {
	    anchor[l] = *replace;
	    point[*replace] = start;
/*            write(logfile,*) 'Point is replacing current anchor for ' */
/*     +             , 'this list ',l,replace,start */
	} else {
/* +-----------------------------------------------------------------------+ */
/* | Insert the point into the list according to its (replaced) function   | */
/* | value.                                                                | */
/* +-----------------------------------------------------------------------+ */
	    pos = start;
	    i__1 = *maxfunc;
	    for (i__ = 1; i__ <= i__1; ++i__) {
/* +-----------------------------------------------------------------------+ */
/* | The point has to be added at the end of the list.                     | */
/* +-----------------------------------------------------------------------+ */
		if (point[pos] == 0) {
		    point[*replace] = point[pos];
		    point[pos] = *replace;
/*                  write(logfile,*) 'Point is added at the end of the ' */
/*     +             , 'list ',l, replace */
		    goto L40;
		} else {
		    if (f[(point[pos] << 1) + 1] > f[(*replace << 1) + 1]) {
			point[*replace] = point[pos];
			point[pos] = *replace;
/*                     write(logfile,*) 'There are points with a higher ' */
/*     +               ,'f-value in the list ',l,replace, pos */
			goto L40;
		    }
		    pos = point[pos];
		}
/* L30: */
	    }
L40:
	    pos = pos;
	}
    }
} /* dirresortlist_ */

/* +-----------------------------------------------------------------------+ */
/* | JG Added 09/25/00                                                     | */
/* |                       SUBROUTINE DIRreplaceInf                        | */
/* |                                                                       | */
/* | Find out if there are infeasible points which are near feasible ones. | */
/* | If this is the case, replace the function value at the center of the  | */
/* | hyper rectangle by the lowest function value of a nearby function.    | */
/* +-----------------------------------------------------------------------+ */
/* Subroutine */ void direct_dirreplaceinf_(integer *free, integer *freeold, 
	doublereal *f, doublereal *c__, doublereal *thirds, integer *length, 
	integer *anchor, integer *point, doublereal *c1, doublereal *c2, 
	integer *maxfunc, const integer *maxdeep, integer *maxdim, integer *n, 
	FILE *logfile, doublereal *fmax, integer jones)
{
    /* System generated locals */
    integer c_dim1, c_offset, length_dim1, length_offset, i__1, i__2, i__3;
    doublereal d__1, d__2;

    /* Local variables */
    doublereal a[32], b[32];
    integer i__, j, k, l;
    doublereal x[32], sidelength;
    integer help;

/* +-----------------------------------------------------------------------+ */
/* | JG 01/22/01 Added variable to keep track of the maximum value found.  | */
/* +-----------------------------------------------------------------------+ */
    /* Parameter adjustments */
    --point;
    f -= 3;
    ++anchor;
    length_dim1 = *maxdim;
    length_offset = 1 + length_dim1;
    length -= length_offset;
    c_dim1 = *maxdim;
    c_offset = 1 + c_dim1;
    c__ -= c_offset;
    --c2;
    --c1;

    /* Function Body */
    i__1 = *free - 1;
    for (i__ = 1; i__ <= i__1; ++i__) {
	if (f[(i__ << 1) + 2] > 0.) {
/* +-----------------------------------------------------------------------+ */
/* | Get the maximum side length of the hyper rectangle and then set the   | */
/* | new side length to this lengths times the growth factor.              | */
/* +-----------------------------------------------------------------------+ */
	    help = direct_dirgetmaxdeep_(&i__, &length[length_offset], maxfunc, n);
	    sidelength = thirds[help] * 2.;
/* +-----------------------------------------------------------------------+ */
/* | Set the Center and the upper and lower bounds of the rectangles.      | */
/* +-----------------------------------------------------------------------+ */
	    i__2 = *n;
	    for (j = 1; j <= i__2; ++j) {
		sidelength = thirds[length[i__ + j * length_dim1]];
		a[j - 1] = c__[j + i__ * c_dim1] - sidelength;
		b[j - 1] = c__[j + i__ * c_dim1] + sidelength;
/* L20: */
	    }
/* +-----------------------------------------------------------------------+ */
/* | The function value is reset to 'Inf', since it may have been changed  | */
/* | in an earlier iteration and now the feasible point which was close    | */
/* | is not close anymore (since the hyper rectangle surrounding the       | */
/* | current point may have shrunk).                                       | */
/* +-----------------------------------------------------------------------+ */
	    f[(i__ << 1) + 1] = HUGE_VAL;
	    f[(i__ << 1) + 2] = 2.;
/* +-----------------------------------------------------------------------+ */
/* | Check if any feasible point is near this infeasible point.            | */
/* +-----------------------------------------------------------------------+ */
	    i__2 = *free - 1;
	    for (k = 1; k <= i__2; ++k) {
/* +-----------------------------------------------------------------------+ */
/* | If the point k is feasible, check if it is near.                      | */
/* +-----------------------------------------------------------------------+ */
		if (f[(k << 1) + 2] == 0.) {
/* +-----------------------------------------------------------------------+ */
/* | Copy the coordinates of the point k into x.                           | */
/* +-----------------------------------------------------------------------+ */
		    i__3 = *n;
		    for (l = 1; l <= i__3; ++l) {
			x[l - 1] = c__[l + k * c_dim1];
/* L40: */
		    }
/* +-----------------------------------------------------------------------+ */
/* | Check if the point k is near the infeasible point, if so, replace the | */
/* | value at */
/* +-----------------------------------------------------------------------+ */
		    if (isinbox_(x, a, b, n, &c__32) == 1) {
/* Computing MIN */
			 d__1 = f[(i__ << 1) + 1], d__2 = f[(k << 1) + 1];
			 f[(i__ << 1) + 1] = MIN(d__1,d__2);
			 f[(i__ << 1) + 2] = 1.; 
		    }
		}
/* L30: */
	    }
	    if (f[(i__ << 1) + 2] == 1.) {
		f[(i__ << 1) + 1] += (d__1 = f[(i__ << 1) + 1], fabs(d__1)) *
			1e-6f;
		i__2 = *n;
		for (l = 1; l <= i__2; ++l) {
		    x[l - 1] = c__[l + i__ * c_dim1] * c1[l] + c__[l + i__ *
			    c_dim1] * c2[l];
/* L200: */
		}
		dirresortlist_(&i__, &anchor[-1], &f[3], &point[1], 
			       &length[length_offset], n, 
			       maxfunc, maxdim, maxdeep, logfile, jones);
	    } else {
/* +-----------------------------------------------------------------------+ */
/* | JG 01/22/01                                                           | */
/* | Replaced fixed value for infeasible points with maximum value found,  | */
/* | increased by 1.                                                       | */
/* +-----------------------------------------------------------------------+ */
		if (! (*fmax == f[(i__ << 1) + 1])) {
/* Computing MAX */
		    d__1 = *fmax + 1., d__2 = f[(i__ << 1) + 1];
		    f[(i__ << 1) + 1] = MAX(d__1,d__2);
		}
	    }
	}
/* L10: */
    }
/* L1000: */
} /* dirreplaceinf_ */

/* +-----------------------------------------------------------------------+ */
/* |    SUBROUTINE DIRInsert                                               | */
/* +-----------------------------------------------------------------------+ */
/* Subroutine */ static void dirinsert_(integer *start, integer *ins, integer *point, 
	doublereal *f, integer *maxfunc)
{
    /* System generated locals */
    integer i__1;

    /* Local variables */
    integer i__, help;

/* JG 09/17/00 Rewrote this routine. */
/*      DO 10,i = 1,maxfunc */
/*        IF (f(ins,1) .LT. f(point(start),1)) THEN */
/*          help = point(start) */
/*          point(start) = ins */
/*          point(ins) = help */
/*          GOTO 20 */
/*        END IF */
/*        IF (point(start) .EQ. 0) THEN */
/*           point(start) = ins */
/*           point(ins) = 0 */
/*           GOTO 20 */
/*        END IF */
/*        start = point(start) */
/* 10    CONTINUE */
/* 20    END */
    /* Parameter adjustments */
    f -= 3;
    --point;

    /* Function Body */
    i__1 = *maxfunc;
    for (i__ = 1; i__ <= i__1; ++i__) {
	if (point[*start] == 0) {
	    point[*start] = *ins;
	    point[*ins] = 0;
	    return;
	} else if (f[(*ins << 1) + 1] < f[(point[*start] << 1) + 1]) {
	     help = point[*start];
	     point[*start] = *ins;
	     point[*ins] = help;
	     return;
	}
	*start = point[*start];
/* L10: */
    }
} /* dirinsert_ */

/* +-----------------------------------------------------------------------+ */
/* |    SUBROUTINE DIRInsertList                                           | */
/* |    Changed 02-24-2000                                                 | */
/* |      Got rid of the distinction between feasible and infeasible points| */
/* |      I could do this since infeasible points get set to a high        | */
/* |      function value, which may be replaced by a function value of a   | */
/* |      nearby function at the end of the main loop.                     | */
/* +-----------------------------------------------------------------------+ */
/* Subroutine */ void direct_dirinsertlist_(integer *new__, integer *anchor, integer *
	point, doublereal *f, integer *maxi, integer *length, integer *
	maxfunc, const integer *maxdeep, integer *n, integer *samp,
					    integer jones)
{
    /* System generated locals */
    integer length_dim1, length_offset, i__1;

    /* Local variables */
    integer j;
    integer pos;
    integer pos1, pos2, deep;

/* JG 09/24/00 Changed this to Getlevel */
    /* Parameter adjustments */
    f -= 3;
    --point;
    ++anchor;
    length_dim1 = *n;
    length_offset = 1 + length_dim1;
    length -= length_offset;

    /* Function Body */
    i__1 = *maxi;
    for (j = 1; j <= i__1; ++j) {
	pos1 = *new__;
	pos2 = point[pos1];
	*new__ = point[pos2];
/* JG 09/24/00 Changed this to Getlevel */
/*        deep = DIRGetMaxdeep(pos1,length,maxfunc,n) */
	deep = direct_dirgetlevel_(&pos1, &length[length_offset], maxfunc, n, jones);
	if (anchor[deep] == 0) {
	    if (f[(pos2 << 1) + 1] < f[(pos1 << 1) + 1]) {
		anchor[deep] = pos2;
		point[pos2] = pos1;
		point[pos1] = 0;
	    } else {
		anchor[deep] = pos1;
		point[pos2] = 0;
	    }
	} else {
	    pos = anchor[deep];
	    if (f[(pos2 << 1) + 1] < f[(pos1 << 1) + 1]) {
		if (f[(pos2 << 1) + 1] < f[(pos << 1) + 1]) {
		    anchor[deep] = pos2;
/* JG 08/30/00 Fixed bug. Sorting was not correct when */
/*      f(1,pos2) < f(1,pos1) < f(1,pos) */
		    if (f[(pos1 << 1) + 1] < f[(pos << 1) + 1]) {
			point[pos2] = pos1;
			point[pos1] = pos;
		    } else {
			point[pos2] = pos;
			dirinsert_(&pos, &pos1, &point[1], &f[3], maxfunc);
		    }
		} else {
		    dirinsert_(&pos, &pos2, &point[1], &f[3], maxfunc);
		    dirinsert_(&pos, &pos1, &point[1], &f[3], maxfunc);
		}
	    } else {
		if (f[(pos1 << 1) + 1] < f[(pos << 1) + 1]) {
/* JG 08/30/00 Fixed bug. Sorting was not correct when */
/*      f(pos1,1) < f(pos2,1) < f(pos,1) */
		    anchor[deep] = pos1;
		    if (f[(pos << 1) + 1] < f[(pos2 << 1) + 1]) {
			point[pos1] = pos;
			dirinsert_(&pos, &pos2, &point[1], &f[3], maxfunc);
		    } else {
			point[pos1] = pos2;
			point[pos2] = pos;
		    }
		} else {
		    dirinsert_(&pos, &pos1, &point[1], &f[3], maxfunc);
		    dirinsert_(&pos, &pos2, &point[1], &f[3], maxfunc);
		}
	    }
	}
/* L10: */
    }
/* JG 09/24/00 Changed this to Getlevel */
/*      deep = DIRGetMaxdeep(samp,length,maxfunc,n) */
    deep = direct_dirgetlevel_(samp, &length[length_offset], maxfunc, n, jones);
    pos = anchor[deep];
    if (f[(*samp << 1) + 1] < f[(pos << 1) + 1]) {
	anchor[deep] = *samp;
	point[*samp] = pos;
    } else {
	dirinsert_(&pos, samp, &point[1], &f[3], maxfunc);
    }
} /* dirinsertlist_ */

/* +-----------------------------------------------------------------------+ */
/* |    SUBROUTINE DIRInsertList2  (Old way to do it.)                     | */
/* +-----------------------------------------------------------------------+ */
/* Subroutine */ static void dirinsertlist_2__(integer *start, integer *j, integer *k,
	 integer *list2, doublereal *w, integer *maxi, integer *n)
{
    /* System generated locals */
    integer list2_dim1, list2_offset, i__1;

    /* Local variables */
    integer i__, pos;

    /* Parameter adjustments */
    --w;
    list2_dim1 = *n;
    list2_offset = 1 + list2_dim1;
    list2 -= list2_offset;

    /* Function Body */
    pos = *start;
    if (*start == 0) {
	list2[*j + list2_dim1] = 0;
	*start = *j;
	goto L50;
    }
    if (w[*start] > w[*j]) {
	list2[*j + list2_dim1] = *start;
	*start = *j;
    } else {
	i__1 = *maxi;
	for (i__ = 1; i__ <= i__1; ++i__) {
	    if (list2[pos + list2_dim1] == 0) {
		list2[*j + list2_dim1] = 0;
		list2[pos + list2_dim1] = *j;
		goto L50;
	    } else {
		if (w[*j] < w[list2[pos + list2_dim1]]) {
		    list2[*j + list2_dim1] = list2[pos + list2_dim1];
		    list2[pos + list2_dim1] = *j;
		    goto L50;
		}
	    }
	    pos = list2[pos + list2_dim1];
/* L10: */
	}
    }
L50:
    list2[*j + (list2_dim1 << 1)] = *k;
} /* dirinsertlist_2__ */

/* +-----------------------------------------------------------------------+ */
/* |    SUBROUTINE DIRSearchmin                                            | */
/* |    Search for the minimum in the list.                                ! */
/* +-----------------------------------------------------------------------+ */
/* Subroutine */ static void dirsearchmin_(integer *start, integer *list2, integer *
	pos, integer *k, integer *n)
{
    /* System generated locals */
    integer list2_dim1, list2_offset;

    /* Parameter adjustments */
    list2_dim1 = *n;
    list2_offset = 1 + list2_dim1;
    list2 -= list2_offset;

    /* Function Body */
    *k = *start;
    *pos = list2[*start + (list2_dim1 << 1)];
    *start = list2[*start + list2_dim1];
} /* dirsearchmin_ */

/* +-----------------------------------------------------------------------+ */
/* |    SUBROUTINE DIRSamplepoints                                         | */
/* |    Subroutine to sample the new points.                               | */
/* +-----------------------------------------------------------------------+ */
/* Subroutine */ void direct_dirsamplepoints_(doublereal *c__, integer *arrayi, 
	doublereal *delta, integer *sample, integer *start, integer *length, 
	FILE *logfile, doublereal *f, integer *free, 
	integer *maxi, integer *point, doublereal *x, doublereal *l,
	 doublereal *minf, integer *minpos, doublereal *u, integer *n, 
	integer *maxfunc, const integer *maxdeep, integer *oops)
{
    /* System generated locals */
    integer length_dim1, length_offset, c_dim1, c_offset, i__1, i__2;

    /* Local variables */
    integer j, k, pos;


    /* Parameter adjustments */
    --u;
    --l;
    --x;
    --arrayi;
    --point;
    f -= 3;
    length_dim1 = *n;
    length_offset = 1 + length_dim1;
    length -= length_offset;
    c_dim1 = *n;
    c_offset = 1 + c_dim1;
    c__ -= c_offset;

    /* Function Body */
    *oops = 0;
    pos = *free;
    *start = *free;
    i__1 = *maxi + *maxi;
    for (k = 1; k <= i__1; ++k) {
	i__2 = *n;
	for (j = 1; j <= i__2; ++j) {
	    length[j + *free * length_dim1] = length[j + *sample *
		    length_dim1];
	    c__[j + *free * c_dim1] = c__[j + *sample * c_dim1];
/* L20: */
	}
	pos = *free;
	*free = point[*free];
	if (*free == 0) {
	     if (logfile)
		  fprintf(logfile, "Error, no more free positions! "
			  "Increase maxfunc!\n");
	    *oops = 1;
	    return;
	}
/* L10: */
    }
    point[pos] = 0;
    pos = *start;
    i__1 = *maxi;
    for (j = 1; j <= i__1; ++j) {
	c__[arrayi[j] + pos * c_dim1] = c__[arrayi[j] + *sample * c_dim1] + *
		delta;
	pos = point[pos];
	c__[arrayi[j] + pos * c_dim1] = c__[arrayi[j] + *sample * c_dim1] - *
		delta;
	pos = point[pos];
/* L30: */
    }
    ASRT(pos <= 0);
} /* dirsamplepoints_ */

/* +-----------------------------------------------------------------------+ */
/* |    SUBROUTINE DIRDivide                                               | */
/* |    Subroutine to divide the hyper rectangles according to the rules.  | */
/* |    Changed 02-24-2000                                                 | */
/* |      Replaced if statement by min (line 367)                          | */
/* +-----------------------------------------------------------------------+ */
/* Subroutine */ void direct_dirdivide_(integer *new__, integer *currentlength, 
	integer *length, integer *point, integer *arrayi, integer *sample, 
	integer *list2, doublereal *w, integer *maxi, doublereal *f, integer *
	maxfunc, const integer *maxdeep, integer *n)
{
    /* System generated locals */
    integer length_dim1, length_offset, list2_dim1, list2_offset, i__1, i__2;
    doublereal d__1, d__2;

    /* Local variables */
    integer i__, j, k, pos, pos2;
    integer start;


    /* Parameter adjustments */
    f -= 3;
    --point;
    --w;
    list2_dim1 = *n;
    list2_offset = 1 + list2_dim1;
    list2 -= list2_offset;
    --arrayi;
    length_dim1 = *n;
    length_offset = 1 + length_dim1;
    length -= length_offset;

    /* Function Body */
    start = 0;
    pos = *new__;
    i__1 = *maxi;
    for (i__ = 1; i__ <= i__1; ++i__) {
	j = arrayi[i__];
	w[j] = f[(pos << 1) + 1];
	k = pos;
	pos = point[pos];
/* Computing MIN */
	d__1 = f[(pos << 1) + 1], d__2 = w[j];
	w[j] = MIN(d__1,d__2);
	pos = point[pos];
	dirinsertlist_2__(&start, &j, &k, &list2[list2_offset], &w[1], maxi, 
		n);
/* L10: */
    }
    ASRT(pos <= 0);
    i__1 = *maxi;
    for (j = 1; j <= i__1; ++j) {
	dirsearchmin_(&start, &list2[list2_offset], &pos, &k, n);
	pos2 = start;
	length[k + *sample * length_dim1] = *currentlength + 1; 
	i__2 = *maxi - j + 1;
	for (i__ = 1; i__ <= i__2; ++i__) {
	    length[k + pos * length_dim1] = *currentlength + 1; 
	    pos = point[pos];
	    length[k + pos * length_dim1] = *currentlength + 1;
/* JG 07/10/01 pos2 = 0 at the end of the 30-loop. Since we end */
/*             the loop now, we do not need to reassign pos and pos2. */
	    if (pos2 > 0) {
		pos = list2[pos2 + (list2_dim1 << 1)];
		pos2 = list2[pos2 + list2_dim1];
	    }
/* L30: */
	}
/* L20: */
    }
} /* dirdivide_ */

/* +-----------------------------------------------------------------------+ */
/* |                                                                       | */
/* |                       SUBROUTINE DIRINFCN                             | */
/* |                                                                       | */
/* | Subroutine DIRinfcn unscales the variable x for use in the            | */
/* | user-supplied function evaluation subroutine fcn. After fcn returns   | */
/* | to DIRinfcn, DIRinfcn then rescales x for use by DIRECT.              | */
/* |                                                                       | */
/* | On entry                                                              | */
/* |                                                                       | */
/* |        fcn -- The argument containing the name of the user-supplied   | */
/* |               subroutine that returns values for the function to be   | */
/* |               minimized.                                              | */
/* |                                                                       | */
/* |          x -- A double-precision vector of length n. The point at     | */
/* |               which the derivative is to be evaluated.                | */
/* |                                                                       | */
/* |        xs1 -- A double-precision vector of length n. Used for         | */
/* |               scaling and unscaling the vector x by DIRinfcn.         | */
/* |                                                                       | */
/* |        xs2 -- A double-precision vector of length n. Used for         | */
/* |               scaling and unscaling the vector x by DIRinfcn.         | */
/* |                                                                       | */
/* |          n -- An integer. The dimension of the problem.               | */
/* |       kret -- An Integer. If kret =  1, the point is infeasible,      | */
/* |                              kret = -1, bad problem set up,           | */
/* |                              kret =  0, feasible.                     | */
/* |                                                                       | */
/* | On return                                                             | */
/* |                                                                       | */
/* |          f -- A double-precision scalar.                              | */
/* |                                                                       | */
/* | Subroutines and Functions                                             | */
/* |                                                                       | */
/* | The subroutine whose name is passed through the argument fcn.         | */
/* |                                                                       | */
/* +-----------------------------------------------------------------------+ */
/* Subroutine */ void direct_dirinfcn_(fp fcn, doublereal *x, doublereal *c1, 
	doublereal *c2, integer *n, doublereal *f, integer *flag__, 
				       void *fcn_data)
{
    /* System generated locals */
    integer i__1;

    /* Local variables */
    integer i__;

/* +-----------------------------------------------------------------------+ */
/* | Variables to pass user defined data to the function to be optimized.  | */
/* +-----------------------------------------------------------------------+ */
/* +-----------------------------------------------------------------------+ */
/* | Unscale the variable x.                                               | */
/* +-----------------------------------------------------------------------+ */
    /* Parameter adjustments */
    --c2;
    --c1;
    --x;

    /* Function Body */
    i__1 = *n;
    for (i__ = 1; i__ <= i__1; ++i__) {
	x[i__] = (x[i__] + c2[i__]) * c1[i__];
/* L20: */
    }
/* +-----------------------------------------------------------------------+ */
/* | Call the function-evaluation subroutine fcn.                          | */
/* +-----------------------------------------------------------------------+ */
    *flag__ = 0;
    *f = fcn(*n, &x[1], flag__, fcn_data);
/* +-----------------------------------------------------------------------+ */
/* | Rescale the variable x.                                               | */
/* +-----------------------------------------------------------------------+ */
    i__1 = *n;
    for (i__ = 1; i__ <= i__1; ++i__) {
	x[i__] = x[i__] / c1[i__] - c2[i__];
/* L30: */
    }
} /* dirinfcn_ */

/* +-----------------------------------------------------------------------+ */
/* |    SUBROUTINE DIRGet_I                                                | */
/* +-----------------------------------------------------------------------+ */
/* Subroutine */ void direct_dirget_i__(integer *length, integer *pos, integer *
	arrayi, integer *maxi, integer *n, integer *maxfunc)
{
    /* System generated locals */
    integer length_dim1, length_offset, i__1;

    /* Local variables */
    integer i__, j, help;

    /* Parameter adjustments */
    --arrayi;
    length_dim1 = *n;
    length_offset = 1 + length_dim1;
    length -= length_offset;

    /* Function Body */
    j = 1;
    help = length[*pos * length_dim1 + 1];
    i__1 = *n;
    for (i__ = 2; i__ <= i__1; ++i__) {
	if (length[i__ + *pos * length_dim1] < help) {
	    help = length[i__ + *pos * length_dim1];
	}
/* L10: */
    }
    i__1 = *n;
    for (i__ = 1; i__ <= i__1; ++i__) {
	if (length[i__ + *pos * length_dim1] == help) {
	    arrayi[j] = i__;
	    ++j;
	}
/* L20: */
    }
    *maxi = j - 1;
} /* dirget_i__ */

/* +-----------------------------------------------------------------------+ */
/* |    SUBROUTINE DIRInit                                                 | */
/* |    Initialise all needed variables and do the first run of the        | */
/* |    algorithm.                                                         | */
/* |    Changed 02/24/2000                                                 | */
/* |       Changed fcn Double precision to fcn external!                   | */
/* |    Changed 09/15/2000                                                 | */
/* |       Added distinction between Jones way to characterize rectangles  | */
/* |       and our way. Common variable JONES controls which way we use.   | */
/* |          JONES = 0    Jones way (Distance from midpoint to corner)    | */
/* |          JONES = 1    Our way (Length of longest side)                | */
/* |    Changed 09/24/00                                                   | */
/* |       Added array levels. Levels contain the values to characterize   | */
/* |       the hyperrectangles.                                            | */
/* |    Changed 01/22/01                                                   | */
/* |       Added variable fmax to keep track of maximum value found.       | */
/* |       Added variable Ifeasiblef to keep track if feasibel point has   | */
/* |       been found.                                                     | */
/* |    Changed 01/23/01                                                   | */
/* |       Added variable Ierror to keep track of errors.                  | */
/* +-----------------------------------------------------------------------+ */
/* Subroutine */ void direct_dirinit_(doublereal *f, fp fcn, doublereal *c__, 
	integer *length, integer *actdeep, integer *point, integer *anchor, 
	integer *free, FILE *logfile, integer *arrayi, 
	integer *maxi, integer *list2, doublereal *w, doublereal *x, 
	doublereal *l, doublereal *u, doublereal *minf, integer *minpos, 
	doublereal *thirds, doublereal *levels, integer *maxfunc, const integer *
	maxdeep, integer *n, integer *maxor, doublereal *fmax, integer *
	ifeasiblef, integer *iinfeasible, integer *ierror, void *fcndata,
	integer jones, double starttime, double maxtime, int *force_stop)
{
    /* System generated locals */
    integer c_dim1, c_offset, length_dim1, length_offset, list2_dim1, 
	    list2_offset, i__1, i__2;

    /* Local variables */
    integer i__, j;
    integer new__, help, oops;
    doublereal help2, delta;
    doublereal costmin;

/* +-----------------------------------------------------------------------+ */
/* | JG 01/22/01 Added variable to keep track of the maximum value found.  | */
/* +-----------------------------------------------------------------------+ */
/* +-----------------------------------------------------------------------+ */
/* | JG 01/22/01 Added variable Ifeasiblef to keep track if feasibel point | */
/* |             has been found.                                           | */
/* | JG 01/23/01 Added variable Ierror to keep track of errors.            | */
/* | JG 03/09/01 Added IInfeasible to keep track if an infeasible point has| */
/* |             been found.                                               | */
/* +-----------------------------------------------------------------------+ */
/* JG 09/15/00 Added variable JONES (see above) */
/* +-----------------------------------------------------------------------+ */
/* | Variables to pass user defined data to the function to be optimized.  | */
/* +-----------------------------------------------------------------------+ */
    /* Parameter adjustments */
    --point;
    f -= 3;
    ++anchor;
    --u;
    --l;
    --x;
    --w;
    list2_dim1 = *maxor;
    list2_offset = 1 + list2_dim1;
    list2 -= list2_offset;
    --arrayi;
    length_dim1 = *n;
    length_offset = 1 + length_dim1;
    length -= length_offset;
    c_dim1 = *maxor;
    c_offset = 1 + c_dim1;
    c__ -= c_offset;

    /* Function Body */
    *minf = HUGE_VAL;
    costmin = *minf;
/* JG 09/15/00 If Jones way of characterising rectangles is used, */
/*             initialise thirds to reflect this. */
    if (jones == 0) {
	i__1 = *n - 1;
	for (j = 0; j <= i__1; ++j) {
	    w[j + 1] = sqrt(*n - j + j / 9.) * .5;
/* L5: */
	}
	help2 = 1.;
	i__1 = *maxdeep / *n;
	for (i__ = 1; i__ <= i__1; ++i__) {
	    i__2 = *n - 1;
	    for (j = 0; j <= i__2; ++j) {
		levels[(i__ - 1) * *n + j] = w[j + 1] / help2;
/* L8: */
	    }
	    help2 *= 3.;
/* L10: */
	}
    } else {
/* JG 09/15/00 Initialiase levels to contain 1/j */
	help2 = 3.;
	i__1 = *maxdeep;
	for (i__ = 1; i__ <= i__1; ++i__) {
	    levels[i__] = 1. / help2;
	    help2 *= 3.;
/* L11: */
	}
	levels[0] = 1.;
    }
    help2 = 3.;
    i__1 = *maxdeep;
    for (i__ = 1; i__ <= i__1; ++i__) {
	thirds[i__] = 1. / help2;
	help2 *= 3.;
/* L21: */
    }
    thirds[0] = 1.;
    i__1 = *n;
    for (i__ = 1; i__ <= i__1; ++i__) {
	c__[i__ + c_dim1] = .5;
	x[i__] = .5;
	length[i__ + length_dim1] = 0;
/* L20: */
    }
    direct_dirinfcn_(fcn, &x[1], &l[1], &u[1], n, &f[3], &help, fcndata);
    if (force_stop && *force_stop) {
	 *ierror = -102;
	 return;
    }
    f[4] = (doublereal) help;
    *iinfeasible = help;
    *fmax = f[3];
/* 09/25/00 Added this */
/*      if (f(1,1) .ge. 1.E+6) then */
    if (f[4] > 0.) {
	f[3] = HUGE_VAL;
	*fmax = f[3];
	*ifeasiblef = 1;
    } else {
	*ifeasiblef = 0;
    }
/* JG 09/25/00 Remove IF */
    *minf = f[3];
    costmin = f[3];
    *minpos = 1;
    *actdeep = 2;
    point[1] = 0;
    *free = 2;
    delta = thirds[1];
    if (nlopt_stop_time_(starttime, maxtime)) {
	 *ierror = DIRECT_MAXTIME_EXCEEDED;
	 return;
    }
    direct_dirget_i__(&length[length_offset], &c__1, &arrayi[1], maxi, n, maxfunc);
    new__ = *free;
    direct_dirsamplepoints_(&c__[c_offset], &arrayi[1], &delta, &c__1, &new__, &
	    length[length_offset], logfile, &f[3], free, maxi, &
	    point[1], &x[1], &l[1], minf, minpos, &u[1], n, 
	    maxfunc, maxdeep, &oops);
/* +-----------------------------------------------------------------------+ */
/* | JG 01/23/01 Added error checking.                                     | */
/* +-----------------------------------------------------------------------+ */
    if (oops > 0) {
	*ierror = -4;
	return;
    }
/* +-----------------------------------------------------------------------+ */
/* | JG 01/22/01 Added variable to keep track of the maximum value found.  | */
/* |             Added variable to keep track if feasible point was found. | */
/* +-----------------------------------------------------------------------+ */
    direct_dirsamplef_(&c__[c_offset], &arrayi[1], &delta, &c__1, &new__, &length[
	    length_offset], logfile, &f[3], free, maxi, &point[
	    1], fcn, &x[1], &l[1], minf, minpos, &u[1], n, maxfunc, 
	    maxdeep, &oops, fmax, ifeasiblef, iinfeasible, fcndata,
	    force_stop);
    if (force_stop && *force_stop) {
	 *ierror = -102;
	 return;
    }
    if (nlopt_stop_time_(starttime, maxtime)) {
	 *ierror = DIRECT_MAXTIME_EXCEEDED;
	 return;
    }
/* +-----------------------------------------------------------------------+ */
/* | JG 01/23/01 Added error checking.                                     | */
/* +-----------------------------------------------------------------------+ */
    if (oops > 0) {
	*ierror = -5;
	return;
    }
    direct_dirdivide_(&new__, &c__0, &length[length_offset], &point[1], &arrayi[1], &
	    c__1, &list2[list2_offset], &w[1], maxi, &f[3], maxfunc, 
	    maxdeep, n);
    direct_dirinsertlist_(&new__, &anchor[-1], &point[1], &f[3], maxi, &
	    length[length_offset], maxfunc, maxdeep, n, &c__1, jones);
} /* dirinit_ */

/* +-----------------------------------------------------------------------+ */
/* |    SUBROUTINE DIRInitList                                             | */
/* |    Initialise the list.                                               | */
/* +-----------------------------------------------------------------------+ */
/* Subroutine */ void direct_dirinitlist_(integer *anchor, integer *free, integer *
	point, doublereal *f, integer *maxfunc, const integer *maxdeep)
{
    /* System generated locals */
    integer i__1;

    /* Local variables */
    integer i__;

/*   f -- values of functions. */
/*   anchor -- anchors of lists with deep i */
/*   point -- lists */
/*   free  -- first free position */
    /* Parameter adjustments */
    f -= 3;
    --point;
    ++anchor;

    /* Function Body */
    i__1 = *maxdeep;
    for (i__ = -1; i__ <= i__1; ++i__) {
	anchor[i__] = 0;
/* L10: */
    }
    i__1 = *maxfunc;
    for (i__ = 1; i__ <= i__1; ++i__) {
	f[(i__ << 1) + 1] = 0.;
	f[(i__ << 1) + 2] = 0.;
	point[i__] = i__ + 1;
/*       point(i) = 0 */
/* L20: */
    }
    point[*maxfunc] = 0;
    *free = 1;
} /* dirinitlist_ */

/* +-----------------------------------------------------------------------+ */
/* |                                                                       | */
/* |                       SUBROUTINE DIRPREPRC                            | */
/* |                                                                       | */
/* | Subroutine DIRpreprc uses an afine mapping to map the hyper-box given | */
/* | by the constraints on the variable x onto the n-dimensional unit cube.| */
/* | This mapping is done using the following equation:                    | */
/* |                                                                       | */
/* |               x(i)=x(i)/(u(i)-l(i))-l(i)/(u(i)-l(i)).                 | */
/* |                                                                       | */
/* | DIRpreprc checks if the bounds l and u are well-defined. That is, if  | */
/* |                                                                       | */
/* |               l(i) < u(i) forevery i.                                 | */
/* |                                                                       | */
/* | On entry                                                              | */
/* |                                                                       | */
/* |          u -- A double-precision vector of length n. The vector       | */
/* |               containing the upper bounds for the n independent       | */
/* |               variables.                                              | */
/* |                                                                       | */
/* |          l -- A double-precision vector of length n. The vector       | */
/* |               containing the lower bounds for the n independent       | */
/* |               variables.                                              | */
/* |                                                                       | */
/* |          n -- An integer. The dimension of the problem.               | */
/* |                                                                       | */
/* | On return                                                             | */
/* |                                                                       | */
/* |        xs1 -- A double-precision vector of length n, used for scaling | */
/* |               and unscaling the vector x.                             | */
/* |                                                                       | */
/* |        xs2 -- A double-precision vector of length n, used for scaling | */
/* |               and unscaling the vector x.                             | */
/* |                                                                       | */
/* |                                                                       | */
/* |       oops -- An integer. If an upper bound is less than a lower      | */
/* |               bound or if the initial point is not in the             | */
/* |               hyper-box oops is set to 1 and iffco terminates.        | */
/* |                                                                       | */
/* +-----------------------------------------------------------------------+ */
/* Subroutine */ void direct_dirpreprc_(doublereal *u, doublereal *l, integer *n, 
	doublereal *xs1, doublereal *xs2, integer *oops)
{
    /* System generated locals */
    integer i__1;

    /* Local variables */
    integer i__;
    doublereal help;

    /* Parameter adjustments */
    --xs2;
    --xs1;
    --l;
    --u;

    /* Function Body */
    *oops = 0;
    i__1 = *n;
    for (i__ = 1; i__ <= i__1; ++i__) {
/* +-----------------------------------------------------------------------+ */
/* | Check if the hyper-box is well-defined.                               | */
/* +-----------------------------------------------------------------------+ */
	if (u[i__] <= l[i__]) {
	    *oops = 1;
	    return;
	}
/* L20: */
    }
/* +-----------------------------------------------------------------------+ */
/* | Scale the initial iterate so that it is in the unit cube.             | */
/* +-----------------------------------------------------------------------+ */
    i__1 = *n;
    for (i__ = 1; i__ <= i__1; ++i__) {
	help = u[i__] - l[i__];
	xs2[i__] = l[i__] / help;
	xs1[i__] = help;
/* L50: */
    }
} /* dirpreprc_ */

/* Subroutine */ void direct_dirheader_(FILE *logfile, integer *version, 
	doublereal *x, integer *n, doublereal *eps, integer *maxf, integer *
	maxt, doublereal *l, doublereal *u, integer *algmethod, integer *
	maxfunc, const integer *maxdeep, doublereal *fglobal, doublereal *fglper, 
	integer *ierror, doublereal *epsfix, integer *iepschange, doublereal *
	volper, doublereal *sigmaper)
{
    /* System generated locals */
    integer i__1;

    /* Local variables */
    integer imainver, i__, numerrors, isubsubver, ihelp, isubver;


/* +-----------------------------------------------------------------------+ */
/* | Variables to pass user defined data to the function to be optimized.  | */
/* +-----------------------------------------------------------------------+ */
    /* Parameter adjustments */
    --u;
    --l;
    --x;

    /* Function Body */
    if (logfile)
	 fprintf(logfile, "------------------- Log file ------------------\n");

    numerrors = 0;
    *ierror = 0;
    imainver = *version / 100;
    ihelp = *version - imainver * 100;
    isubver = ihelp / 10;
    ihelp -= isubver * 10;
    isubsubver = ihelp;
/* +-----------------------------------------------------------------------+ */
/* | JG 01/13/01 Added check for epsilon. If epsilon is smaller 0, we use  | */
/* |             the update formula from Jones. We then set the flag       | */
/* |             iepschange to 1, and store the absolute value of eps in   | */
/* |             epsfix. epsilon is then changed after each iteration.     | */
/* +-----------------------------------------------------------------------+ */
    if (*eps < 0.) {
	*iepschange = 1;
	*epsfix = -(*eps);
	*eps = -(*eps);
    } else {
	*iepschange = 0;
	*epsfix = 1e100;
    }

/* +-----------------------------------------------------------------------+ */
/* | JG 07/16/01 Removed printout of contents in cdata(1).                 | */
/* +-----------------------------------------------------------------------+ */
/*      write(logfile,*) cdata(1) */

    if (logfile) {
	 fprintf(logfile, "DIRECT Version %d.%d.%d\n"
		 " Problem dimension n: %d\n"
		 " Eps value: %e\n"
		 " Maximum number of f-evaluations (maxf): %d\n"
		 " Maximum number of iterations (MaxT): %d\n"
		 " Value of f_global: %e\n"
		 " Global percentage wanted: %e\n"
		 " Volume percentage wanted: %e\n"
		 " Measure percentage wanted: %e\n",
		 imainver, isubver, isubsubver, *n, *eps, *maxf, *maxt,
		 *fglobal, *fglper, *volper, *sigmaper);
	 fprintf(logfile, *iepschange == 1 
		 ? "Epsilon is changed using the Jones formula.\n" 
		 : "Epsilon is constant.\n");
	 fprintf(logfile, *algmethod == 0
		 ? "Jones original DIRECT algorithm is used.\n"
		 : "Our modification of the DIRECT algorithm is used.\n");
    }

    i__1 = *n;
    for (i__ = 1; i__ <= i__1; ++i__) {
	if (u[i__] <= l[i__]) {
	    *ierror = -1;
	    if (logfile)
		 fprintf(logfile, "WARNING: bounds on variable x%d: "
			 "%g <= xi <= %g\n", i__, l[i__], u[i__]);
	    ++numerrors;
	} else {
	    if (logfile)
		 fprintf(logfile, "Bounds on variable x%d: "
			 "%g <= xi <= %g\n", i__, l[i__], u[i__]);
	}
/* L1010: */
    }
/* +-----------------------------------------------------------------------+ */
/* | If there are to many function evaluations or to many iteration, note  | */
/* | this and set the error flag accordingly. Note: If more than one error | */
/* | occurred, we give out an extra message.                               | */
/* +-----------------------------------------------------------------------+ */
    if (*maxf + 20 > *maxfunc) {
	if (logfile)
	     fprintf(logfile,
"WARNING: The maximum number of function evaluations (%d) is higher than\n"
"         the constant maxfunc (%d).  Increase maxfunc in subroutine DIRECT\n"
"         or decrease the maximum number of function evaluations.\n",
		     *maxf, *maxfunc);
	++numerrors;
	*ierror = -2;
    }
    if (*ierror < 0) {
	if (logfile) fprintf(logfile, "----------------------------------\n");
	if (numerrors == 1) {
	     if (logfile) 
		  fprintf(logfile, "WARNING: One error in the input!\n");
	} else {
	     if (logfile) 
		  fprintf(logfile, "WARNING: %d errors in the input!\n",
			  numerrors);
	}
    }
    if (logfile) fprintf(logfile, "----------------------------------\n");
    if (*ierror >= 0) {
	 if (logfile)
	      fprintf(logfile, "Iteration # of f-eval. minf\n");
    }
/* L10005: */
} /* dirheader_ */

/* Subroutine */ void direct_dirsummary_(FILE *logfile, doublereal *x, doublereal *
	l, doublereal *u, integer *n, doublereal *minf, doublereal *fglobal, 
	integer *numfunc, integer *ierror)
{
    /* Local variables */
    integer i__;

    /* Parameter adjustments */
    --u;
    --l;
    --x;

    /* Function Body */
    if (logfile) {
	 fprintf(logfile, "-----------------------Summary------------------\n"
		 "Final function value: %g\n"
		 "Number of function evaluations: %d\n", *minf, *numfunc);
	 if (*fglobal > -1e99)
	      fprintf(logfile, "Final function value is within %g%% of global optimum\n", 100*(*minf - *fglobal) / MAX(1.0, fabs(*fglobal)));
	 fprintf(logfile, "Index, final solution, x(i)-l(i), u(i)-x(i)\n");
	 for (i__ = 1; i__ <= *n; ++i__)
	      fprintf(logfile, "%d, %g, %g, %g\n", i__, x[i__], 
		      x[i__]-l[i__], u[i__] - x[i__]);
	 fprintf(logfile, "-----------------------------------------------\n");
	      
    }
} /* dirsummary_ */
