-
Notifications
You must be signed in to change notification settings - Fork 5
/
simps.m
119 lines (109 loc) · 3.36 KB
/
simps.m
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
function z = simps(x,y,dim)
%SIMPS Simpson's numerical integration.
% Z = SIMPS(Y) computes an approximation of the 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, SIMPS(Y) is the integral of Y. For matrices, SIMPS(Y) is a
% row vector with the integral over each column. For N-D arrays, SIMPS(Y)
% works across the first non-singleton dimension.
%
% Z = SIMPS(X,Y) computes the integral of Y with respect to X using the
% Simpson's rule. 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). SIMPS operates along this dimension.
%
% Z = SIMPS(X,Y,DIM) or SIMPS(Y,DIM) integrates across dimension DIM of
% Y. The length of X must be the same as size(Y,DIM).
%
% Examples:
% --------
% % The integration of sin(x) on [0,pi] is 2
% % Let us compare TRAPZ and SIMPS
% x = linspace(0,pi,6);
% y = sin(x);
% trapz(x,y) % returns 1.9338
% simps(x,y) % returns 2.0071
%
% If Y = [0 1 2
% 3 4 5
% 6 7 8]
% then simps(Y,1) is [6 8 10] and simps(Y,2) is [2; 8; 14]
%
%
% Class support for inputs X, Y:
% float: double, single
%
% -- Damien Garcia -- 08/2007, revised 11/2009
% directly adapted from TRAPZ
%
% See also CUMSIMPS, TRAPZ, QUAD.
%% Make sure x and y are column vectors, or y is a matrix.
perm = []; nshifts = 0;
if nargin == 3 % simps(x,y,dim)
perm = [dim:max(ndims(y),dim) 1:dim-1];
yp = permute(y,perm);
[m,n] = size(yp);
elseif nargin==2 && isscalar(y) % simps(y,dim)
dim = y; y = x;
perm = [dim:max(ndims(y),dim) 1:dim-1];
yp = permute(y,perm);
[m,n] = size(yp);
x = 1:m;
else % simps(y) or simps(x,y)
if nargin < 2, y = x; end
[yp,nshifts] = shiftdim(y);
[m,n] = size(yp);
if nargin < 2, x = 1:m; end
end
x = x(:);
if length(x) ~= m
if isempty(perm) % dim argument not given
error('MATLAB:simps:LengthXmismatchY',...
'LENGTH(X) must equal the length of the first non-singleton dimension of Y.');
else
error('MATLAB:simps:LengthXmismatchY',...
'LENGTH(X) must equal the length of the DIM''th dimension of Y.');
end
end
%% The output size for [] is a special case when DIM is not given.
if isempty(perm) && isequal(y,[])
z = zeros(1,class(y));
return;
end
%% Use TRAPZ if m<3
if m<3
if exist('dim','var')
z = trapz(x,y,dim);
else
z = trapz(x,y);
end
return
end
%% Simpson's rule
y = yp;
clear yp
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);
z = sum(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);
if rem(m,2) == 0 % Adjusting if length(x) is even
state0 = warning('query','MATLAB:nearlySingularMatrix');
state0 = state0.state;
warning('off','MATLAB:nearlySingularMatrix')
C = vander(x(end-2:end))\y(end-2:end,:);
z = z + C(1,:).*(x(end,:).^3-x(end-1,:).^3)/3 +...
C(2,:).*(x(end,:).^2-x(end-1,:).^2)/2 +...
C(3,:).*dx(end,:);
warning(state0,'MATLAB:nearlySingularMatrix')
end
%% Resizing
siz = size(y); siz(1) = 1;
z = reshape(z,[ones(1,nshifts),siz]);
if ~isempty(perm), z = ipermute(z,perm); end