# HG changeset patch # User John W. Eaton # Date 1347563687 14400 # Node ID 197774b411ec4040f18331b8be294415bbb5347a # Parent 4663cc835c65873fe12b599bcab11ba4a8f5fb87 rcond: use new copy of data for full factorization if positive definite cholesky factorization fails (bug #37336) * dMatrix.cc (Matrix::rcond): Don't reuse modified matrix data if positive definite cholesky factorization was attempted but fails. * CMatrix.cc (ComplexMatrix::rcond): Likewise. * fMatrix.cc (FloatMatrix::rcond): Likewise. * fCMatrix.cc (FloatComplexMatrix::rcond): Likewise. * rcond.cc: New tests. diff -r 4663cc835c65 -r 197774b411ec liboctave/CMatrix.cc --- a/liboctave/CMatrix.cc Thu Jun 21 14:42:05 2012 -0400 +++ b/liboctave/CMatrix.cc Thu Sep 13 15:14:47 2012 -0400 @@ -1786,13 +1786,15 @@ else if (typ == MatrixType::Full || typ == MatrixType::Hermitian) { double anorm = -1.0; - ComplexMatrix atmp = *this; - Complex *tmp_data = atmp.fortran_vec (); if (typ == MatrixType::Hermitian) { octave_idx_type info = 0; char job = 'L'; + + ComplexMatrix atmp = *this; + Complex *tmp_data = atmp.fortran_vec (); + anorm = atmp.abs().sum(). row(static_cast(0)).max(); @@ -1829,6 +1831,9 @@ { octave_idx_type info = 0; + ComplexMatrix atmp = *this; + Complex *tmp_data = atmp.fortran_vec (); + Array ipvt (dim_vector (nr, 1)); octave_idx_type *pipvt = ipvt.fortran_vec (); @@ -2098,8 +2103,10 @@ { info = 0; char job = 'L'; + ComplexMatrix atmp = *this; Complex *tmp_data = atmp.fortran_vec (); + anorm = atmp.abs().sum().row(static_cast(0)).max(); F77_XFCN (zpotrf, ZPOTRF, (F77_CONST_CHAR_ARG2 (&job, 1), nr, diff -r 4663cc835c65 -r 197774b411ec liboctave/dMatrix.cc --- a/liboctave/dMatrix.cc Thu Jun 21 14:42:05 2012 -0400 +++ b/liboctave/dMatrix.cc Thu Sep 13 15:14:47 2012 -0400 @@ -1454,13 +1454,15 @@ else if (typ == MatrixType::Full || typ == MatrixType::Hermitian) { double anorm = -1.0; - Matrix atmp = *this; - double *tmp_data = atmp.fortran_vec (); if (typ == MatrixType::Hermitian) { octave_idx_type info = 0; char job = 'L'; + + Matrix atmp = *this; + double *tmp_data = atmp.fortran_vec (); + anorm = atmp.abs().sum(). row(static_cast(0)).max(); @@ -1495,6 +1497,9 @@ { octave_idx_type info = 0; + Matrix atmp = *this; + double *tmp_data = atmp.fortran_vec (); + Array ipvt (dim_vector (nr, 1)); octave_idx_type *pipvt = ipvt.fortran_vec (); @@ -1760,8 +1765,10 @@ { info = 0; char job = 'L'; + Matrix atmp = *this; double *tmp_data = atmp.fortran_vec (); + anorm = atmp.abs().sum().row(static_cast(0)).max(); F77_XFCN (dpotrf, DPOTRF, (F77_CONST_CHAR_ARG2 (&job, 1), nr, @@ -1838,6 +1845,7 @@ Matrix atmp = *this; double *tmp_data = atmp.fortran_vec (); + if(anorm < 0.) anorm = atmp.abs().sum().row(static_cast(0)).max(); diff -r 4663cc835c65 -r 197774b411ec liboctave/fCMatrix.cc --- a/liboctave/fCMatrix.cc Thu Jun 21 14:42:05 2012 -0400 +++ b/liboctave/fCMatrix.cc Thu Sep 13 15:14:47 2012 -0400 @@ -1782,13 +1782,15 @@ else if (typ == MatrixType::Full || typ == MatrixType::Hermitian) { float anorm = -1.0; - FloatComplexMatrix atmp = *this; - FloatComplex *tmp_data = atmp.fortran_vec (); if (typ == MatrixType::Hermitian) { octave_idx_type info = 0; char job = 'L'; + + FloatComplexMatrix atmp = *this; + FloatComplex *tmp_data = atmp.fortran_vec (); + anorm = atmp.abs().sum(). row(static_cast(0)).max(); @@ -1825,6 +1827,9 @@ { octave_idx_type info = 0; + FloatComplexMatrix atmp = *this; + FloatComplex *tmp_data = atmp.fortran_vec (); + Array ipvt (dim_vector (nr, 1)); octave_idx_type *pipvt = ipvt.fortran_vec (); @@ -2094,8 +2099,10 @@ { info = 0; char job = 'L'; + FloatComplexMatrix atmp = *this; FloatComplex *tmp_data = atmp.fortran_vec (); + anorm = atmp.abs().sum().row(static_cast(0)).max(); F77_XFCN (cpotrf, CPOTRF, (F77_CONST_CHAR_ARG2 (&job, 1), nr, diff -r 4663cc835c65 -r 197774b411ec liboctave/fMatrix.cc --- a/liboctave/fMatrix.cc Thu Jun 21 14:42:05 2012 -0400 +++ b/liboctave/fMatrix.cc Thu Sep 13 15:14:47 2012 -0400 @@ -1454,13 +1454,15 @@ else if (typ == MatrixType::Full || typ == MatrixType::Hermitian) { float anorm = -1.0; - FloatMatrix atmp = *this; - float *tmp_data = atmp.fortran_vec (); if (typ == MatrixType::Hermitian) { octave_idx_type info = 0; char job = 'L'; + + FloatMatrix atmp = *this; + float *tmp_data = atmp.fortran_vec (); + anorm = atmp.abs().sum(). row(static_cast(0)).max(); @@ -1495,6 +1497,9 @@ { octave_idx_type info = 0; + FloatMatrix atmp = *this; + float *tmp_data = atmp.fortran_vec (); + Array ipvt (dim_vector (nr, 1)); octave_idx_type *pipvt = ipvt.fortran_vec (); @@ -1760,8 +1765,10 @@ { info = 0; char job = 'L'; + FloatMatrix atmp = *this; float *tmp_data = atmp.fortran_vec (); + anorm = atmp.abs().sum().row(static_cast(0)).max(); F77_XFCN (spotrf, SPOTRF, (F77_CONST_CHAR_ARG2 (&job, 1), nr, @@ -1838,6 +1845,7 @@ FloatMatrix atmp = *this; float *tmp_data = atmp.fortran_vec (); + if(anorm < 0.) anorm = atmp.abs().sum().row(static_cast(0)).max(); diff -r 4663cc835c65 -r 197774b411ec src/DLD-FUNCTIONS/rcond.cc --- a/src/DLD-FUNCTIONS/rcond.cc Thu Jun 21 14:42:05 2012 -0400 +++ b/src/DLD-FUNCTIONS/rcond.cc Thu Sep 13 15:14:47 2012 -0400 @@ -93,4 +93,12 @@ %!assert( rcond ([1 1; 2 1]), 1/9) %!assert( rcond (magic (4)), 0, eps) +%!shared x, sx +%! x = [-5.25, -2.25; -2.25, 1] * eps () + ones (2) / 2; +%! sx = [-5.25, -2.25; -2.25, 1] * eps ("single") + ones (2) / 2; +%!assert (rcond (x) < eps ()); +%!assert (rcond (sx) < eps ('single')); +%!assert (rcond (x*i) < eps ()); +%!assert (rcond (sx*i) < eps ('single')); + */