changeset 23971:6cc3aafbdc41

improve accuracy of deconv for inputs of very different magnitude (bug #51221) * deconv.m: Compute r from the second output argument of filter.
author Marco Caliari <marco.caliari@univr.it>
date Tue, 29 Aug 2017 16:00:43 -0400
parents 37f3c4416f2e
children b4cf41d173dd
files scripts/polynomial/deconv.m
diffstat 1 files changed, 33 insertions(+), 17 deletions(-) [+]
line wrap: on
line diff
--- a/scripts/polynomial/deconv.m	Sun Jun 25 18:50:44 2017 +0200
+++ b/scripts/polynomial/deconv.m	Tue Aug 29 16:00:43 2017 -0400
@@ -57,34 +57,26 @@
   if (ly > la)
     x = zeros (size (y) - size (a) + 1);
     x(1) = 1;
-    b = filter (y, a, x);
+    [b, r] = filter (y, a, x);
+    r *= a(1);
   elseif (ly == la)
-    b = filter (y, a, 1);
+    [b, r] = filter (y, a, 1);
+    r *= a(1);
   else
     b = 0;
+    r = y;
   endif
 
   if (isargout (2))
-    lc = la + length (b) - 1;
-    if (ly == lc)
-      r = y - conv (a, b);
-    else
-      ## Respect the orientation of Y.
-      if (rows (y) <= columns (y))
-        r = [(zeros (1, lc - ly)), y] - conv (a, b);
-      else
-        r = [(zeros (lc - ly, 1)); y] - conv (a, b);
-      endif
-      if (ly < la)
-        ## Trim the remainder to be the length of Y.
-        r = r(end-(length(y)-1):end);
-      endif
+    if (ly >= la)
+      r = [zeros(ly - la + 1, 1); r(1:la - 1)];
+      ## Respect the orientation of Y
+      r = reshape (r, size (y));
     endif
   endif
 
 endfunction
 
-
 %!test
 %! [b, r] = deconv ([3, 6, 9, 9], [1, 2, 3]);
 %! assert (b, [3, 0]);
@@ -117,3 +109,27 @@
 %!error deconv (1,2,3)
 %!error <Y .* must be vector> deconv ([3, 6], [1, 2; 3, 4])
 %!error <A must be vector> deconv ([3, 6], [1, 2; 3, 4])
+
+%!test
+%! y = (10:-1:1);
+%! a = (4:-1:1);
+%! [b, r] = deconv (y, a);
+%! assert (conv (a, b) + r, y, eps)
+
+%!test <51221>
+%! a = [1.92306958582241e+15, 3.20449986572221e+24, 1.34271290136344e+32, ...
+%!     2.32739765751038e+38];
+%! b = [7.33727670161595e+27, 1.05919311870816e+36, 4.56169848520627e+42];
+%! [div, rem] = deconv (a, b);
+%! assert (rem, [0, 0, -2.89443678763879e+32  -1.58695290534499e+39], -10*eps)
+%! a(2) = 3.204499865722215e+24;
+%! [div, rem] = deconv (a, b);
+%! assert (rem, [0, 0, -2.89443678763879e+32  -1.58695290534499e+39], -10*eps)
+
+%!test
+%! [b, r] = deconv ([1, 1], 1);
+%! assert (r, [0, 0])
+
+%!test
+%! [b, r] = deconv ([1; 1], 1);
+%! assert (r, [0; 0])