#include <iostream>
#include <cmath>
double goldmax(double func(double), double ax, double bx, double cx, double tol);
double expsearch(double func(double), double a, double b, double c, double tol, int k, double a0, double b0);
double brentmax(double func(double), double a, double c, double tol){
float b=c-((3.0-sqrt(5))/2)*(c-a);
if ((func(a) < func(b) && func(b) < func(c)) || (func(a) > func(b) && func(b) > func(c))){
return expsearch(func, a, b, c, tol, 0, a, b);
}else{
return goldmax(func, a, b, c, tol);
}
}
double goldmax(double func(double), double ax, double bx, double cx, double tol){
double C=(3.0-sqrt(5))/2.0;
double R=1-C;
double x0=ax;
double x1;
double x2;
double x3=cx;
if (fabs(cx-bx) > fabs(bx-ax)){
x1=bx;
x2=bx+C*(cx-bx);
}else{
x2=bx;
x1=bx-C*(bx-ax);
}
double f1=func(x1);
double f2=func(x2);
int k=0;
while (fabs(x3-x0) > tol*(fabs(x1)+fabs(x2))){ if (f2 > f1){
x0=x1;
x1=x2;
x2=R*x1+C*x3; f1=f2;
f2=func(x2);
}else{
x3=x2;
x2=x1;
x1=R*x2+C*x0; f2=f1;
f1=func(x1);
}
++k;
}
double xmax;
if(f1 > f2){
xmax=x1;
}else{
xmax=x2;
}
return xmax;
}
double expsearch(double func(double), double a, double b, double c, double tol, int k, double a0, double b0){
if ((func(a) <= func(b) && func(b) <= func(c)) || (func(a) >= func(b) && func(b) >= func(c))){
double R=2/(sqrt(5)-1);
++k;
if(k<100){
double x=c+R*(c-b);
return expsearch(func, b, c, x, tol, k, a0, b0);
}else if(k==100){
double x=a0-R*(b0-a0);
return expsearch(func, x, a, b, tol, k, a0, b0);
}else if(k<200){
double x=a-R*(b-a);
return expsearch(func, x, a, b, tol, k, a0, b0);
}else{
return 1234567890;
}
}
return goldmax(func,a,b,c,tol);
}