Blame min/bracketing.c

Packit 67cb25
/* min/bracketing.c
Packit 67cb25
 * 
Packit 67cb25
 * Copyright (C) 1996, 1997, 1998, 1999, 2000 Fabrice Rossi
Packit 67cb25
 * 
Packit 67cb25
 * This program is free software; you can redistribute it and/or modify
Packit 67cb25
 * it under the terms of the GNU General Public License as published by
Packit 67cb25
 * the Free Software Foundation; either version 3 of the License, or (at
Packit 67cb25
 * your option) any later version.
Packit 67cb25
 * 
Packit 67cb25
 * This program is distributed in the hope that it will be useful, but
Packit 67cb25
 * WITHOUT ANY WARRANTY; without even the implied warranty of
Packit 67cb25
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit 67cb25
 * General Public License for more details.
Packit 67cb25
 * 
Packit 67cb25
 * You should have received a copy of the GNU General Public License
Packit 67cb25
 * along with this program; if not, write to the Free Software
Packit 67cb25
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
Packit 67cb25
 */
Packit 67cb25
Packit 67cb25
/* bracketing.c -- find an initial bracketing interval for a function to minimize */
Packit 67cb25
Packit 67cb25
#include <config.h>
Packit 67cb25
#include <gsl/gsl_math.h>
Packit 67cb25
#include <gsl/gsl_errno.h>
Packit 67cb25
#include <gsl/gsl_min.h>
Packit 67cb25
#include <gsl/gsl_machine.h>
Packit 67cb25
Packit 67cb25
#include "min.h"
Packit 67cb25
Packit 67cb25
int 
Packit 67cb25
gsl_min_find_bracket(gsl_function *f,double *x_minimum,double * f_minimum,
Packit 67cb25
                     double * x_lower, double * f_lower, 
Packit 67cb25
                     double * x_upper, double * f_upper,
Packit 67cb25
                     size_t eval_max)
Packit 67cb25
{
Packit 67cb25
  /* The three following variables must be declared volatile to avoid storage
Packit 67cb25
     in extended precision registers available on some architecture. The code
Packit 67cb25
     relies on the ability to compare double values. As the values will be
Packit 67cb25
     store in regular memory, the extended precision will then be lost and
Packit 67cb25
     values that are different in extended precision might have equal
Packit 67cb25
     representation in double precision. This behavior might break the
Packit 67cb25
     algorithm. 
Packit 67cb25
   */
Packit 67cb25
  volatile double f_left = *f_lower;
Packit 67cb25
  volatile double f_right = *f_upper;
Packit 67cb25
  volatile double f_center;
Packit 67cb25
  double x_left = *x_lower;
Packit 67cb25
  double x_right= *x_upper; 
Packit 67cb25
  double x_center;
Packit 67cb25
  const double golden = 0.3819660;      /* golden = (3 - sqrt(5))/2 */
Packit 67cb25
  size_t nb_eval = 0;
Packit 67cb25
  
Packit 67cb25
  
Packit 67cb25
  if (f_right >= f_left) 
Packit 67cb25
    {
Packit 67cb25
      x_center = (x_right - x_left) * golden + x_left;
Packit 67cb25
      nb_eval++;
Packit 67cb25
      SAFE_FUNC_CALL (f, x_center, &f_center);
Packit 67cb25
    }
Packit 67cb25
  else
Packit 67cb25
    {
Packit 67cb25
      x_center = x_right ;
Packit 67cb25
      f_center = f_right ;
Packit 67cb25
      x_right = (x_center - x_left) / golden + x_left;
Packit 67cb25
      nb_eval++;
Packit 67cb25
      SAFE_FUNC_CALL (f, x_right, &f_right);
Packit 67cb25
    }
Packit 67cb25
  
Packit 67cb25
  do
Packit 67cb25
    {
Packit 67cb25
      if (f_center < f_left )
Packit 67cb25
        {
Packit 67cb25
          if (f_center < f_right)
Packit 67cb25
            {
Packit 67cb25
              *x_lower = x_left;
Packit 67cb25
              *x_upper = x_right;
Packit 67cb25
              *x_minimum = x_center;
Packit 67cb25
              *f_lower = f_left;
Packit 67cb25
              *f_upper = f_right;
Packit 67cb25
              *f_minimum = f_center;
Packit 67cb25
/*            gsl_ieee_printf_double (&f_left);
Packit 67cb25
              printf(" ");
Packit 67cb25
              gsl_ieee_printf_double (&f_center);
Packit 67cb25
              printf("\n");*/
Packit 67cb25
              return GSL_SUCCESS;
Packit 67cb25
            }
Packit 67cb25
          else if (f_center > f_right)
Packit 67cb25
            {
Packit 67cb25
              x_left = x_center;
Packit 67cb25
              f_left = f_center;
Packit 67cb25
              x_center = x_right;
Packit 67cb25
              f_center = f_right;
Packit 67cb25
              x_right = (x_center - x_left) / golden + x_left;
Packit 67cb25
              nb_eval++;
Packit 67cb25
              SAFE_FUNC_CALL (f, x_right, &f_right);
Packit 67cb25
            }
Packit 67cb25
          else /* f_center == f_right */
Packit 67cb25
            {
Packit 67cb25
              x_right = x_center;
Packit 67cb25
              f_right = f_center;
Packit 67cb25
              x_center = (x_right - x_left) * golden + x_left;
Packit 67cb25
              nb_eval++;
Packit 67cb25
              SAFE_FUNC_CALL (f, x_center, &f_center);
Packit 67cb25
            }
Packit 67cb25
        }
Packit 67cb25
      else /* f_center >= f_left */
Packit 67cb25
        {
Packit 67cb25
          x_right = x_center;
Packit 67cb25
          f_right = f_center;
Packit 67cb25
          x_center = (x_right - x_left) * golden + x_left;
Packit 67cb25
          nb_eval++;
Packit 67cb25
          SAFE_FUNC_CALL (f, x_center, &f_center);
Packit 67cb25
        }
Packit 67cb25
    }
Packit 67cb25
  while (nb_eval < eval_max 
Packit 67cb25
         && (x_right - x_left) > GSL_SQRT_DBL_EPSILON * ( (x_right + x_left) * 0.5 ) + GSL_SQRT_DBL_EPSILON);
Packit 67cb25
  *x_lower = x_left;
Packit 67cb25
  *x_upper = x_right;
Packit 67cb25
  *x_minimum = x_center;
Packit 67cb25
  *f_lower = f_left;
Packit 67cb25
  *f_upper = f_right;
Packit 67cb25
  *f_minimum = f_center;
Packit 67cb25
  return GSL_FAILURE;
Packit 67cb25
}
Packit 67cb25