changeset 29556:d75aa2bf4915 stable

qz.cc: return correct number of eigenvalues (bug #60357). * qz.cc (Fqz): Change docstring to emphasize that QZ factorization is the main output, and eigenvalues are secondary. Don't truncate number of eigenvalues to the number returned by LAPACK. For eigenvalues that are not defined, return Inf as the eig() function does. (grafted from 06f4bb661d966b4ffd504a29685bb265b6350395)
author Rik <rik@octave.org>
date Fri, 23 Apr 2021 08:04:48 -0700
parents 99e3912441ec
children 50aa945836c3
files libinterp/corefcn/qz.cc
diffstat 1 files changed, 33 insertions(+), 29 deletions(-) [+]
line wrap: on
line diff
--- a/libinterp/corefcn/qz.cc	Sat Apr 24 19:17:16 2021 +0200
+++ b/libinterp/corefcn/qz.cc	Fri Apr 23 08:04:48 2021 -0700
@@ -97,18 +97,18 @@
 Compute QZ@tie{}decomposition, generalized eigenvectors, and generalized
 eigenvalues.
 @tex
+$$ AA = Q^T AZ, BB = Q^T BZ $$
 $$ AV = BV{ \rm diag }(\lambda) $$
 $$ W^T A = { \rm diag }(\lambda)W^T B $$
-$$ AA = Q^T AZ, BB = Q^T BZ $$
 @end tex
 @ifnottex
 
 @example
 @group
 
+@var{AA} = @var{Q} * @var{A} * @var{Z}, @var{BB} = @var{Q} * @var{B} * @var{Z}
 @var{A} * @var{V} = @var{B} * @var{V} * diag (@var{lambda})
 @var{W}' * @var{A} = diag (@var{lambda}) * @var{W}' * @var{B}
-@var{AA} = @var{Q} * @var{A} * @var{Z}, @var{BB} = @var{Q} * @var{B} * @var{Z}
 
 @end group
 @end example
@@ -165,7 +165,7 @@
 (@pxref{XREFbalance,,balance}), which may be lead to less accurate results than
 @code{eig}.  The order of output arguments was selected for compatibility with
 @sc{matlab}.
-@seealso{eig, ordeig, balance, lu, chol, hess, qr, qzhess, schur, svd}
+@seealso{eig, gsvd, balance, chol, hess, lu, qr, qzhess, schur}
 @end deftypefn */)
 {
   int nargin = args.length ();
@@ -682,12 +682,13 @@
           // Return finite generalized eigenvalues.
           ComplexColumnVector tmp (nn);
 
-          F77_INT cnt = 0;
           for (F77_INT i = 0; i < nn; i++)
-            if (betar(i) != 0)
-              tmp(cnt++) = Complex (alphar(i), alphai(i)) / betar(i);
-
-          tmp.resize (cnt);  // Trim vector to number of return values
+            {
+              if (betar(i) != 0)
+                tmp(i) = Complex (alphar(i), alphai(i)) / betar(i);
+              else
+                tmp(i) = octave::numeric_limits<double>::Inf ();
+            }
 
           gev = tmp;
         }
@@ -898,27 +899,30 @@
 }
 
 /*
-%!shared a, b, c
-%! a = [1 2; 0 3];
-%! b = [1 0; 0 0];
-%! c = [0 1; 0 0];
-%!assert (qz (a,b), 1)
-%!assert (isempty (qz (a,c)))
+%!test
+%! A = [1 2; 0 3];
+%! B = [1 0; 0 0];
+%! C = [0 1; 0 0];
+%! assert (qz (A,B), [1; Inf]);
+%! assert (qz (A,C), [Inf; Inf]);
 
 ## Example 7.7.3 in Golub & Van Loan
 %!test
 %! a = [ 10  1  2;
 %!        1  2 -1;
-%!        1  1  2];
-%! b = reshape (1:9,3,3);
+%!        1  1  2 ];
+%! b = reshape (1:9, 3,3);
 %! [aa, bb, q, z, v, w, lambda] = qz (a, b);
-%! sz = length (lambda);
-%! observed = (b * v * diag ([lambda;0])) (:, 1:sz);
-%! assert ((a*v)(:, 1:sz), observed, norm (observed) * 1e-14);
-%! observed = (diag ([lambda;0]) * w' * b) (1:sz, :);
-%! assert ((w'*a)(1:sz, :) , observed, norm (observed) * 1e-13);
 %! assert (q * a * z, aa, norm (aa) * 1e-14);
 %! assert (q * b * z, bb, norm (bb) * 1e-14);
+%! sz = find (isinf (lambda), 1);
+%! if (isempty (sz))
+%!   sz = numel (lamdda);
+%! endif
+%! observed = (b * v * diag (lambda)) (:, 1:sz);
+%! assert ((a*v)(:, 1:sz), observed, norm (observed) * 1e-14);
+%! observed = (diag (lambda) * w' * b) (1:sz, :);
+%! assert ((w'*a)(1:sz, :) , observed, norm (observed) * 1e-13);
 
 %!test
 %! A = [0, 0, -1, 0; 1, 0, 0, 0; -1, 0, -2, -1; 0, -1, 1, 0];
@@ -937,15 +941,15 @@
 %!        0.169281 -0.405205 -1.775834  1.511730;
 %!        0.717770  1.291390 -1.766607 -0.531352 ];
 %! [AA, BB, Z, lambda] = qz (A, B, "+");
-%! assert (all (real (lambda(1:3)) >= 0))
-%! assert (real (lambda(4) < 0))
+%! assert (all (real (lambda(1:3)) >= 0));
+%! assert (real (lambda(4) < 0));
 %! [AA, BB, Z, lambda] = qz (A, B, "-");
-%! assert (real (lambda(1) < 0))
-%! assert (all (real (lambda(2:4)) >= 0))
+%! assert (real (lambda(1) < 0));
+%! assert (all (real (lambda(2:4)) >= 0));
 %! [AA, BB, Z, lambda] = qz (A, B, "B");
-%! assert (all (abs (lambda(1:3)) >= 1))
-%! assert (abs (lambda(4) < 1))
+%! assert (all (abs (lambda(1:3)) >= 1));
+%! assert (abs (lambda(4) < 1));
 %! [AA, BB, Z, lambda] = qz (A, B, "S");
-%! assert (abs (lambda(1) < 1))
-%! assert (all (abs (lambda(2:4)) >= 1))
+%! assert (abs (lambda(1) < 1));
+%! assert (all (abs (lambda(2:4)) >= 1));
 */