changeset 22615:68e9bdb7cde3

Accept second input '0' to svd (bug #49309). * svd.cc (Fsvd): Add 3rd calling form to docstring. Document behavior of "econ" and '0' inputs. Add BIST test for bug #49309. Change all calls to svd_type to match new prototype. * svd.cc (svd_type): Change function to have two additional inputs, the octave_value_list args and the matrix A. Change code to use if/else tree to calculate the svd type.
author Rik <rik@octave.org>
date Tue, 11 Oct 2016 14:14:44 -0700
parents edd04ce99891
children 5fdfde2a873d
files libinterp/corefcn/svd.cc
diffstat 1 files changed, 37 insertions(+), 13 deletions(-) [+]
line wrap: on
line diff
--- a/libinterp/corefcn/svd.cc	Tue Oct 11 09:49:21 2016 -0700
+++ b/libinterp/corefcn/svd.cc	Tue Oct 11 14:14:44 2016 -0700
@@ -38,13 +38,22 @@
 
 template <typename T>
 static typename octave::math::svd<T>::Type
-svd_type (int nargin, int nargout)
+svd_type (int nargin, int nargout, const octave_value_list & args, const T & A)
 {
-  return ((nargout == 0 || nargout == 1)
-          ? octave::math::svd<T>::Type::sigma_only
-          : ((nargin == 2)
-             ? octave::math::svd<T>::Type::economy
-             : octave::math::svd<T>::Type::std));
+  if (nargout == 0 || nargout == 1)
+    return octave::math::svd<T>::Type::sigma_only;
+  else if (nargin == 1)
+    return octave::math::svd<T>::Type::std;
+  else
+    if (! args(1).is_real_scalar ())
+      return octave::math::svd<T>::Type::economy;
+    else
+      {
+        if (A.rows () > A.columns ())
+          return octave::math::svd<T>::Type::economy;
+        else
+          return octave::math::svd<T>::Type::std;
+      }
 }
 
 template <typename T>
@@ -60,7 +69,8 @@
        doc: /* -*- texinfo -*-
 @deftypefn  {} {@var{s} =} svd (@var{A})
 @deftypefnx {} {[@var{U}, @var{S}, @var{V}] =} svd (@var{A})
-@deftypefnx {} {[@var{U}, @var{S}, @var{V}] =} svd (@var{A}, @var{econ})
+@deftypefnx {} {[@var{U}, @var{S}, @var{V}] =} svd (@var{A}, "econ")
+@deftypefnx {} {[@var{U}, @var{S}, @var{V}] =} svd (@var{A}, 0)
 @cindex singular value decomposition
 Compute the singular value decomposition of @var{A}
 @tex
@@ -135,9 +145,14 @@
 @end group
 @end example
 
-If given a second argument, @code{svd} returns an economy-sized
+When given a second argument that is not 0, @code{svd} returns an economy-sized
 decomposition, eliminating the unnecessary rows or columns of @var{U} or
 @var{V}.
+
+If the second argument is exactly 0, then the choice of decomposition is based
+on the matrix @var{A}.  If @var{A} has more rows than columns then an
+economy-sized decomposition is returned, otherwise a regular decomposition 
+is calculated.
 @seealso{svd_driver, svds, eig, lu, chol, hess, qr, qz}
 @end deftypefn */)
 {
@@ -165,7 +180,8 @@
             error ("svd: cannot take SVD of matrix containing Inf or NaN values");
 
           octave::math::svd<FloatMatrix> result
-            (tmp, svd_type<FloatMatrix> (nargin, nargout),
+            (tmp,
+             svd_type<FloatMatrix> (nargin, nargout, args, tmp),
              svd_driver<FloatMatrix> ());
 
           FloatDiagMatrix sigma = result.singular_values ();
@@ -185,7 +201,8 @@
             error ("svd: cannot take SVD of matrix containing Inf or NaN values");
 
           octave::math::svd<FloatComplexMatrix> result
-            (ctmp, svd_type<FloatComplexMatrix> (nargin, nargout),
+            (ctmp,
+             svd_type<FloatComplexMatrix> (nargin, nargout, args, ctmp),
              svd_driver<FloatComplexMatrix> ());
 
           FloatDiagMatrix sigma = result.singular_values ();
@@ -208,7 +225,8 @@
             error ("svd: cannot take SVD of matrix containing Inf or NaN values");
 
           octave::math::svd<Matrix> result
-            (tmp, svd_type<Matrix> (nargin, nargout),
+            (tmp,
+             svd_type<Matrix> (nargin, nargout, args, tmp),
              svd_driver<Matrix> ());
 
           DiagMatrix sigma = result.singular_values ();
@@ -228,7 +246,8 @@
             error ("svd: cannot take SVD of matrix containing Inf or NaN values");
 
           octave::math::svd<ComplexMatrix> result
-            (ctmp, svd_type<ComplexMatrix> (nargin, nargout),
+            (ctmp,
+             svd_type<ComplexMatrix> (nargin, nargout, args, ctmp),
              svd_driver<ComplexMatrix> ());
 
           DiagMatrix sigma = result.singular_values ();
@@ -255,7 +274,6 @@
 [u,s,v] = svd (a);
 assert (a, u * s * v', 128 * eps);
 
-
 %!test
 %! [u, s, v] = svd ([1, 2; 2, 1]);
 %! x = 1 / sqrt (2);
@@ -326,6 +344,12 @@
 %! assert (size (s), [0, 0]);
 %! assert (size (v), [0, 0]);
 
+%!test <49309>
+%! [~,~,v] = svd ([1, 1, 1], 0);
+%! assert (size (v), [3 3]);
+%! [~,~,v] = svd ([1, 1, 1], "econ");
+%! assert (size (v), [3 1]);
+
 %!error svd ()
 %!error svd ([1, 2; 4, 5], 2, 3)
 %!error [u, v] = svd ([1, 2; 3, 4])