// ................................................................... #include
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

// .............................................................. dichiarazioni
double funz(double x);
void brackmin(double *xa,double *xb,double *xc,double *fa,double *fb,double *fc,
	      double (*ptfunz)(double x));
double golden(double ax,double bx,double cx,double (*ptfunz)(double x),double tol,
       double *xmin);
// ====================================================================== main
main()
{
  int i;
  double f1,f2,f3,fmin,x,x1,x2,x3,xmin;
  double (*ptfunz)(double x);

  ptfunz=funz;
  x1=3.0;
  x2=4.0;
  x3=5.0;
  brackmin(&x1,&x2,&x3,&f1,&f2,&f3,ptfunz);
  fmin=golden(x1,x2,x3,ptfunz,1.0e-8,&xmin);
  printf("il minimo si tova in x=%.7le e vale %.7le\n",xmin,fmin);
}
// =======================================================================funz
double funz(double x)
{
  double y;

  y=pow(x,2.0)-8.0*x;
  return y;
}
// ==================================================================== brackmin
void brackmin(double *xa,double *xb,double *xc,double *fa,double *fb,double *fc,
	      double (*ptfunz)(double x))
{
  int count,CountMax;
  double f1,f2,f3,x1,x2,x3,xx;
  const double golden = 0.3819660;	// golden = (3-sqrt(5))/2.0

  // ........................................................ contatore
  CountMax=1000;
  // .................................................... valori inizali
  x1=*xa;
  x3=*xc;
  f1=(*ptfunz)(x1);
  f3=(*ptfunz)(x3);  
  // .................................................................  
  if (f3>=f1) 
    { x2=x1+(x3-x1)*golden;
      f2=(*ptfunz)(x2);
    }
  else
    { x2=x3 ;
      f2=f3 ;
      x3=x1+(x2-x1)/golden;
      f3=(*ptfunz)(x3);
    }
  // .................................................................  
  for (count=0;count<CountMax;count++)
    { // ------------------------------------------------------- f2<f1
      if (f2<f1 )
	{ // ......................................... f2 e' il minimo
	  if (f2 < f3)
	    { *xa=x1;*xb=x2;*xc=x3;
	      *fa=f1;*fb=f2;*fc=f3;
	      return;
	    }
	  // ................................................... f2>f3
	  else if (f2 > f3)
	    { x1=x2;f1=f2;
	      x2=x3;f2=f3;
	      x3=x1+(x2-x1)/golden;
	      f3=(*ptfunz)(x3);
	    }
	  // .................................................. f2==f3
	  else
	    { x1=x2;f1=f2;
	      x2=x1+(x3-x1)*golden;
	      f2=(*ptfunz)(x2);
	    }
	}
      // ------------------------------------------------------ f2>=f1
      else
	{ x3=x2;f3=f2;
	  x2=x1;f2=f1;
	  x1=x1-(x3-x2)/golden;
	  f1=(*ptfunz)(x1);
	}
    }
  *xa=x1;*xc=x3;*xb=x2;
  *fa=f1;*fc=f3;*fb=f2;
  printf("fallimento!!!\n");
}
// ============================================================== golden
double golden(double ax,double bx,double cx,double (*ptfunz)(double x),double tol,
	      double *xmin)
{
  double f1,f2,x0,x1,x2,x3;
  const double golden = 0.3819660;	// golden = (3-sqrt(5))/2.0
  const double rest=0.61803399;         // rest=1-golden

  x0=ax;
  x3=cx;
  if (fabs(cx-bx)>fabs(bx-ax)) {x1=bx;x2=bx+golden*(cx-bx);}
  else {x2=bx;x1=bx-golden*(bx-ax);}

  f1=(*ptfunz)(x1);
  f2=(*ptfunz)(x2);
  while (fabs(x3-x0)>tol) 
    { if (f2<f1) 
        { x0=x1;x1=x2;x2=rest*x1+golden*x3;
	  f1=f2;f2=(*ptfunz)(x2);
	} 
      else 
	{ x3=x2;x2=x1;x1=rest*x2+golden*x0;
          f2=f1;f1=(*ptfunz)(x1);
	}
    }
  if (f1<f2) {*xmin=x1;return f1;}
  else {*xmin=x2;return f2;}
}






