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