function varargout = rosenbrockn(x)
% gibt Funktionswert, Gradient und Hessematrix der n-dimensionalen
% Rosenbrockfunktion aus
%
% Eingabe:
%   x...n-dimensionaler Vektor
%
% Ausgabe:
%   varargout:
%   1. Argument: Funktionswert (Skalar)
%   2. Argument: Gradient (n x 1 Vektor)
%   3. Argument: Hessematrix (n x n sparse Matrix)
%
% Gradient und Hessematrix werden nur berechnet, wenn sie tatsaechlich
% benoetigt werden.
% 
% Das eindeutige globale Minimum der Funktion wird am Vektor (1,...,1)
% angenommen. Fuer hoehere Dimensionen kann es auch lokale Minima geben.
%
% Markus Grasmair,
% Wien, April 2011


% Funktionswert
varargout{1} = sum((1-x(1:end-1)).^2 + 100*(x(2:end)-x(1:end-1).^2).^2);

if nargout > 1
    % Gradient
    g = zeros(size(x));
    g(1:end-1) = -2*(1-x(1:end-1)) - 400*x(1:end-1).*(x(2:end)-x(1:end-1).^2);
    g(2:end) = g(2:end) + 200*(x(2:end)-x(1:end-1).^2);
    varargout{2} = g;
end

if nargout > 2
    % Hessematrix
    n = length(x);
    Hd_main = zeros(n,1);
    Hd_main(1:end-1) = 2-400*x(2:end)+1200*x(1:end-1).^2;
    Hd_main(2:end) = Hd_main(2:end) + 200;

    Hd_lower = zeros(n,1);
    Hd_lower(1:end-1) = -400*x(1:end-1);
    
    Hd_upper = zeros(n,1);
    Hd_upper(2:end) = -400*x(1:end-1);
    
    H = spdiags([Hd_lower,Hd_main,Hd_upper],[-1,0,1],n,n);
    varargout{3} = H;
end
