TJ,
I just can't leave code alone. I thought that I'd try to write the
trapz function since it is similar to cumtrapz. While writing the
trapz function, I kept running into problems trying to visualize 3
dimensional matrices which led to many bugs. It hit me last night as
I was going to sleep to use reshape to flatten the matrix to 2
dimensions and then I applied that idea to the implementation
cumtrapz. It actually improves the code readability a good bit and
performance slightly. On a related note, is this group the best way
to share/contribure m-files written for FreeMat? For now, both
functions are inline below.
-Jonathan
[y, dim] = shiftdim(x); %rotate matrix
x = 1:size(y,1);
elseif(nargin == 2) %cumtrapz(x,y) or cumtrapz(y,dim)
if(isscalar(y)) %cumtrapz(y,dim)
dim = y - 1;
y = shiftdim(x, dim); %rotate matrix
x = 1:size(y,1);
else %cumtrapz(x,y);
[y, dim] = shiftdim(y); %rotate matrix
if(length(x) ~= size(y,1))
error('The length of x must be equal to the length of
the first non-singleton dimension of y');
end
end
elseif(nargin == 3) %cumtrapz(x,y,dim)
dim = dim - 1;
y = shiftdim(y,dim); %rotate matrix
if(length(x) ~= size(y,1))
error('The length of x must be equal to the size(Y,dim)');
end
else
error('Invalid number of arguments');
end
n = size(y);
m = n(1);
p = prod(n(2:end));
y = reshape(y, [m p]); % flatten matrix
b = (y(1:(m-1),:) + y(2:m,:)) / 2;
c = repmat(diff(x).', [1 p]);
a = [zeros([1 p]); cumsum(b.*c)];
a = reshape(a, n); % unflatten matrix
A = shiftdim(a,length(n) - dim); % unrotate matrix
end
% TRAPZ - Trapezoidal numerical integration
%
% Usage
%
% Z = trapz(Y)
% Z = trapz(X,Y)
% Z = trapz(Y,dim)
% Z = trapz(X,Y,dim)
%
% Description
%
% Z = trapz(Y) computes an approximation of the cumulative integral of
Y via
% the trapezoidal method with unit spacing. To compute the integral
with other
% than unit spacing, multiply Z by the spacing increment. Input Y can
be complex.
%
% For vectors, trapz(Y) is the integral of Y.
%
% For matrices, cumtrapz(Y) is a row vector with the integral over
each column.
%
% For multidimensional arrays, trapz(Y) works across the first
% nonsingleton dimension.
%
% Z = trapz(X,Y) computes the cumulative integral of Y with respect to
X
% using trapezoidal integration. X and Y must be vectors of the same
length,
% or X must be a column vector and Y an array whose first nonsingleton
dimension
% is length(X). trapz operates across this dimension. Inputs X and Y
can be
% complex.
%
% If X is a column vector and Y an array whose first nonsingleton
dimension
% is length(X), cumtrapz(X,Y) operates across this dimension.
%
% Z = trapz(X,Y,dim) or trapz(Y,dim) integrates across the dimension
of
% Y specified by scalar dim. The length of X must be the same as
size(Y,dim).
%
% Licensed under the GPL
% Copyright (C) 2010 Jonathan Weaver <
jonw...@netscape.net>
function [A] = trapz(x,y,dim)
% This program is free software; you can redistribute it and/or modify
it under
% the terms of the GNU General Public License as published by the Free
Software
% Foundation; either version 2 of the License, or (at your option) any
later
% version.
%
% This program is distributed in the hope that it will be useful, but
WITHOUT
% ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
or FITNESS
% FOR A PARTICULAR PURPOSE. See the GNU General Public License for
more
% details.
%
% You should have received a copy of the GNU General Public License
along with
% this program; if not, write to the Free Software Foundation, Inc.,
% 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
if (nargin == 1) %trapz(y)
[y, dim] = shiftdim(x); %rotate matrix
x = 1:size(y,1);
elseif(nargin == 2) %trapz(x,y) or trapz(y,dim)
if(isscalar(y)) %trapz(y,dim)
dim = y - 1;
y = shiftdim(x, dim); % rotate matrix
x = 1:size(y,1);
else %trapz(x,y);
[y, dim] = shiftdim(y); % rotate matrix
if(length(x) ~= size(y,1))
error('The length of x must be equal to the length of
the first non-singleton dimension of y');
end
end
elseif(nargin == 3) %trapz(x,y,dim)
dim = dim - 1;
y = shiftdim(y,dim); % rotate matrix
if(length(x) ~= size(y,1))
error('The length of x must be equal to the size(Y,dim)');
end
else
error('Invalid number of arguments');
end
n = size(y);
m = n(1);
m2 = n(2:end);
y = reshape(y, [m prod(m2)]); % flatten matrix
b = (y(1:(m-1),:) + y(2:m,:)) / 2;
c = diff(x);
a = c * b;
a = reshape(a, [1 m2]); % unflatten matrix
A = shiftdim(a,length(n) - dim); % rotate matrix
end
On Nov 18, 12:34 pm, Timothy Cyders <
t.cyd...@gmail.com> wrote:
> Jonathan,
>
> Your function looks good. If I recall correctly, mine calls a loop in such a
> way that it cannot be compiled by JIT. I actually wrote that one mostly on
> paper in Africa. Yours looks much better without all the loops and with
> matrix operations instead. I'll do some testing on it and commit it to the
> code as cumtrapz() when I get the chance. Thanks for the contribution!
>
> TJ
>
> On Thu, Nov 18, 2010 at 11:36 AM, jonw0224
> <
jonathan.wea...@windstream.net>wrote:
> >
freemat+u...@googlegroups.com<
freemat%2Bunsu...@googlegroups.com>
> > .