diff -r cd38f31e9b4b libinterp/corefcn/qr.cc --- a/libinterp/corefcn/qr.cc Fri Apr 08 17:44:26 2022 -0400 +++ b/libinterp/corefcn/qr.cc Sat Apr 09 15:53:46 2022 -0400 @@ -116,6 +116,7 @@ DEFUN (qr, args, nargout, @deftypefnx {} {@var{X} =} qr (@var{A}, @var{B}) # sparse A @deftypefnx {} {[@var{C}, @var{R}] =} qr (@var{A}, @var{B}) @deftypefnx {} {[@dots{}] =} qr (@dots{}, 0) +@deftypefnx {} {[@dots{}] =} qr (@dots{}, "econ") @deftypefnx {} {[@dots{}] =} qr (@dots{}, "vector") @deftypefnx {} {[@dots{}] =} qr (@dots{}, "matrix") @cindex QR factorization @@ -270,14 +271,14 @@ matrix. In this case, the defining rela The default, however, is to return a permutation matrix and this may be explicitly specified by using a final argument of @qcode{"matrix"}. -If the final argument is the scalar 0 an @qcode{"economy"} factorization is -returned. If the original matrix @var{A} has size MxN and M > N, then the -@qcode{"economy"} factorization will calculate just N rows in @var{R} and N -columns in @var{Q} and omit the zeros in @var{R}. If M @leq{} N, there is no -difference between the economy and standard factorizations. When calculating -an @qcode{"economy"} factorization and @var{A} is dense, the output @var{P} is -always a vector rather than a matrix. If @var{A} is sparse, output -@var{P} is a sparse permutation matrix. +If the final argument is the scalar 0 or the string @qcode{"econ"}, an +economy factorization is returned. If the original matrix @var{A} has size +MxN and M > N, then the economy factorization will calculate just N rows in +@var{R} and N columns in @var{Q} and omit the zeros in @var{R}. If M @leq{} +N, there is no difference between the economy and standard factorizations. +When calculating an economy factorization and @var{A} is dense, the output +@var{P} is always a vector rather than a matrix. If @var{A} is sparse, +output @var{P} is a sparse permutation matrix. Background: The QR factorization has applications in the solution of least squares problems @@ -344,9 +345,14 @@ orthogonal basis of @code{span (A)}. std::string str = args(nargin-1).string_value (); if (str == "vector") vector_p = true; + else if (str == "econ") + { + economy = true; + have_b = (nargin > 2); + } else if (str != "matrix") - error ("qr: type for P must be 'matrix' or 'vector', not %s", - str.c_str ()); + error ("qr: option string must be 'econ' or 'matrix' or " \ + "'vector', not \"%s\"", str.c_str ()); have_b = (nargin > 2); } else if (! args(nargin-1).is_matrix_type ()) @@ -704,45 +710,55 @@ orthogonal basis of @code{span (A)}. %! %! [q, r] = qr (a); %! [qe, re] = qr (a, 0); +%! [qe2, re2] = qr (a, "econ"); %! %! assert (q * r, a, sqrt (eps)); %! assert (qe * re, a, sqrt (eps)); +%! assert (qe2 * re2, a, sqrt (eps)); %!test %! a = [0, 2, 1; 2, 1, 2]; %! %! [q, r] = qr (a); %! [qe, re] = qr (a, 0); +%! [qe2, re2] = qr (a, "econ"); %! %! assert (q * r, a, sqrt (eps)); %! assert (qe * re, a, sqrt (eps)); +%! assert (qe2 * re2, a, sqrt (eps)); %!test %! a = [0, 2, 1; 2, 1, 2]; %! %! [q, r, p] = qr (a); # FIXME: not giving right dimensions. %! [qe, re, pe] = qr (a, 0); +%! [qe2, re2, pe2] = qr (a, "econ"); %! %! assert (q * r, a * p, sqrt (eps)); %! assert (qe * re, a(:, pe), sqrt (eps)); +%! assert (qe2 * re2, a(:, pe2), sqrt (eps)); %!test %! a = [0, 2; 2, 1; 1, 2]; %! %! [q, r] = qr (a); %! [qe, re] = qr (a, 0); +%! [qe2, re2] = qr (a, "econ"); %! %! assert (q * r, a, sqrt (eps)); %! assert (qe * re, a, sqrt (eps)); +%! assert (qe2 * re2, a, sqrt (eps)); %!test %! a = [0, 2; 2, 1; 1, 2]; %! %! [q, r, p] = qr (a); %! [qe, re, pe] = qr (a, 0); +%! [qe2, re2, pe2] = qr (a, "econ"); %! %! assert (q * r, a * p, sqrt (eps)); %! assert (qe * re, a(:, pe), sqrt (eps)); +%! assert (qe2 * re2, a(:, pe2), sqrt (eps)); %!test %! a = [0, 2, 1; 2, 1, 2; 3, 1, 2]; @@ -791,6 +807,10 @@ orthogonal basis of @code{span (A)}. %!error qr () %!error qr ([1, 2; 3, 4], 0, 2) +%!error