function [x_min,f_min,niter] = fletcher_reeves(f,x0,h,tolgrad,tolfun,tolx,nder)
% f = function to be minimized
% x0 = starting point.
% h = initial search increment.
% nder = type of derivative: [1] 1st forward [2] 2nd forward [3] central
% tolgrad = error tolerance on the gradient (default = 1.0e-4).
% tolfun = error tolerance on the function (default = 1.0e-6).
% tolx = error tolerance on the solution (default = 1.0e-6)
% niter = number of iterations

if nargin < 7; nder = 2; end
if nargin < 6; tolx = 1.0e-6; end
if nargin < 5; tolfun = 1.0e-6; end
if nargin < 4; tolgrad = 1.0e-4; end
if nargin < 3; h = 0.1; end

[f0,g0] = gradx(f,x0,nder);
r0 = -g0;
s0 = r0;
df = tolfun;dx = tolx;

niter = 0;
while (r0'*r0) >= tolgrad || abs(df) >= tolfun || (dx'*dx) >= tolx

        niter = niter + 1;
        [alpha,~] = line_search(@(alpha) f(x0+alpha*s0),0.0,-Inf,Inf,h);

        x_min = x0 + alpha*s0;
        [f_min,g1] = gradx(f,x_min,nder);
        r1 = -g1;
        
        beta = (r1'*r1)/(r0'*r0);
        s1 = r1 + beta*s0;
        dx = x_min-x0;df = f_min-f0;
        x0 = x_min;f0 = f_min;s0 = s1;r0 = r1;
        
end

end

