# HG changeset patch # User Rik # Date 1318044069 25200 # Node ID 96c7143304d953e82ce0aae996600afafc3c805f # Parent 7dce7e110511369316c41cfbaf56142fb5f00e50 conv.m: Simplify algorithm and add more input validation and tests * conv.m: Simplify algorithm and add more input validation and tests diff -r 7dce7e110511 -r 96c7143304d9 scripts/polynomial/conv.m --- a/scripts/polynomial/conv.m Fri Oct 07 22:16:07 2011 -0400 +++ b/scripts/polynomial/conv.m Fri Oct 07 20:21:09 2011 -0700 @@ -19,12 +19,12 @@ ## -*- texinfo -*- ## @deftypefn {Function File} {} conv (@var{a}, @var{b}) ## @deftypefnx {Function File} {} conv (@var{a}, @var{b}, @var{shape}) -## Convolve two vectors. +## Convolve two vectors @var{a} and @var{b}. ## -## @code{c = conv (@var{a}, @var{b})} returns a vector of length equal to +## The output convolution is a vector with length equal to ## @code{length (@var{a}) + length (@var{b}) - 1}. -## If @var{a} and @var{b} are the coefficient vectors of two polynomials, the -## returned value is the coefficient vector of the product polynomial. +## When @var{a} and @var{b} are the coefficient vectors of two polynomials, the +## convolution represents the coefficient vector of the product polynomial. ## ## The optional @var{shape} argument may be ## @@ -50,7 +50,9 @@ endif if (! (isvector (a) && isvector (b))) - error ("conv: both arguments must be vectors"); + error ("conv: both arguments A and B must be vectors"); + elseif (nargin == 3 && ! any (strcmpi (shape, {"full", "same"}))) + error ('conv: SHAPE argument must be "full" or "same"'); endif la = length (a); @@ -60,40 +62,31 @@ if (ly == 0) y = zeros (1, 0); - else - ## Use the shortest vector as the coefficent vector to filter. - ## Preserve the row/column orientation of the longer input. - if (la <= lb) - if (ly > lb) - if (size (b, 1) <= size (b, 2)) - x = [b, (zeros (1, ly - lb))]; - else - x = [b; (zeros (ly - lb, 1))]; - endif - else - x = b; - endif - y = filter (a, 1, x); - else - if (ly > la) - if (size (a, 1) <= size (a, 2)) - x = [a, (zeros (1, ly - la))]; - else - x = [a; (zeros (ly - la, 1))]; - endif - else - x = a; - endif - y = filter (b, 1, x); - endif - if (strcmp (shape, "same")) - idx = ceil ((ly - la) / 2); - y = y(idx+1:idx+la); - endif + return; + endif + + ## Use shortest vector as the coefficent vector to filter. + if (la > lb) + [a, b] = deal (b, a); # Swap vectors + lb = la; + endif + x = b; + + ## Pad longer vector to convolution length. + if (ly > lb) + x(end+1:end+ly-lb) = 0; + endif + + y = filter (a, 1, x); + + if (strcmp (shape, "same")) + idx = ceil ((ly - la) / 2); + y = y(idx+1:idx+la); endif endfunction + %!test %! x = ones(3,1); %! y = ones(1,3); @@ -112,35 +105,37 @@ %!test %! a = 1:10; %! b = 1:3; -%! assert (size(conv(a,b)), [1, numel(a)+numel(b)-1]) -%! assert (size(conv(b,a)), [1, numel(a)+numel(b)-1]) +%! assert (size (conv(a,b)), [1, numel(a)+numel(b)-1]); +%! assert (size (conv(b,a)), [1, numel(a)+numel(b)-1]); +%!test %! a = (1:10).'; %! b = 1:3; -%! assert (size(conv(a,b)), [numel(a)+numel(b)-1, 1]) -%! assert (size(conv(b,a)), [numel(a)+numel(b)-1, 1]) +%! assert (size (conv(a,b)), [numel(a)+numel(b)-1, 1]); +%! assert (size (conv(b,a)), [numel(a)+numel(b)-1, 1]); %!test %! a = 1:10; %! b = (1:3).'; -%! assert (size(conv(a,b)), [1, numel(a)+numel(b)-1]) -%! assert (size(conv(b,a)), [1, numel(a)+numel(b)-1]) +%! assert (size (conv(a,b)), [1, numel(a)+numel(b)-1]); +%! assert (size (conv(b,a)), [1, numel(a)+numel(b)-1]); %!test %! a = 1:10; %! b = 1:3; -%! assert (conv(a,b,"full"), conv(a,b)) -%! assert (conv(b,a,"full"), conv(b,a)) +%! assert (conv (a,b,"full"), conv (a,b)); +%! assert (conv (b,a,"full"), conv (b,a)); %!test %! a = 1:10; %! b = 1:3; -%! assert (conv(a,b,'same'), [4, 10, 16, 22, 28, 34, 40, 46, 52, 47]) -%! assert (conv(b,a,'same'), [28, 34, 40]) +%! assert (conv (a,b,"same"), [4, 10, 16, 22, 28, 34, 40, 46, 52, 47]); +%! assert (conv (b,a,"same"), [28, 34, 40]); %% Test input validation -%!error conv (1); -%!error conv (1,2,3,4); -%!error conv ([1, 2; 3, 4], 3); -%!error conv (2, []); +%!error conv (1) +%!error conv (1,2,3,4) +%!error conv ([1, 2; 3, 4], 3) +%!error conv (3, [1, 2; 3, 4]) +%!error conv (2, 3, "XXXX")