Mercurial > octave
changeset 29551:06f4bb661d96
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.
author | Rik <rik@octave.org> |
---|---|
date | Fri, 23 Apr 2021 08:04:48 -0700 |
parents | 8dd0fca2a3d9 |
children | 33556123b892 |
files | libinterp/corefcn/qz.cc |
diffstat | 1 files changed, 33 insertions(+), 29 deletions(-) [+] |
line wrap: on
line diff
--- a/libinterp/corefcn/qz.cc Thu Apr 22 12:52:14 2021 -0400 +++ 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,,@code{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)); */