Code covered by the BSD License  

Highlights from
Simpson's numerical integration

image thumbnail
from Simpson's numerical integration by Damien Garcia
The Simpson's rule uses parabolic arcs instead of the straight lines used in the trapezoidal rule

cumsimps(x,y,dim)
function z = cumsimps(x,y,dim)

%CUMSIMPS Cumulative Simpson's numerical integration.
%   Z = CUMSIMPS(Y) computes an approximation of the cumulative integral of
%   Y via the Simpson's method (with unit spacing). To compute the integral
%   for spacing different from one, multiply Z by the spacing increment.
%
%   For vectors, CUMSIMPS(Y) is a vector containing the cumulative integral
%   of Y. For matrices, CUMSIMPS(Y) is a matrix the same size as X with the
%   cumulative integral over each column. For N-D arrays, CUMSIMPS(Y) works
%   along the first non-singleton dimension.
%
%   Z = CUMSIMPS(X,Y) computes the cumulative integral of Y with respect to
%   X using Simpson's integration. X and Y must be vectors of the same
%   length, or X must be a column vector and Y an array whose first
%   non-singleton dimension is length(X). CUMSIMPS operates across this
%   dimension.
%
%   Z = CUMSIMPS(X,Y,DIM) or CUMSIMPS(Y,DIM) integrates along dimension DIM
%   of Y. The length of X must be the same as size(Y,DIM).
%
%   Examples:
%   --------
%   % The integral of cos(x) is sin(x)
%   % Let us compare CUMTRAPZ and CUMSIMPS
%   x = linspace(0,2*pi,20);
%   y = cos(x);
%   yt = cumtrapz(x,y);
%   ys = cumsimps(x,y);
%   % RMSE: root mean squared errors:
%   sqrt(mean((yt-sin(x)).^2)) % returns 0.0063
%   sqrt(mean((ys-sin(x)).^2)) % returns 1.2309e-004
%
%   If Y = [0 1 2; 3 4 5; 6 7 8]
%   then cumsimps(Y,1) is [0   0   0    and cumsimps(Y,2) is [0 0.5 2
%                          1.5 2.5 3.5                        0 3.5 8
%                          6   8   10]                        0 6.5 14]
%
%
%   Class support for inputs X,Y:
%      float: double, single
%
%   -- Damien Garcia -- 09/2007, revised 11/2009
%   directly adapted from CUMTRAPZ
%
%   See also CUMSUM, CUMTRAPZ, SIMPS.

%%   Make sure x and y are column vectors, or y is a matrix.
perm = []; nshifts = 0;
if nargin == 3, % cumsimps(x,y,dim)
  perm = [dim:max(length(size(y)),dim) 1:dim-1];
  y = permute(y,perm);
  [m,n] = size(y);
elseif nargin==2 && isequal(size(y),[1 1]) % cumsimps(y,dim)
  dim = y; y = x;
  perm = [dim:max(length(size(y)),dim) 1:dim-1];
  y = permute(y,perm);
  [m,n] = size(y);
  x = 1:m;
else
  if nargin < 2, y = x; end
  [y,nshifts] = shiftdim(y);
  [m,n] = size(y);
  if nargin < 2, x = 1:m; end
end
x = x(:);
if length(x) ~= m
    error('MATLAB:cumsimps:LengthXMismatchY',...
          'length(x) must equal length of first non-singleton dim of y.');
end
if m<3
    error('MATLAB:cumsimps:LengthX',...
          'length(x) must be at least 3.');
end

%%
z = zeros(size(y),class(y));

dx = repmat(diff(x,1,1),1,n);
dx1 = dx(1:end-1,:);
dx2 = dx(2:end,:);

alpha = (dx1+dx2)./dx1/6;
a0 = alpha.*(2*dx1-dx2);
a1 = alpha.*(dx1+dx2).^2./dx2;
a2 = alpha.*dx1./dx2.*(2*dx2-dx1);

%% First cumulative value
state0 = warning('query','MATLAB:nearlySingularMatrix');
state0 = state0.state;
warning('off','MATLAB:nearlySingularMatrix')
C = vander(x(1:3))\y(1:3,:);
z(2,:) = C(1,:).*(x(2,:).^3-x(1,:).^3)/3 +...
    C(2,:).*(x(2,:).^2-x(1,:).^2)/2 +...
    C(3,:).*dx(1,:);
warning(state0,'MATLAB:nearlySingularMatrix')

%% Other cumulative values
z(3:2:end,:) = cumsum(a0(1:2:end,:).*y(1:2:m-2,:) +...
    a1(1:2:end,:).*y(2:2:m-1,:) +...
    a2(1:2:end,:).*y(3:2:m,:),1);
z(4:2:end,:) = cumsum(a0(2:2:end,:).*y(2:2:m-2,:) +...
    a1(2:2:end,:).*y(3:2:m-1,:) +...
    a2(2:2:end,:).*y(4:2:m,:),1) +...
    repmat(z(2,:),ceil((m-3)/2),1);

%% Resizing
siz = size(y); siz(1) = max(1,siz(1));
z = reshape(z,[ones(1,nshifts),siz]);
if ~isempty(perm), z = ipermute(z,perm); end

Contact us at files@mathworks.com