function [tout, yout] = q2_solution(ypfun, t0, tfinal, y0, tol, trace)
% Q2_SOLUTION Modification of ode23_orig to use following embedded methods
% 
%    0 |
%  1/2 | 1/2
%    1 | -1    2
% -----+---------------
%      |  0    1
%      | 1/6  2/3  1/6

% Initialization
pow = 1/3;
if nargin < 5, tol = 1.e-3; end
if nargin < 6, trace = 0; end

t = t0;
hmax = (tfinal - t)/16;
h = hmax/8;
y = y0(:);
chunk = 128;
tout = zeros(chunk,1);
yout = zeros(chunk,length(y));
k = 1;
tout(k) = t;
yout(k,:) = y.';

if trace
   clc, t, h, y
end

% The main loop

while (t < tfinal) & (t + h > t)
   if t + h > tfinal, h = tfinal - t; end

   % Compute the slopes
   s1 = feval(ypfun, t, y); s1 = s1(:);
   s2 = feval(ypfun, t+h/2, y+h*s1/2); s2 = s2(:);
   s3 = feval(ypfun, t+h, y+h*(2*s2-s1)); s3 = s3(:);
  
   % Estimate the error and the acceptable error
   delta = norm(h*(2*s2 - s1 - s3)/6,'inf');
   tau = tol*max(norm(y,'inf'),1.0);

   % Update the solution only if the error is acceptable
   if delta <= tau
      t = t + h;
      y = y + h*(s1 + 4*s2 + s3)/6;
      k = k+1;
      if k > length(tout)
         tout = [tout; zeros(chunk,1)];
         yout = [yout; zeros(chunk,length(y))];
      end
      tout(k) = t;
      yout(k,:) = y.';
   end
   if trace
      home, t, h, y
   end

   % Update the step size
   if delta ~= 0.0
      h = min(hmax, 0.9*h*(tau/delta)^pow);
   end
end

if (t < tfinal)
   disp('Singularity likely.')
   t
end

tout = tout(1:k);
yout = yout(1:k,:);
