function [ x, fx ] = glomin ( a, b, c, m, machep, e, t, f )

%*****************************************************************************80
%
%% GLOMIN seeks a global minimum of a function F(X) in an interval [A,B].
%
%  Discussion:
%
%    This function assumes that F(X) is twice continuously differentiable
%    over [A,B] and that F''(X) <= M for all X in [A,B].
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    17 April 2008
%
%  Author:
%
%    Original FORTRAN77 version by Richard Brent.
%    MATLAB version by John Burkardt.
%
%  Reference:
%
%    Richard Brent,
%    Algorithms for Minimization Without Derivatives,
%    Dover, 2002,
%    ISBN: 0-486-41998-3,
%    LC: QA402.5.B74.
%
%  Parameters:
%
%    Input, real A, B, the endpoints of the interval.
%    It must be the case that A < B.
%
%    Input, real C, an initial guess for the global
%    minimizer.  If no good guess is known, C = A or B is acceptable.
%
%    Input, real M, the bound on the second derivative.
%
%    Input, real MACHEP, an estimate for the relative machine
%    precision.
%
%    Input, real E, a positive tolerance, a bound for the
%    absolute error in the evaluation of F(X) for any X in [A,B].
%
%    Input, real T, a positive error tolerance.
%
%    Input, function value = F ( x ), the name of a user-supplied
%    function whose global minimum is being sought.
%
%    Output, real X, the estimated value of the abscissa
%    for which F attains its global minimum value in [A,B].
%
%    Output, real FX, the value F(X).
%
  a0 = b;
  x = a0;
  a2 = a;
  y0 = f ( b );
  yb = y0;
  y2 = f ( a );
  y = y2;

  if ( y0 < y )
    y = y0;
  else
    x = a;
  end

  if ( m <= 0.0 || b <= a )
    fx = y;
    return
  end

  m2 = 0.5 * ( 1.0 + 16.0 * machep ) * m;

  if ( c <= a || b <= c )
    sc = 0.5 * ( a + b );
  else
    sc = c;
  end

  y1 = f ( sc );
  k = 3;
  d0 = a2 - sc;
  h = 9.0 / 11.0;

  if ( y1 < y )
    x = sc;
    y = y1;
  end

  while ( 1 )

    d1 = a2 - a0;
    d2 = sc - a0;
    z2 = b - a2;
    z0 = y2 - y1;
    z1 = y2 - y0;
    r = d1 * d1 * z0 - d0 * d0 * z1;
    p = r;
    qs = 2.0 * ( d0 * z1 - d1 * z0 );
    q = qs;

    if ( k < 1000000 || y2 <= y )

      while ( 1 )

        if ( q * ( r * ( yb - y2 ) + z2 * q * ( ( y2 - y ) + t ) ) < ...
          z2 * m2 * r * ( z2 * q - r ) )
          a3 = a2 + r / q;
          y3 = f ( a3 );

          if ( y3 < y )
            x = a3;
            y = y3;
          end
        end

        k = mod ( 1611 * k, 1048576 );
        q = 1.0;
        r = ( b - a ) * 0.00001 * k;

        if ( z2 <= r )
          break
        end

      end

    else

      k = mod ( 1611 * k, 1048576 );
      q = 1.0;
      r = ( b - a ) * 0.00001 * k;

      while ( r < z2 )

        if ( q * ( r * ( yb - y2 ) + z2 * q * ( ( y2 - y ) + t ) ) < ...
          z2 * m2 * r * ( z2 * q - r ) )
          a3 = a2 + r / q;
          y3 = f ( a3 );

          if ( y3 < y )
            x = a3;
            y = y3;
          end
        end

        k = mod ( 1611 * k, 1048576 );
        q = 1.0;
        r = ( b - a ) * 0.00001 * k;

      end

    end

    r = m2 * d0 * d1 * d2;
    s = sqrt ( ( ( y2 - y ) + t ) / m2 );
    h = 0.5 * ( 1.0 + h );
    p = h * ( p + 2.0 * r * s );
    q = q + 0.5 * qs;
    r = - 0.5 * ( d0 + ( z0 + 2.01 * e ) / ( d0 * m2 ) );

    if ( r < s || d0 < 0.0 )
      r = a2 + s;
    else
      r = a2 + r;
    end

    if ( 0.0 < p * q )
      a3 = a2 + p / q;
    else
      a3 = r;
    end

    while ( 1 )

      a3 = max ( a3, r );

      if ( b <= a3 )
        a3 = b;
        y3 = yb;
      else
        y3 = f ( a3 );
      end

      if ( y3 < y )
        x = a3;
        y = y3;
      end

      d0 = a3 - a2;

      if ( a3 <= r )
        break
      end

      p = 2.0 * ( y2 - y3 ) / ( m * d0 );

      if ( ( 1.0 + 9.0 * machep ) * d0 <= abs ( p ) )
        break
      end

      if ( 0.5 * m2 * ( d0 * d0 + p * p ) <= ...
        ( y2 - y ) + ( y3 - y ) + 2.0 * t )
        break
      end

      a3 = 0.5 * ( a2 + a3 );
      h = 0.9 * h;

    end

    if ( b <= a3 )
      break
    end

    a0 = sc;
    sc = a2;
    a2 = a3;
    y0 = y1;
    y1 = y2;
    y2 = y3;

  end

  fx = y;
 
  return
end
