changeset 22598:5aa8f199e328 stable

avoid invalid BLAS calls that then invoke xerbla (bug #39000) * dMatrix.cc (Matrix::lssolve): Don't call dgelsd if norm is inf or nan. * fMatrix.cc (FloatMatrix::lssolve): Likewise, for sgelsd. * CMatrix.cc (ComplexMatrix::lssolve): Likewise, for zgelsd. * fCMatrix.cc (FloatComplexMatrix::lssolve): Likewise, for cgelsd. * test/bug-46330.tst: Don't avoid test on Windows systems.
author Avinoam Kalma <a.kalma@gmail.com>
date Thu, 06 Oct 2016 11:52:12 -0400
parents 8d3a2d1af389
children 51b395d24782
files liboctave/array/CMatrix.cc liboctave/array/dMatrix.cc liboctave/array/fCMatrix.cc liboctave/array/fMatrix.cc test/bug-46330.tst
diffstat 5 files changed, 91 insertions(+), 48 deletions(-) [+]
line wrap: on
line diff
--- a/liboctave/array/CMatrix.cc	Wed Oct 05 17:35:24 2016 +0200
+++ b/liboctave/array/CMatrix.cc	Thu Oct 06 11:52:12 2016 -0400
@@ -2415,6 +2415,7 @@
       double dminmn = static_cast<double> (minmn);
       double dsmlsizp1 = static_cast<double> (smlsiz+1);
       double tmp = octave::math::log2 (dminmn / dsmlsizp1);
+      double anorm = 0.0;
 
       octave_idx_type nlvl = static_cast<octave_idx_type> (tmp) + 1;
       if (nlvl < 0)
@@ -2473,18 +2474,29 @@
       lwork = static_cast<octave_idx_type> (octave::math::real (work(0)));
       work.resize (dim_vector (lwork, 1));
 
-      F77_XFCN (zgelsd, ZGELSD, (m, n, nrhs, F77_DBLE_CMPLX_ARG (tmp_data), m,
-                                 F77_DBLE_CMPLX_ARG (pretval),
-                                 maxmn, ps, rcon, rank,
-                                 F77_DBLE_CMPLX_ARG (work.fortran_vec ()), lwork,
-                                 prwork, piwork, info));
-
-      if (s.elem (0) == 0.0)
-        rcon = 0.0;
+      anorm = xnorm (*this, 1);
+
+      if (octave::math::isinf (anorm) || octave::math::isnan (anorm))
+        {
+          rcon = 0.0;
+          octave::warn_singular_matrix ();
+          retval = Matrix (n, m, 0.0);
+        }
       else
-        rcon = s.elem (minmn - 1) / s.elem (0);
-
-      retval.resize (n, nrhs);
+        {
+          F77_XFCN (zgelsd, ZGELSD, (m, n, nrhs, F77_DBLE_CMPLX_ARG (tmp_data),
+                                     m, F77_DBLE_CMPLX_ARG (pretval),
+                                     maxmn, ps, rcon, rank,
+                                     F77_DBLE_CMPLX_ARG (work.fortran_vec ()),
+                                     lwork, prwork, piwork, info));
+
+          if (s.elem (0) == 0.0)
+            rcon = 0.0;
+          else
+            rcon = s.elem (minmn - 1) / s.elem (0);
+
+          retval.resize (n, nrhs);
+        }
     }
 
   return retval;
--- a/liboctave/array/dMatrix.cc	Wed Oct 05 17:35:24 2016 +0200
+++ b/liboctave/array/dMatrix.cc	Thu Oct 06 11:52:12 2016 -0400
@@ -2076,6 +2076,7 @@
       double dminmn = static_cast<double> (minmn);
       double dsmlsizp1 = static_cast<double> (smlsiz+1);
       double tmp = octave::math::log2 (dminmn / dsmlsizp1);
+      double anorm = 0.0;
 
       octave_idx_type nlvl = static_cast<octave_idx_type> (tmp) + 1;
       if (nlvl < 0)
@@ -2131,17 +2132,28 @@
       lwork = static_cast<octave_idx_type> (work(0));
       work.resize (dim_vector (lwork, 1));
 
-      F77_XFCN (dgelsd, DGELSD, (m, n, nrhs, tmp_data, m, pretval,
-                                 maxmn, ps, rcon, rank,
-                                 work.fortran_vec (), lwork,
-                                 piwork, info));
-
-      if (s.elem (0) == 0.0)
-        rcon = 0.0;
+      anorm = xnorm (*this, 1);
+
+      if (octave::math::isinf (anorm) || octave::math::isnan (anorm))
+        {
+          rcon = 0.0;
+          octave::warn_singular_matrix ();
+          retval = Matrix (n, m, 0.0);
+        }
       else
-        rcon = s.elem (minmn - 1) / s.elem (0);
-
-      retval.resize (n, nrhs);
+        {
+          F77_XFCN (dgelsd, DGELSD, (m, n, nrhs, tmp_data, m, pretval,
+                                     maxmn, ps, rcon, rank,
+                                     work.fortran_vec (), lwork,
+                                     piwork, info));
+
+          if (s.elem (0) == 0.0)
+            rcon = 0.0;
+          else
+            rcon = s.elem (minmn - 1) / s.elem (0);
+
+          retval.resize (n, nrhs);
+        }
     }
 
   return retval;
--- a/liboctave/array/fCMatrix.cc	Wed Oct 05 17:35:24 2016 +0200
+++ b/liboctave/array/fCMatrix.cc	Thu Oct 06 11:52:12 2016 -0400
@@ -2432,6 +2432,7 @@
       float dminmn = static_cast<float> (minmn);
       float dsmlsizp1 = static_cast<float> (smlsiz+1);
       float tmp = octave::math::log2 (dminmn / dsmlsizp1);
+      float anorm = 0.0;
 
       octave_idx_type nlvl = static_cast<octave_idx_type> (tmp) + 1;
       if (nlvl < 0)
@@ -2490,18 +2491,29 @@
       lwork = static_cast<octave_idx_type> (octave::math::real (work(0)));
       work.resize (dim_vector (lwork, 1));
 
-      F77_XFCN (cgelsd, CGELSD, (m, n, nrhs, F77_CMPLX_ARG (tmp_data), m,
-                                 F77_CMPLX_ARG (pretval),
-                                 maxmn, ps, rcon, rank,
-                                 F77_CMPLX_ARG (work.fortran_vec ()), lwork,
-                                 prwork, piwork, info));
-
-      if (s.elem (0) == 0.0)
-        rcon = 0.0;
+      anorm = xnorm (*this, 1);
+
+      if (octave::math::isinf (anorm) || octave::math::isnan (anorm))
+        {
+          rcon = 0.0;
+          octave::warn_singular_matrix ();
+          retval = Matrix (n, m, 0.0);
+        }
       else
-        rcon = s.elem (minmn - 1) / s.elem (0);
-
-      retval.resize (n, nrhs);
+        {
+          F77_XFCN (cgelsd, CGELSD, (m, n, nrhs, F77_CMPLX_ARG (tmp_data),
+                                     m, F77_CMPLX_ARG (pretval),
+                                     maxmn, ps, rcon, rank,
+                                     F77_CMPLX_ARG (work.fortran_vec ()),
+                                     lwork, prwork, piwork, info));
+
+          if (s.elem (0) == 0.0)
+            rcon = 0.0;
+          else
+            rcon = s.elem (minmn - 1) / s.elem (0);
+
+          retval.resize (n, nrhs);
+        }
     }
 
   return retval;
--- a/liboctave/array/fMatrix.cc	Wed Oct 05 17:35:24 2016 +0200
+++ b/liboctave/array/fMatrix.cc	Thu Oct 06 11:52:12 2016 -0400
@@ -2103,6 +2103,7 @@
       float dminmn = static_cast<float> (minmn);
       float dsmlsizp1 = static_cast<float> (smlsiz+1);
       float tmp = octave::math::log2 (dminmn / dsmlsizp1);
+      float anorm = 0.0;
 
       octave_idx_type nlvl = static_cast<octave_idx_type> (tmp) + 1;
       if (nlvl < 0)
@@ -2158,17 +2159,28 @@
       lwork = static_cast<octave_idx_type> (work(0));
       work.resize (dim_vector (lwork, 1));
 
-      F77_XFCN (sgelsd, SGELSD, (m, n, nrhs, tmp_data, m, pretval,
-                                 maxmn, ps, rcon, rank,
-                                 work.fortran_vec (), lwork,
-                                 piwork, info));
-
-      if (s.elem (0) == 0.0)
-        rcon = 0.0;
+      anorm = xnorm (*this, 1);
+
+      if (octave::math::isinf (anorm) || octave::math::isnan (anorm))
+        {
+          rcon = 0.0;
+          octave::warn_singular_matrix ();
+          retval = Matrix (n, m, 0.0);
+        }
       else
-        rcon = s.elem (minmn - 1) / s.elem (0);
-
-      retval.resize (n, nrhs);
+        {
+          F77_XFCN (sgelsd, SGELSD, (m, n, nrhs, tmp_data, m, pretval,
+                                     maxmn, ps, rcon, rank,
+                                     work.fortran_vec (), lwork,
+                                     piwork, info));
+
+          if (s.elem (0) == 0.0)
+            rcon = 0.0;
+          else
+            rcon = s.elem (minmn - 1) / s.elem (0);
+
+          retval.resize (n, nrhs);
+        }
     }
 
   return retval;
--- a/test/bug-46330.tst	Wed Oct 05 17:35:24 2016 +0200
+++ b/test/bug-46330.tst	Thu Oct 06 11:52:12 2016 -0400
@@ -17,9 +17,4 @@
 %! ## This statement caused an error in LAPACK and eventually caused
 %! ## a segmentation fault.
 %! ## Triggers "warning: matrix singular to machine precision"
-%! ## FIXME: LAPACK errors become fatal crashes on Windows, don't test this
-%! if (ispc ())
-%!   warning ("unable to test for bug #46330 on Windows");
-%! else
-%!   assert (c / (i * Inf * eye (4) - a) * b, zeros (2, 2))
-%! endif
+%! assert (c / (i * Inf * eye (4) - a) * b, zeros (2, 2))