changeset 25736:138f91fb2883

ordeig.m: Use Octave coding conventions in function. * linalg.txi: Move docstring location to be near ordschur for relevance. * ordeig.m: Use common GPL text header at start of file. Change docstring to start with an initial one sentence summary of the function. Add semicolons to all error() invocations. Eliminate (! isquasitri (B)) validation check as B has not yet been determined to even be a valid square, numeric matrix yet. Use in-place '+=' operator for efficiency. Add semicolon to assert statements that are within %!test blocks. Add tests for input validation.
author Rik <rik@octave.org>
date Fri, 03 Aug 2018 09:00:49 -0700
parents d45b0027d325
children 799dcddaf158
files doc/interpreter/linalg.txi scripts/linear-algebra/ordeig.m
diffstat 2 files changed, 47 insertions(+), 30 deletions(-) [+]
line wrap: on
line diff
--- a/doc/interpreter/linalg.txi	Fri Aug 03 17:21:00 2018 +0200
+++ b/doc/interpreter/linalg.txi	Fri Aug 03 09:00:49 2018 -0700
@@ -122,8 +122,6 @@
 
 @DOCSTRING(null)
 
-@DOCSTRING(ordeig)
-
 @DOCSTRING(orth)
 
 @DOCSTRING(mgorth)
@@ -185,6 +183,8 @@
 
 @DOCSTRING(ordschur)
 
+@DOCSTRING(ordeig)
+
 @DOCSTRING(subspace)
 
 @DOCSTRING(svd)
--- a/scripts/linear-algebra/ordeig.m	Fri Aug 03 17:21:00 2018 +0200
+++ b/scripts/linear-algebra/ordeig.m	Fri Aug 03 09:00:49 2018 -0700
@@ -3,9 +3,9 @@
 ##
 ## This file is part of Octave.
 ##
-## Octave is free software; you can redistribute it and/or modify it
+## Octave 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 3 of the License, or
+## the Free Software Foundation, either version 3 of the License, or
 ## (at your option) any later version.
 ##
 ## Octave is distributed in the hope that it will be useful, but
@@ -15,20 +15,21 @@
 ##
 ## You should have received a copy of the GNU General Public License
 ## along with Octave; see the file COPYING.  If not, see
-## <http://www.gnu.org/licenses/>.
+## <https://www.gnu.org/licenses/>.
 
 ## -*- texinfo -*-
 ## @deftypefn  {} {@var{lambda} =} ordeig (@var{A})
 ## @deftypefnx {} {@var{lambda} =} ordeig (@var{A}, @var{B})
-## Return the eigenvalues of quasi-triangular matrices in their order
-## of appearance on the matrix @var{A}.  The matrix @var{A} is usually
-## the result of a Schur factorization.  If @var{B} is given, then the
-## generalized eigenvalues of the pair @var{A}, @var{B} are computed,
-## in their order of appearance on the matrix
-## @code{@var{A}-@var{lambda}*@var{B}}. The pair @var{A}, @var{B} is
-## usually the result of a QZ decomposition.
+## Return the eigenvalues of quasi-triangular matrices in their order of
+## appearance in the matrix @var{A}.
 ##
-## @seealso{eig, schur, qz}
+## The quasi-triangular matrix @var{A} is usually the result of a Schur
+## factorization.  If called with a second input @var{B} then the generalized
+## eigenvalues of the pair @var{A}, @var{B} are returned in the order of
+## appearance of the matrix @code{@var{A}-@var{lambda}*@var{B}}.  The pair
+## @var{A}, @var{B} is usually the result of a QZ decomposition.
+##
+## @seealso{ordschur, eig, schur, qz}
 ## @end deftypefn
 
 function lambda = ordeig (A, B)
@@ -47,31 +48,31 @@
     B = eye (n);
     if (isreal (A))
       if (! isquasitri (A))
-        error ("ordeig: A must be quasi-triangular (i.e. upper block triangular with 1x1 or 2x2 blocks on the diagonal)")
+        error ("ordeig: A must be quasi-triangular (i.e., upper block triangular with 1x1 or 2x2 blocks on the diagonal)");
       endif
     else
       if (! istriu (A))
-        error ("ordeig: A must be upper-triangular when it is complex")
+        error ("ordeig: A must be upper-triangular when it is complex");
       endif
     endif
-  elseif (! isquasitri (B))
+  else
     if (! isnumeric (B) || ! issquare (B))
-      error ("ordeig: B must be a square matrix")
-    endif
-    if (length (B) != n)
-      error ("ordeig: A and B must be of the same size")
+      error ("ordeig: B must be a square matrix");
+    elseif (length (B) != n)
+      error ("ordeig: A and B must be the same size");
     endif
     if (isreal (A) && isreal (B))
       if (! isquasitri (A) || ! isquasitri (B))
-        error ("ordeig: A and B must be quasi-triangular (i.e. upper block triangular with 1x1 or 2x2 blocks on the diagonal)")
+        error ("ordeig: A and B must be quasi-triangular (i.e., upper block triangular with 1x1 or 2x2 blocks on the diagonal)");
       endif
     else
       if (! istriu (A) || ! istriu (B))
-        error ("ordeig: A and B must be both upper-triangular if any of the two is complex")
+        error ("ordeig: A and B must both be upper-triangular if either is complex");
       endif
     endif
   endif
 
+  ## Start of algorithm
   lambda = zeros (n, 1);
 
   i = 1;
@@ -85,15 +86,15 @@
           (A(i,i+1) - B(i,i+1)) * (A(i+1,i) - B(i+1,i));
       if (b > 0)
         lambda(i) = 2*c / (-b - sqrt (b^2 - 4*a*c));
-        i = i + 1;
+        i += 1;
         lambda(i) = (-b - sqrt (b^2 - 4*a*c)) / 2 / a;
       else
         lambda(i) = (-b + sqrt (b^2 - 4*a*c)) / 2 / a;
-        i = i + 1;
+        i += 1;
         lambda(i) = 2*c / (-b + sqrt (b^2 - 4*a*c));
       endif
     endif
-    i = i + 1;
+    i += 1;
   endwhile
 
 endfunction
@@ -104,20 +105,36 @@
   retval = all (tril (A, -2)(:) == 0) && all (v(1:end-1) + v(2:end) < 2);
 endfunction
 
+
 %!test
 %! A = toeplitz ([0, 1, 0, 0], [0, -1, 0, 0]);
 %! T = schur (A);
 %! lambda = ordeig (T);
-%! assert (lambda, [1.61803i; -1.61803i; 0.61803i; -0.61803i], 1e-4)
+%! assert (lambda, [1.61803i; -1.61803i; 0.61803i; -0.61803i], 1e-4);
 
 %!test
 %! A = toeplitz ([0, 1, 0, 0], [0, -1, 0, 0]);
 %! B = toeplitz ([0, 0, 0, 1], [0, -1, 0, 2]);
 %! [AA, BB] = qz (A, B);
-%! assert (isreal (AA) && isreal (BB))
+%! assert (isreal (AA) && isreal (BB));
 %! lambda = ordeig (AA, BB);
-%! assert (lambda, [0.5+0.86603i; 0.5-0.86603i; i; -i], 1e-4)
+%! assert (lambda, [0.5+0.86603i; 0.5-0.86603i; i; -i], 1e-4);
 %! [AA, BB] = qz (complex (A), complex (B));
-%! assert (iscomplex (AA) && iscomplex (BB))
+%! assert (iscomplex (AA) && iscomplex (BB));
 %! lambda = ordeig (AA, BB);
-%! assert (lambda, diag (AA) ./ diag (BB))
+%! assert (lambda, diag (AA) ./ diag (BB));
+
+## Test input validation
+%!error ordeig ()
+%!error ordeig (1,2,3)
+%!error <A must be a square matrix> ordeig ('a')
+%!error <A must be a square matrix> ordeig ([1, 2, 3])
+%!error <A must be quasi-triangular> ordeig (magic (3))
+%!error <A must be upper-triangular> ordeig ([1, 0; i, 1])
+%!error <B must be a square matrix> ordeig (1, 'a')
+%!error <B must be a square matrix> ordeig (1, [1, 2])
+%!error <A and B must be the same size> ordeig (1, ones (2,2))
+%!error <A and B must be quasi-triangular>
+%! ordeig (triu (magic (3)), magic (3))
+%!error <A and B must both be upper-triangular>
+%! ordeig ([1, 1; 0, 1], [1, 0; i, 1])