function [ tv, uv ] = runge_kutta_4( fun, y0, t0, tf, Nh )
% RUNGE_KUTTA_4 Runge-Kutta 4, explicit method for the scalar ODE in the 
% form:
% y'(t) = f(t,y(t)),  t \in (t0,tf)
% y(0) = y_0
%
%  [ tv, uv ] = runge_kutta_4( fun, y0, t0, tf, Nh )
%  Inputs: fun    = function handle for f(t,y), fun = @(t,y) ...
%          y0     = initial value
%          t0     = initial time
%          tf     = final time
%          Nh     = number of time subintervals
%  Output: tv     = vector of time steps (1 x (Nh+1))
%          uv     = vector of approximate solution at times tv
%

tv = linspace( t0, tf, Nh + 1 );
h = ( tf - t0 ) / Nh;

uv = zeros( 1, Nh + 1 );
uv( 1 ) = y0;

for n = 1 : Nh    
    K1 = fun( tv( n ), uv( n ) );
    K2 = fun( tv( n ) + h / 2, uv( n ) + h / 2 * K1 );
    K3 = fun( tv( n ) + h / 2, uv( n ) + h / 2 * K2 );
    K4 = fun( tv( n + 1 ), uv( n ) + h * K3 );
    uv( n + 1 ) = uv( n ) + h / 6 * ( K1 + 2 * K2 + 2 * K3 + K4 );  
end

return