changeset 24195:d3dc76efb38b

Return correct value for pinv of zero vectors and scalars (bug #51246). CMatrix.cc, dMatrix.cc (pseudo_inverse): Change any computed tolerance of 0 to std::numeric_limits<double>::min() so that zero values are later dropped from calculation. fCMatrix.cc, fMatrix.cc (pseudo_inverse): Change calculation of default tolerance to us the <float> version of std::numeric_limits::epsilon () rather than the double version. Change any computed tolerance of 0 to std::numeric_limits<float>::min() so that zero values are later dropped from calculation. * pinv.cc (Fpinv): Add BIST tests.
author Rik <rik@octave.org>
date Fri, 03 Nov 2017 10:03:36 -0700
parents 3333ca37c038
children 2b769c242188
files libinterp/corefcn/pinv.cc liboctave/array/CMatrix.cc liboctave/array/dMatrix.cc liboctave/array/fCMatrix.cc liboctave/array/fMatrix.cc
diffstat 5 files changed, 25 insertions(+), 4 deletions(-) [+]
line wrap: on
line diff
--- a/libinterp/corefcn/pinv.cc	Fri Nov 03 15:49:18 2017 +0100
+++ b/libinterp/corefcn/pinv.cc	Fri Nov 03 10:03:36 2017 -0700
@@ -189,4 +189,13 @@
 %! y = pinv (x, 2);
 %! assert (diag (y), [1/3 1/2 0 0 0]');
 
+## Test special case of 0 scalars and vectors
+%!assert (pinv (0), 0)
+%!assert (pinv ([0, 0, 0]), [0; 0; 0])
+%!assert (pinv (single (0)), single (0))
+%!assert (pinv (single ([0, 0, 0])), single ([0; 0; 0]))
+%!assert (pinv (complex (0,0)), 0)
+%!assert (pinv (complex ([0,0,0], [0,0,0])), [0; 0; 0])
+%!assert (pinv (complex (single (0),0)), single (0))
+%!assert (pinv (complex (single ([0,0,0]), [0,0,0])), single ([0; 0; 0]))
 */
--- a/liboctave/array/CMatrix.cc	Fri Nov 03 15:49:18 2017 +0100
+++ b/liboctave/array/CMatrix.cc	Fri Nov 03 10:03:36 2017 -0700
@@ -973,6 +973,9 @@
         tol = nr * sigma.elem (0) * std::numeric_limits<double>::epsilon ();
       else
         tol = nc * sigma.elem (0) * std::numeric_limits<double>::epsilon ();
+
+      if (tol == 0)
+        tol = std::numeric_limits<double>::min ();
     }
 
   while (r >= 0 && sigma.elem (r) < tol)
--- a/liboctave/array/dMatrix.cc	Fri Nov 03 15:49:18 2017 +0100
+++ b/liboctave/array/dMatrix.cc	Fri Nov 03 10:03:36 2017 -0700
@@ -672,6 +672,9 @@
         tol = nr * sigma.elem (0) * std::numeric_limits<double>::epsilon ();
       else
         tol = nc * sigma.elem (0) * std::numeric_limits<double>::epsilon ();
+
+      if (tol == 0)
+        tol = std::numeric_limits<double>::min ();
     }
 
   while (r >= 0 && sigma.elem (r) < tol)
--- a/liboctave/array/fCMatrix.cc	Fri Nov 03 15:49:18 2017 +0100
+++ b/liboctave/array/fCMatrix.cc	Fri Nov 03 10:03:36 2017 -0700
@@ -972,9 +972,12 @@
   if (tol <= 0.0)
     {
       if (nr > nc)
-        tol = nr * sigma.elem (0) * std::numeric_limits<double>::epsilon ();
+        tol = nr * sigma.elem (0) * std::numeric_limits<float>::epsilon ();
       else
-        tol = nc * sigma.elem (0) * std::numeric_limits<double>::epsilon ();
+        tol = nc * sigma.elem (0) * std::numeric_limits<float>::epsilon ();
+
+      if (tol == 0)
+        tol = std::numeric_limits<float>::min ();
     }
 
   while (r >= 0 && sigma.elem (r) < tol)
--- a/liboctave/array/fMatrix.cc	Fri Nov 03 15:49:18 2017 +0100
+++ b/liboctave/array/fMatrix.cc	Fri Nov 03 10:03:36 2017 -0700
@@ -675,9 +675,12 @@
   if (tol <= 0.0)
     {
       if (nr > nc)
-        tol = nr * sigma.elem (0) * std::numeric_limits<double>::epsilon ();
+        tol = nr * sigma.elem (0) * std::numeric_limits<float>::epsilon ();
       else
-        tol = nc * sigma.elem (0) * std::numeric_limits<double>::epsilon ();
+        tol = nc * sigma.elem (0) * std::numeric_limits<float>::epsilon ();
+
+      if (tol == 0)
+        tol = std::numeric_limits<float>::min ();
     }
 
   while (r >= 0 && sigma.elem (r) < tol)