function romberg_demo

% demonstration of calling romberg.m
% based on integrating sin(x) from 0 to pi; the exact integral is 2.
a = 0; 
b = pi;
max_k = 10;
f = @(x) sin(x); 
f = @(x) 1./sqrt(x + 1e-5); % close to non-Cinfty
R = romberg(f,a,b,max_k);

n = size(R,1);

figure
exact = integral(f,a,b,'AbsTol',1e-14);
semilogy(1:n,abs(R(:,1)-exact),'bo-')
hold on
semilogy(1:n-1,abs(R(2:end,2)-exact),'r*-')
semilogy(1:n-2,abs(R(3:end,3)-exact),'gx-')
semilogy(1:n-3,abs(R(4:end,4)-exact),'ks-')
xlabel('j'); ylabel('Error');
legend('O(h^2)','O(h^4)','O(h^6)','O(h^8)')

return
% plot the approximate integrals
figure
plot(1:n,R(:,1),'bo-',1:n-1,R(2:end,2),'r*-',1:n-2,R(3:end,3),'g',1:n-3,R(4:end,4),'k')
xlabel('j'); ylabel('approximate integral');
legend('O(h^2)','O(h^4)','O(h^6)','O(h^8)')

% The ratio of the difference between successive entries in column k
% should be approximately 4^k. This provides a simple test to see if
% our extrapolation is working, without requiring knowledge of the exact
% answer. See Johnson and Riess, Numerical Analysis, 2nd ed., p. 323.

Ratio = zeros(max_k-1,max_k-1);
for k=1:max_k-1
    Ratio(k:end,k) = (R(1+k:end-1,k)-R(k:end-2,k))./(R(2+k:end,k)-R(1+k:end-1,k));
end
Ratio
% keyboard
return


function R = romberg(f, a, b, max_k)
% Compute the triangular extrapolation table for Romberg integration
% using the composite trapezoid rule, starting with h=b-a.
% f: function name (either a name in quotes, or an inline function)
% a, b: lower and upper limits of integration
% max_k: the number of extrapolation steps (= number of columns in R, plus one.)
% max_k=0 will do no extrapolation.
% Example: R = romberg(@(x) sin(x),0,pi,1,6)

R = zeros(max_k+1);
for j=1:max_k+1
    R(j,1) = trapezoid(f,a,b,2^(j-1));
end
for k=2:max_k+1
    for j=k:max_k+1
        R(j,k) = (4^(k-1)*R(j,k-1)-R(j-1,k-1))/(4^(k-1)-1);
    end
end
return

function I = trapezoid(f,a,b,n)

h = (b-a)/n;
x = a:h:b;

if (abs(length(x)-1-n)>0)
    disp('error')
    keyboard
end

fx = f(x);
fx = h*fx;
fx(1)=1/2*fx(1);
fx(end) = 1/2*fx(end);

I = sum(fx);

return