function [integral_value,success] = composite_Newton_Cotes(f, a, b, m, eps); % Accompanying program for the text % % Classical and Modern Numerical Analysis: % Theory, Methods and Practice % by Azmy S. Ackleh, Edward J. Allen, % R. Baker Kearfott, and Padmanabhan Seshaiyer % % (Taylor and Francis / CRC Press, 2009) % % I = composite_Newton_Cotes(f, a, b, m, eps) computes an approximation to % the integral of f over the interval a to b, using composite Newton-Cotes % integration, according to the explanation in sections 6.3.1 and 6.3.2 of % the text. f is a string giving the name of an "m" file containing the % function to be integrated, a is the left end point of the integration % interval, b is the right end point of the integration interval, and m is % the number of points in the Newton-Cotes formula. (Closed Newton-Cotes % formulas are used.) The weights for various m are stored in this % routine, with valid values of m between 2 and 11. Computations stop when % the approximation with 2n subintervals differs by less than eps from % the approximation with n subintervals, provided that can be achieved with % less 15 doublings (2^{15} = 32768 subintervals. 'success' is set to % false if the tolerance cannot be met, and is set to 'true' if it can. % % For example, suppose the m-file f_sin_x_over_xsqp1.m contains % % function [y] = f_sin_x_over_xsqp1(x) % y = sin(x) / (x^2 + 1); % return % % Then, the following sequence will return an approximation to the integral % of sin(x) / (x^{2} + 1) over the interval [0,10], using Simpson's rule, % and with a stopping criterion for the composite integration process of % eps = 0.000001: % clear % a = 0; b = 10; m = 3; % [integral_value, success] = composite_Newton_Cotes('f_sin_x_over_xsqp1',... % a, b, m, 0.000001) switch m case 2 % Trapezoidal rule w = [1 1]; case 3 % Simpson's rule w = [1/3 4/3 1/3]; case 4 % The 3/8 rule w = 2 * [1/8 3/8 3/8 1/8]; case 5 % Boole's rule w = (2/90) * [7 32 12 32 7]; case 6 w = (1/144) * [19 75 50 50 75 19]; case 7 w = (1/420) * [41 216 27 272 27 216 41]; case 8 w = (1/8640) * [751 3577 1323 2989 2989 1323 3577 751]; case 9 % Note weights of opposite signs, bad for roundoff error -- w = (1/14175) * [989 5888 -928 10496 -4540 10496 -928 5888 989]; case 10 w = (1/44800) * [2857 15741 1080 19344 5778 5778 19344 1080 15741 2857]; case 11 % Expect this formula to have very bad roundoff properties -- w = (1/299376) * ... [16067 106300 -48525 272400 -260550 427368 -260550 272400 -48525 106300 16067]; otherwise disp('Error in composite_Newton_Cotes:') disp(sprintf('The case m = %3f points is not implemented.', m)) success = false; integral_value = (b-a)*feval(f,(a+b)/2); return end x = linspace(-1,1,m); n=1; error=2*eps; success = false; sm2=1000.0; n_doubling = 0; while error > eps n=2*n; n_doubling = n_doubling + 1; if n_doubling > 15 success = false disp(sprintf('composite_Newton_Cotes could not achieve accuracy eps = %12.9e', eps)) integral_value = sm2; return end h=(b-a)/n; s=0; for j=1:n ss=0; aa=a+(j-1)*h; %left endpoint of jth subinterval for k=1:m z = (x(k)+1)*h/2 + aa; ss = ss + feval(f,z)*w(k)*h/2.0; end s=s+ss; end sm1=sm2; sm2=s; error=abs(sm2-sm1); disp(sprintf(' %9.0f %12.6f ',n,sm2)); end success = true; integral_value = sm2;