function [xmin,fmin,gmin] = Newton_optimize(x,fname,prtout,tol)
% Call : [xmin,fmin,gmin] = Newton_optimize(x,fname,prtout,tol)
%
% Written by Emre Mengi - May 7th, 2008
%
% Task :
% Newton's Iteration to find a minimizer of
% the function fname with the initial guess x 
%
% Input parameters:
% x	(vector)	   : Initial point for Newton's method.
% fname (string)      : Name of the function to be minimized. 
%				 This function is supposed to take one input
%			     argument, the point where the function should be
%			     evaluated. It returns the output arguments, the 
%				 function value, and possibly the gradient and 
%				 the Hessian.
% prtout (integer)	   : If prtout > 0 , print the function
%			     value and the norm of the gradient at each iteration. (Default) 
%			     If prtout <= 0, don't print.
% tol (real scalar)	   : Tolerance for termination. When the 2-norm of the 
%			     gradient is at most tol, stop. (Default --- tol=10^-8)
%
% Output arguments:
% xmin (vector)		   : Computed minimizer.
% fmin (scalar)		   : Function value at xmin.
% gmin (gradient)	   : The gradient cannot be greater than
%			     tol in 2-norm. For better accuracy set
%			     tol small. Setting tol too small causes convergence
%			     problems due to rounding errors.


if nargin < 2
	error('two input arguments - initial point and fun name - required')
end

if nargin < 3
	prtout = 1; % default print
end

if nargin < 4
	tol = 10^-8;
end


% Initializations for the main loop
iter = 0;
[f, g, H] = feval(fname,x);

if prtout > 0
	fprintf('iter %3d - f:%.9f normg:%.9f\n', iter, f, norm(g));
end

while norm(g) > tol & iter < 500
	
	% 1 - GENERATE A SEARCH DIRECTION (AT THE MOMENT NEWTON)
	p = -H\g;
	
	% 2 - GENERATE THE STEP-LENGTH
	alpha = linesearch(fname,x,p,f,g); 
	
	% 3 - UPDATE THE ESTIMATE
	x = x + alpha*p;
	
	
	[f, g, H] = feval(fname,x);
	iter = iter + 1;
	
	if prtout > 0
		fprintf('iter %3d - f:%.9f normg:%.9f\n', iter, f, norm(g));
	end
	
end

xmin = x;
fmin = f;
gmin = g;

if prtout > 0
	fprintf('iter %3d - f:%.9f normg:%.9f\n', iter, f, norm(g));
end


if iter >= 500
	fprintf('\n');
	warning('Newtons method could not converge after 500 iterations') 
end

return