Mercurial > hg > octave-nkf
changeset 5681:233d98d95659
[project @ 2006-03-16 17:48:55 by dbateman]
author | dbateman |
---|---|
date | Thu, 16 Mar 2006 17:48:56 +0000 |
parents | cc6a965ae4ca |
children | cbc323d109e4 |
files | doc/ChangeLog doc/interpreter/images/sparseimages.m doc/interpreter/sparse.txi liboctave/CSparse.cc liboctave/CSparse.h liboctave/ChangeLog liboctave/MSparse.cc liboctave/Makefile.in liboctave/Sparse-op-defs.h liboctave/Sparse.cc liboctave/SparseCmplxQR.cc liboctave/SparseQR.cc liboctave/SparseType.cc liboctave/dSparse.cc liboctave/dSparse.h scripts/ChangeLog scripts/testfun/test.m src/ChangeLog src/DLD-FUNCTIONS/luinc.cc src/DLD-FUNCTIONS/matrix_type.cc src/DLD-FUNCTIONS/spqr.cc src/sparse-xdiv.cc test/build_sparse_tests.sh |
diffstat | 23 files changed, 4473 insertions(+), 3252 deletions(-) [+] |
line wrap: on
line diff
--- a/doc/ChangeLog +++ b/doc/ChangeLog @@ -1,3 +1,9 @@ +2006-03-16 David Bateman <dbateman@free.fr> + + * interpreter/images/sparseimages.m: set terminal type to dummy to + direct output to terminal rather than X11. + * interpreter/sparse.txi: Update docs for new QR solvers. + 2006-03-09 David Bateman <dbateman@free.fr> * interpreter/Makefile.in: Change order of commands in HTML/index.html
--- a/doc/interpreter/images/sparseimages.m +++ b/doc/interpreter/images/sparseimages.m @@ -1,4 +1,13 @@ function sparseimages(dirc,typ) + ## XXX FIXME XXX + ## How do we set terminal and direct the output to /dev/null without + ## gnuplot? Note that due to replot in print.m, the redirection to + ## /dev/null effectively doesn't work at the moment. + __gnuplot_set__ term dumb + [status, dummy] = fileattrib("/dev/null"); + if (status) + __gnuplot_set__ output '/dev/null' + endif plot(1) # FIXME bypass 2.9.4 bug!! if (strcmp(typ,"txt")) txtimages(15,dirc,typ);
--- a/doc/interpreter/sparse.txi +++ b/doc/interpreter/sparse.txi @@ -745,16 +745,23 @@ solvers can be entirely disabled by using @dfn{spparms} to set @code{bandden} to 1 (i.e. @code{spparms ("bandden", 1)}). -All of the solvers above, expect the banded solvers, calculate an -estimate of the condition number. This can be used to detect numerical -stability problems in the solution and force a minimum norm solution -to be used. However, for narrow banded matrices, the cost of -calculating the condition number is significant, and can in fact exceed -the cost of factoring the matrix. Therefore the condition number is -not calculated for banded matrices, and therefore unless the factorization -is exactly singular, these numerical instabilities won't be detected. -In cases where, this might be a problem the user is recommended to disable -the banded solvers as above, at a significant cost in terms of speed. +The QR solver factorizes the problem with a Dulmage-Mendhelsohn, to +seperate the problem into blocks that can be treated as over-determined, +multiple well determined blocks, and a final over-determined block. For +matrices with blocks of strongly connectted nodes this is a big win as +LU decomposition can be used for many blocks. It also significantly +improves the chance of finding a solution to over-determined problems +rather than just returning a vector of @dfn{NaN}'s. + +All of the solvers above, can calculate an estimate of the condition +number. This can be used to detect numerical stability problems in the +solution and force a minimum norm solution to be used. However, for +narrow banded, triangular or diagonal matrices, the cost of +calculating the condition number is significant, and can in fact +exceed the cost of factoring the matrix. Therefore the condition +number is not calculated in these case, and octave relies on simplier +techniques to detect sinular matrices or the underlying LAPACK code in +the case of banded matrices. The user can force the type of the matrix with the @code{matrix_type} function. This overcomes the cost of discovering the type of the matrix.
--- a/liboctave/CSparse.cc +++ b/liboctave/CSparse.cc @@ -47,6 +47,13 @@ #include "oct-sort.h" +// Define whether to use a basic QR solver or one that uses a Dulmange +// Mendelsohn factorization to seperate the problem into under-determined, +// well-determined and over-determined parts and solves them seperately +#ifndef USE_QRSOLVE +#include "sparse-dmsolve.cc" +#endif + // Fortran functions we call. extern "C" { @@ -82,7 +89,7 @@ F77_RET_T F77_FUNC (zpbcon, ZPBCON) (F77_CONST_CHAR_ARG_DECL, const octave_idx_type&, const octave_idx_type&, Complex*, const octave_idx_type&, - const double&, double&, Complex*, octave_idx_type*, octave_idx_type& + const double&, double&, Complex*, double*, octave_idx_type& F77_CHAR_ARG_LEN_DECL); F77_RET_T @@ -106,33 +113,33 @@ } SparseComplexMatrix::SparseComplexMatrix (const SparseMatrix& a) - : MSparse<Complex> (a.rows (), a.cols (), a.nzmax ()) + : MSparse<Complex> (a.rows (), a.cols (), a.nnz ()) { octave_idx_type nc = cols (); - octave_idx_type nz = nzmax (); + octave_idx_type nz = a.nnz (); for (octave_idx_type i = 0; i < nc + 1; i++) cidx (i) = a.cidx (i); for (octave_idx_type i = 0; i < nz; i++) { - data (i) = a.data (i); + data (i) = Complex (a.data (i)); ridx (i) = a.ridx (i); } } SparseComplexMatrix::SparseComplexMatrix (const SparseBoolMatrix& a) - : MSparse<Complex> (a.rows (), a.cols (), a.nzmax ()) + : MSparse<Complex> (a.rows (), a.cols (), a.nnz ()) { octave_idx_type nc = cols (); - octave_idx_type nz = nzmax (); + octave_idx_type nz = a.nnz (); for (octave_idx_type i = 0; i < nc + 1; i++) cidx (i) = a.cidx (i); for (octave_idx_type i = 0; i < nz; i++) { - data (i) = a.data (i); + data (i) = Complex (a.data (i)); ridx (i) = a.ridx (i); } } @@ -142,10 +149,10 @@ { octave_idx_type nr = rows (); octave_idx_type nc = cols (); - octave_idx_type nz = nzmax (); + octave_idx_type nz = nnz (); octave_idx_type nr_a = a.rows (); octave_idx_type nc_a = a.cols (); - octave_idx_type nz_a = a.nzmax (); + octave_idx_type nz_a = a.nnz (); if (nr != nr_a || nc != nc_a || nz != nz_a) return false; @@ -546,7 +553,7 @@ { octave_idx_type nr = rows (); octave_idx_type nc = cols (); - octave_idx_type nz = nzmax (); + octave_idx_type nz = nnz (); SparseComplexMatrix retval (nc, nr, nz); OCTAVE_LOCAL_BUFFER (octave_idx_type, w, nr + 1); @@ -580,7 +587,7 @@ { octave_idx_type nr = a.rows (); octave_idx_type nc = a.cols (); - octave_idx_type nz = a.nzmax (); + octave_idx_type nz = a.nnz (); SparseComplexMatrix retval (nc, nr, nz); for (octave_idx_type i = 0; i < nc + 1; i++) @@ -713,7 +720,7 @@ if (typ == SparseType::Upper || typ == SparseType::Lower) { - octave_idx_type nz = nzmax (); + octave_idx_type nz = nnz (); octave_idx_type cx = 0; octave_idx_type nz2 = nz; retval = SparseComplexMatrix (nr, nc, nz2); @@ -798,7 +805,7 @@ } else { - octave_idx_type nz = nzmax (); + octave_idx_type nz = nnz (); octave_idx_type cx = 0; octave_idx_type nz2 = nz; retval = SparseComplexMatrix (nr, nc, nz2); @@ -1118,8 +1125,8 @@ ComplexMatrix SparseComplexMatrix::dsolve (SparseType &mattype, const Matrix& b, - octave_idx_type& err, - double& rcond, solve_singularity_handler) const + octave_idx_type& err, double& rcond, + solve_singularity_handler, bool calc_cond) const { ComplexMatrix retval; @@ -1151,16 +1158,21 @@ for (octave_idx_type i = cidx(k); i < cidx(k+1); i++) retval(k,j) = b(ridx(i),j) / data (i); - double dmax = 0., dmin = octave_Inf; - for (octave_idx_type i = 0; i < nm; i++) - { - double tmp = std::abs(data(i)); - if (tmp > dmax) - dmax = tmp; - if (tmp < dmin) - dmin = tmp; - } - rcond = dmin / dmax; + if (calc_cond) + { + double dmax = 0., dmin = octave_Inf; + for (octave_idx_type i = 0; i < nm; i++) + { + double tmp = std::abs(data(i)); + if (tmp > dmax) + dmax = tmp; + if (tmp < dmin) + dmin = tmp; + } + rcond = dmin / dmax; + } + else + rcond = 1.0; } else (*current_liboctave_error_handler) ("incorrect matrix type"); @@ -1172,7 +1184,8 @@ SparseComplexMatrix SparseComplexMatrix::dsolve (SparseType &mattype, const SparseMatrix& b, octave_idx_type& err, double& rcond, - solve_singularity_handler) const + solve_singularity_handler, + bool calc_cond) const { SparseComplexMatrix retval; @@ -1194,7 +1207,7 @@ typ == SparseType::Permuted_Diagonal) { octave_idx_type b_nc = b.cols (); - octave_idx_type b_nz = b.nzmax (); + octave_idx_type b_nz = b.nnz (); retval = SparseComplexMatrix (nc, b_nc, b_nz); retval.xcidx(0) = 0; @@ -1204,6 +1217,8 @@ { for (octave_idx_type i = b.cidx(j); i < b.cidx(j+1); i++) { + if (b.ridx(i) >= nm) + break; retval.xridx (ii) = b.ridx(i); retval.xdata (ii++) = b.data(i) / data (b.ridx (i)); } @@ -1232,16 +1247,21 @@ retval.xcidx(j+1) = ii; } - double dmax = 0., dmin = octave_Inf; - for (octave_idx_type i = 0; i < nm; i++) - { - double tmp = std::abs(data(i)); - if (tmp > dmax) - dmax = tmp; - if (tmp < dmin) - dmin = tmp; - } - rcond = dmin / dmax; + if (calc_cond) + { + double dmax = 0., dmin = octave_Inf; + for (octave_idx_type i = 0; i < nm; i++) + { + double tmp = std::abs(data(i)); + if (tmp > dmax) + dmax = tmp; + if (tmp < dmin) + dmin = tmp; + } + rcond = dmin / dmax; + } + else + rcond = 1.0; } else (*current_liboctave_error_handler) ("incorrect matrix type"); @@ -1253,7 +1273,8 @@ ComplexMatrix SparseComplexMatrix::dsolve (SparseType &mattype, const ComplexMatrix& b, octave_idx_type& err, double& rcond, - solve_singularity_handler) const + solve_singularity_handler, + bool calc_cond) const { ComplexMatrix retval; @@ -1285,16 +1306,21 @@ for (octave_idx_type i = cidx(k); i < cidx(k+1); i++) retval(k,j) = b(ridx(i),j) / data (i); - double dmax = 0., dmin = octave_Inf; - for (octave_idx_type i = 0; i < nr; i++) - { - double tmp = std::abs(data(i)); - if (tmp > dmax) - dmax = tmp; - if (tmp < dmin) - dmin = tmp; - } - rcond = dmin / dmax; + if (calc_cond) + { + double dmax = 0., dmin = octave_Inf; + for (octave_idx_type i = 0; i < nr; i++) + { + double tmp = std::abs(data(i)); + if (tmp > dmax) + dmax = tmp; + if (tmp < dmin) + dmin = tmp; + } + rcond = dmin / dmax; + } + else + rcond = 1.0; } else (*current_liboctave_error_handler) ("incorrect matrix type"); @@ -1306,7 +1332,8 @@ SparseComplexMatrix SparseComplexMatrix::dsolve (SparseType &mattype, const SparseComplexMatrix& b, octave_idx_type& err, double& rcond, - solve_singularity_handler) const + solve_singularity_handler, + bool calc_cond) const { SparseComplexMatrix retval; @@ -1328,7 +1355,7 @@ typ == SparseType::Permuted_Diagonal) { octave_idx_type b_nc = b.cols (); - octave_idx_type b_nz = b.nzmax (); + octave_idx_type b_nz = b.nnz (); retval = SparseComplexMatrix (nc, b_nc, b_nz); retval.xcidx(0) = 0; @@ -1338,6 +1365,8 @@ { for (octave_idx_type i = b.cidx(j); i < b.cidx(j+1); i++) { + if (b.ridx(i) >= nm) + break; retval.xridx (ii) = b.ridx(i); retval.xdata (ii++) = b.data(i) / data (b.ridx (i)); } @@ -1366,16 +1395,21 @@ retval.xcidx(j+1) = ii; } - double dmax = 0., dmin = octave_Inf; - for (octave_idx_type i = 0; i < nm; i++) - { - double tmp = std::abs(data(i)); - if (tmp > dmax) - dmax = tmp; - if (tmp < dmin) - dmin = tmp; - } - rcond = dmin / dmax; + if (calc_cond) + { + double dmax = 0., dmin = octave_Inf; + for (octave_idx_type i = 0; i < nm; i++) + { + double tmp = std::abs(data(i)); + if (tmp > dmax) + dmax = tmp; + if (tmp < dmin) + dmin = tmp; + } + rcond = dmin / dmax; + } + else + rcond = 1.0; } else (*current_liboctave_error_handler) ("incorrect matrix type"); @@ -1387,7 +1421,8 @@ ComplexMatrix SparseComplexMatrix::utsolve (SparseType &mattype, const Matrix& b, octave_idx_type& err, double& rcond, - solve_singularity_handler sing_handler) const + solve_singularity_handler sing_handler, + bool calc_cond) const { ComplexMatrix retval; @@ -1411,23 +1446,26 @@ double anorm = 0.; double ainvnorm = 0.; octave_idx_type b_nc = b.cols (); - rcond = 0.; - - // Calculate the 1-norm of matrix for rcond calculation - for (octave_idx_type j = 0; j < nc; j++) - { - double atmp = 0.; - for (octave_idx_type i = cidx(j); i < cidx(j+1); i++) - atmp += std::abs(data(i)); - if (atmp > anorm) - anorm = atmp; + rcond = 1.; + + if (calc_cond) + { + // Calculate the 1-norm of matrix for rcond calculation + for (octave_idx_type j = 0; j < nc; j++) + { + double atmp = 0.; + for (octave_idx_type i = cidx(j); i < cidx(j+1); i++) + atmp += std::abs(data(i)); + if (atmp > anorm) + anorm = atmp; + } } if (typ == SparseType::Permuted_Upper) { retval.resize (nc, b_nc); octave_idx_type *perm = mattype.triangular_perm (); - OCTAVE_LOCAL_BUFFER (Complex, work, nr); + OCTAVE_LOCAL_BUFFER (Complex, work, nm); for (octave_idx_type j = 0; j < b_nc; j++) { @@ -1442,7 +1480,8 @@ if (work[k] != 0.) { - if (ridx(cidx(kidx+1)-1) != k) + if (ridx(cidx(kidx+1)-1) != k || + data(cidx(kidx+1)-1) == 0.) { err = -2; goto triangular_error; @@ -1463,38 +1502,42 @@ retval (perm[i], j) = work[i]; } - // Calculation of 1-norm of inv(*this) - for (octave_idx_type i = 0; i < nm; i++) - work[i] = 0.; - - for (octave_idx_type j = 0; j < nr; j++) - { - work[j] = 1.; - - for (octave_idx_type k = j; k >= 0; k--) + if (calc_cond) + { + // Calculation of 1-norm of inv(*this) + for (octave_idx_type i = 0; i < nm; i++) + work[i] = 0.; + + for (octave_idx_type j = 0; j < nr; j++) { - octave_idx_type iidx = perm[k]; - - if (work[k] != 0.) + work[j] = 1.; + + for (octave_idx_type k = j; k >= 0; k--) { - Complex tmp = work[k] / data(cidx(iidx+1)-1); - work[k] = tmp; - for (octave_idx_type i = cidx(iidx); - i < cidx(iidx+1)-1; i++) + octave_idx_type iidx = perm[k]; + + if (work[k] != 0.) { - octave_idx_type idx2 = ridx(i); - work[idx2] = work[idx2] - tmp * data(i); + Complex tmp = work[k] / data(cidx(iidx+1)-1); + work[k] = tmp; + for (octave_idx_type i = cidx(iidx); + i < cidx(iidx+1)-1; i++) + { + octave_idx_type idx2 = ridx(i); + work[idx2] = work[idx2] - tmp * data(i); + } } } + double atmp = 0; + for (octave_idx_type i = 0; i < j+1; i++) + { + atmp += std::abs(work[i]); + work[i] = 0.; + } + if (atmp > ainvnorm) + ainvnorm = atmp; } - double atmp = 0; - for (octave_idx_type i = 0; i < j+1; i++) - { - atmp += std::abs(work[i]); - work[i] = 0.; - } - if (atmp > ainvnorm) - ainvnorm = atmp; + rcond = 1. / ainvnorm / anorm; } } else @@ -1513,7 +1556,8 @@ { if (work[k] != 0.) { - if (ridx(cidx(k+1)-1) != k) + if (ridx(cidx(k+1)-1) != k || + data(cidx(k+1)-1) == 0.) { err = -2; goto triangular_error; @@ -1533,45 +1577,51 @@ retval.xelem (i, j) = work[i]; } - // Calculation of 1-norm of inv(*this) - for (octave_idx_type i = 0; i < nm; i++) - work[i] = 0.; - - for (octave_idx_type j = 0; j < nr; j++) - { - work[j] = 1.; - - for (octave_idx_type k = j; k >= 0; k--) + if (calc_cond) + { + // Calculation of 1-norm of inv(*this) + for (octave_idx_type i = 0; i < nm; i++) + work[i] = 0.; + + for (octave_idx_type j = 0; j < nr; j++) { - if (work[k] != 0.) + work[j] = 1.; + + for (octave_idx_type k = j; k >= 0; k--) { - Complex tmp = work[k] / data(cidx(k+1)-1); - work[k] = tmp; - for (octave_idx_type i = cidx(k); i < cidx(k+1)-1; i++) + if (work[k] != 0.) { - octave_idx_type iidx = ridx(i); - work[iidx] = work[iidx] - tmp * data(i); + Complex tmp = work[k] / data(cidx(k+1)-1); + work[k] = tmp; + for (octave_idx_type i = cidx(k); + i < cidx(k+1)-1; i++) + { + octave_idx_type iidx = ridx(i); + work[iidx] = work[iidx] - tmp * data(i); + } } } - } - double atmp = 0; - for (octave_idx_type i = 0; i < j+1; i++) - { - atmp += std::abs(work[i]); - work[i] = 0.; + double atmp = 0; + for (octave_idx_type i = 0; i < j+1; i++) + { + atmp += std::abs(work[i]); + work[i] = 0.; + } + if (atmp > ainvnorm) + ainvnorm = atmp; } - if (atmp > ainvnorm) - ainvnorm = atmp; - } - } - - rcond = 1. / ainvnorm / anorm; + rcond = 1. / ainvnorm / anorm; + } + } triangular_error: if (err != 0) { if (sing_handler) - sing_handler (rcond); + { + sing_handler (rcond); + mattype.mark_as_rectangular (); + } else (*current_liboctave_error_handler) ("SparseComplexMatrix::solve matrix singular to machine precision, rcond = %g", @@ -1585,7 +1635,10 @@ err = -2; if (sing_handler) - sing_handler (rcond); + { + sing_handler (rcond); + mattype.mark_as_rectangular (); + } else (*current_liboctave_error_handler) ("matrix singular to machine precision, rcond = %g", @@ -1602,7 +1655,8 @@ SparseComplexMatrix SparseComplexMatrix::utsolve (SparseType &mattype, const SparseMatrix& b, octave_idx_type& err, double& rcond, - solve_singularity_handler sing_handler) const + solve_singularity_handler sing_handler, + bool calc_cond) const { SparseComplexMatrix retval; @@ -1625,20 +1679,23 @@ { double anorm = 0.; double ainvnorm = 0.; - rcond = 0.; - - // Calculate the 1-norm of matrix for rcond calculation - for (octave_idx_type j = 0; j < nc; j++) - { - double atmp = 0.; - for (octave_idx_type i = cidx(j); i < cidx(j+1); i++) - atmp += std::abs(data(i)); - if (atmp > anorm) - anorm = atmp; + rcond = 1.; + + if (calc_cond) + { + // Calculate the 1-norm of matrix for rcond calculation + for (octave_idx_type j = 0; j < nc; j++) + { + double atmp = 0.; + for (octave_idx_type i = cidx(j); i < cidx(j+1); i++) + atmp += std::abs(data(i)); + if (atmp > anorm) + anorm = atmp; + } } octave_idx_type b_nc = b.cols (); - octave_idx_type b_nz = b.nzmax (); + octave_idx_type b_nz = b.nnz (); retval = SparseComplexMatrix (nc, b_nc, b_nz); retval.xcidx(0) = 0; octave_idx_type ii = 0; @@ -1666,7 +1723,8 @@ if (work[k] != 0.) { - if (ridx(cidx(kidx+1)-1) != k) + if (ridx(cidx(kidx+1)-1) != k || + data(cidx(kidx+1)-1) == 0.) { err = -2; goto triangular_error; @@ -1709,38 +1767,42 @@ retval.maybe_compress (); - // Calculation of 1-norm of inv(*this) - for (octave_idx_type i = 0; i < nm; i++) - work[i] = 0.; - - for (octave_idx_type j = 0; j < nr; j++) - { - work[j] = 1.; - - for (octave_idx_type k = j; k >= 0; k--) + if (calc_cond) + { + // Calculation of 1-norm of inv(*this) + for (octave_idx_type i = 0; i < nm; i++) + work[i] = 0.; + + for (octave_idx_type j = 0; j < nr; j++) { - octave_idx_type iidx = perm[k]; - - if (work[k] != 0.) + work[j] = 1.; + + for (octave_idx_type k = j; k >= 0; k--) { - Complex tmp = work[k] / data(cidx(iidx+1)-1); - work[k] = tmp; - for (octave_idx_type i = cidx(iidx); - i < cidx(iidx+1)-1; i++) + octave_idx_type iidx = perm[k]; + + if (work[k] != 0.) { - octave_idx_type idx2 = ridx(i); - work[idx2] = work[idx2] - tmp * data(i); + Complex tmp = work[k] / data(cidx(iidx+1)-1); + work[k] = tmp; + for (octave_idx_type i = cidx(iidx); + i < cidx(iidx+1)-1; i++) + { + octave_idx_type idx2 = ridx(i); + work[idx2] = work[idx2] - tmp * data(i); + } } } + double atmp = 0; + for (octave_idx_type i = 0; i < j+1; i++) + { + atmp += std::abs(work[i]); + work[i] = 0.; + } + if (atmp > ainvnorm) + ainvnorm = atmp; } - double atmp = 0; - for (octave_idx_type i = 0; i < j+1; i++) - { - atmp += std::abs(work[i]); - work[i] = 0.; - } - if (atmp > ainvnorm) - ainvnorm = atmp; + rcond = 1. / ainvnorm / anorm; } } else @@ -1758,7 +1820,8 @@ { if (work[k] != 0.) { - if (ridx(cidx(k+1)-1) != k) + if (ridx(cidx(k+1)-1) != k || + data(cidx(k+1)-1) == 0.) { err = -2; goto triangular_error; @@ -1800,45 +1863,51 @@ retval.maybe_compress (); - // Calculation of 1-norm of inv(*this) - for (octave_idx_type i = 0; i < nm; i++) - work[i] = 0.; - - for (octave_idx_type j = 0; j < nr; j++) - { - work[j] = 1.; - - for (octave_idx_type k = j; k >= 0; k--) + if (calc_cond) + { + // Calculation of 1-norm of inv(*this) + for (octave_idx_type i = 0; i < nm; i++) + work[i] = 0.; + + for (octave_idx_type j = 0; j < nr; j++) { - if (work[k] != 0.) + work[j] = 1.; + + for (octave_idx_type k = j; k >= 0; k--) { - Complex tmp = work[k] / data(cidx(k+1)-1); - work[k] = tmp; - for (octave_idx_type i = cidx(k); i < cidx(k+1)-1; i++) + if (work[k] != 0.) { - octave_idx_type iidx = ridx(i); - work[iidx] = work[iidx] - tmp * data(i); + Complex tmp = work[k] / data(cidx(k+1)-1); + work[k] = tmp; + for (octave_idx_type i = cidx(k); + i < cidx(k+1)-1; i++) + { + octave_idx_type iidx = ridx(i); + work[iidx] = work[iidx] - tmp * data(i); + } } } - } - double atmp = 0; - for (octave_idx_type i = 0; i < j+1; i++) - { - atmp += std::abs(work[i]); - work[i] = 0.; + double atmp = 0; + for (octave_idx_type i = 0; i < j+1; i++) + { + atmp += std::abs(work[i]); + work[i] = 0.; + } + if (atmp > ainvnorm) + ainvnorm = atmp; } - if (atmp > ainvnorm) - ainvnorm = atmp; - } - } - - rcond = 1. / ainvnorm / anorm; + rcond = 1. / ainvnorm / anorm; + } + } triangular_error: if (err != 0) { if (sing_handler) - sing_handler (rcond); + { + sing_handler (rcond); + mattype.mark_as_rectangular (); + } else (*current_liboctave_error_handler) ("SparseComplexMatrix::solve matrix singular to machine precision, rcond = %g", @@ -1852,7 +1921,10 @@ err = -2; if (sing_handler) - sing_handler (rcond); + { + sing_handler (rcond); + mattype.mark_as_rectangular (); + } else (*current_liboctave_error_handler) ("matrix singular to machine precision, rcond = %g", @@ -1868,7 +1940,8 @@ ComplexMatrix SparseComplexMatrix::utsolve (SparseType &mattype, const ComplexMatrix& b, octave_idx_type& err, double& rcond, - solve_singularity_handler sing_handler) const + solve_singularity_handler sing_handler, + bool calc_cond) const { ComplexMatrix retval; @@ -1892,16 +1965,19 @@ double anorm = 0.; double ainvnorm = 0.; octave_idx_type b_nc = b.cols (); - rcond = 0.; - - // Calculate the 1-norm of matrix for rcond calculation - for (octave_idx_type j = 0; j < nc; j++) - { - double atmp = 0.; - for (octave_idx_type i = cidx(j); i < cidx(j+1); i++) - atmp += std::abs(data(i)); - if (atmp > anorm) - anorm = atmp; + rcond = 1.; + + if (calc_cond) + { + // Calculate the 1-norm of matrix for rcond calculation + for (octave_idx_type j = 0; j < nc; j++) + { + double atmp = 0.; + for (octave_idx_type i = cidx(j); i < cidx(j+1); i++) + atmp += std::abs(data(i)); + if (atmp > anorm) + anorm = atmp; + } } if (typ == SparseType::Permuted_Upper) @@ -1923,7 +1999,8 @@ if (work[k] != 0.) { - if (ridx(cidx(kidx+1)-1) != k) + if (ridx(cidx(kidx+1)-1) != k || + data(cidx(kidx+1)-1) == 0.) { err = -2; goto triangular_error; @@ -1944,38 +2021,42 @@ retval (perm[i], j) = work[i]; } - // Calculation of 1-norm of inv(*this) - for (octave_idx_type i = 0; i < nm; i++) - work[i] = 0.; - - for (octave_idx_type j = 0; j < nr; j++) - { - work[j] = 1.; - - for (octave_idx_type k = j; k >= 0; k--) + if (calc_cond) + { + // Calculation of 1-norm of inv(*this) + for (octave_idx_type i = 0; i < nm; i++) + work[i] = 0.; + + for (octave_idx_type j = 0; j < nr; j++) { - octave_idx_type iidx = perm[k]; - - if (work[k] != 0.) + work[j] = 1.; + + for (octave_idx_type k = j; k >= 0; k--) { - Complex tmp = work[k] / data(cidx(iidx+1)-1); - work[k] = tmp; - for (octave_idx_type i = cidx(iidx); - i < cidx(iidx+1)-1; i++) + octave_idx_type iidx = perm[k]; + + if (work[k] != 0.) { - octave_idx_type idx2 = ridx(i); - work[idx2] = work[idx2] - tmp * data(i); + Complex tmp = work[k] / data(cidx(iidx+1)-1); + work[k] = tmp; + for (octave_idx_type i = cidx(iidx); + i < cidx(iidx+1)-1; i++) + { + octave_idx_type idx2 = ridx(i); + work[idx2] = work[idx2] - tmp * data(i); + } } } + double atmp = 0; + for (octave_idx_type i = 0; i < j+1; i++) + { + atmp += std::abs(work[i]); + work[i] = 0.; + } + if (atmp > ainvnorm) + ainvnorm = atmp; } - double atmp = 0; - for (octave_idx_type i = 0; i < j+1; i++) - { - atmp += std::abs(work[i]); - work[i] = 0.; - } - if (atmp > ainvnorm) - ainvnorm = atmp; + rcond = 1. / ainvnorm / anorm; } } else @@ -1994,7 +2075,8 @@ { if (work[k] != 0.) { - if (ridx(cidx(k+1)-1) != k) + if (ridx(cidx(k+1)-1) != k || + data(cidx(k+1)-1) == 0.) { err = -2; goto triangular_error; @@ -2014,45 +2096,51 @@ retval.xelem (i, j) = work[i]; } - // Calculation of 1-norm of inv(*this) - for (octave_idx_type i = 0; i < nm; i++) - work[i] = 0.; - - for (octave_idx_type j = 0; j < nr; j++) - { - work[j] = 1.; - - for (octave_idx_type k = j; k >= 0; k--) + if (calc_cond) + { + // Calculation of 1-norm of inv(*this) + for (octave_idx_type i = 0; i < nm; i++) + work[i] = 0.; + + for (octave_idx_type j = 0; j < nr; j++) { - if (work[k] != 0.) + work[j] = 1.; + + for (octave_idx_type k = j; k >= 0; k--) { - Complex tmp = work[k] / data(cidx(k+1)-1); - work[k] = tmp; - for (octave_idx_type i = cidx(k); i < cidx(k+1)-1; i++) + if (work[k] != 0.) { - octave_idx_type iidx = ridx(i); - work[iidx] = work[iidx] - tmp * data(i); + Complex tmp = work[k] / data(cidx(k+1)-1); + work[k] = tmp; + for (octave_idx_type i = cidx(k); + i < cidx(k+1)-1; i++) + { + octave_idx_type iidx = ridx(i); + work[iidx] = work[iidx] - tmp * data(i); + } } } - } - double atmp = 0; - for (octave_idx_type i = 0; i < j+1; i++) - { - atmp += std::abs(work[i]); - work[i] = 0.; + double atmp = 0; + for (octave_idx_type i = 0; i < j+1; i++) + { + atmp += std::abs(work[i]); + work[i] = 0.; + } + if (atmp > ainvnorm) + ainvnorm = atmp; } - if (atmp > ainvnorm) - ainvnorm = atmp; - } - } - - rcond = 1. / ainvnorm / anorm; + rcond = 1. / ainvnorm / anorm; + } + } triangular_error: if (err != 0) { if (sing_handler) - sing_handler (rcond); + { + sing_handler (rcond); + mattype.mark_as_rectangular (); + } else (*current_liboctave_error_handler) ("SparseComplexMatrix::solve matrix singular to machine precision, rcond = %g", @@ -2066,7 +2154,10 @@ err = -2; if (sing_handler) - sing_handler (rcond); + { + sing_handler (rcond); + mattype.mark_as_rectangular (); + } else (*current_liboctave_error_handler) ("matrix singular to machine precision, rcond = %g", @@ -2083,7 +2174,8 @@ SparseComplexMatrix SparseComplexMatrix::utsolve (SparseType &mattype, const SparseComplexMatrix& b, octave_idx_type& err, double& rcond, - solve_singularity_handler sing_handler) const + solve_singularity_handler sing_handler, + bool calc_cond) const { SparseComplexMatrix retval; @@ -2106,20 +2198,23 @@ { double anorm = 0.; double ainvnorm = 0.; - rcond = 0.; - - // Calculate the 1-norm of matrix for rcond calculation - for (octave_idx_type j = 0; j < nc; j++) - { - double atmp = 0.; - for (octave_idx_type i = cidx(j); i < cidx(j+1); i++) - atmp += std::abs(data(i)); - if (atmp > anorm) - anorm = atmp; + rcond = 1.; + + if (calc_cond) + { + // Calculate the 1-norm of matrix for rcond calculation + for (octave_idx_type j = 0; j < nc; j++) + { + double atmp = 0.; + for (octave_idx_type i = cidx(j); i < cidx(j+1); i++) + atmp += std::abs(data(i)); + if (atmp > anorm) + anorm = atmp; + } } octave_idx_type b_nc = b.cols (); - octave_idx_type b_nz = b.nzmax (); + octave_idx_type b_nz = b.nnz (); retval = SparseComplexMatrix (nc, b_nc, b_nz); retval.xcidx(0) = 0; octave_idx_type ii = 0; @@ -2147,7 +2242,8 @@ if (work[k] != 0.) { - if (ridx(cidx(kidx+1)-1) != k) + if (ridx(cidx(kidx+1)-1) != k || + data(cidx(kidx+1)-1) == 0.) { err = -2; goto triangular_error; @@ -2190,38 +2286,42 @@ retval.maybe_compress (); - // Calculation of 1-norm of inv(*this) - for (octave_idx_type i = 0; i < nm; i++) - work[i] = 0.; - - for (octave_idx_type j = 0; j < nr; j++) - { - work[j] = 1.; - - for (octave_idx_type k = j; k >= 0; k--) + if (calc_cond) + { + // Calculation of 1-norm of inv(*this) + for (octave_idx_type i = 0; i < nm; i++) + work[i] = 0.; + + for (octave_idx_type j = 0; j < nr; j++) { - octave_idx_type iidx = perm[k]; - - if (work[k] != 0.) + work[j] = 1.; + + for (octave_idx_type k = j; k >= 0; k--) { - Complex tmp = work[k] / data(cidx(iidx+1)-1); - work[k] = tmp; - for (octave_idx_type i = cidx(iidx); - i < cidx(iidx+1)-1; i++) + octave_idx_type iidx = perm[k]; + + if (work[k] != 0.) { - octave_idx_type idx2 = ridx(i); - work[idx2] = work[idx2] - tmp * data(i); + Complex tmp = work[k] / data(cidx(iidx+1)-1); + work[k] = tmp; + for (octave_idx_type i = cidx(iidx); + i < cidx(iidx+1)-1; i++) + { + octave_idx_type idx2 = ridx(i); + work[idx2] = work[idx2] - tmp * data(i); + } } } + double atmp = 0; + for (octave_idx_type i = 0; i < j+1; i++) + { + atmp += std::abs(work[i]); + work[i] = 0.; + } + if (atmp > ainvnorm) + ainvnorm = atmp; } - double atmp = 0; - for (octave_idx_type i = 0; i < j+1; i++) - { - atmp += std::abs(work[i]); - work[i] = 0.; - } - if (atmp > ainvnorm) - ainvnorm = atmp; + rcond = 1. / ainvnorm / anorm; } } else @@ -2239,7 +2339,8 @@ { if (work[k] != 0.) { - if (ridx(cidx(k+1)-1) != k) + if (ridx(cidx(k+1)-1) != k || + data(cidx(k+1)-1) == 0.) { err = -2; goto triangular_error; @@ -2281,45 +2382,51 @@ retval.maybe_compress (); - // Calculation of 1-norm of inv(*this) - for (octave_idx_type i = 0; i < nm; i++) - work[i] = 0.; - - for (octave_idx_type j = 0; j < nr; j++) - { - work[j] = 1.; - - for (octave_idx_type k = j; k >= 0; k--) + if (calc_cond) + { + // Calculation of 1-norm of inv(*this) + for (octave_idx_type i = 0; i < nm; i++) + work[i] = 0.; + + for (octave_idx_type j = 0; j < nr; j++) { - if (work[k] != 0.) + work[j] = 1.; + + for (octave_idx_type k = j; k >= 0; k--) { - Complex tmp = work[k] / data(cidx(k+1)-1); - work[k] = tmp; - for (octave_idx_type i = cidx(k); i < cidx(k+1)-1; i++) + if (work[k] != 0.) { - octave_idx_type iidx = ridx(i); - work[iidx] = work[iidx] - tmp * data(i); + Complex tmp = work[k] / data(cidx(k+1)-1); + work[k] = tmp; + for (octave_idx_type i = cidx(k); + i < cidx(k+1)-1; i++) + { + octave_idx_type iidx = ridx(i); + work[iidx] = work[iidx] - tmp * data(i); + } } } - } - double atmp = 0; - for (octave_idx_type i = 0; i < j+1; i++) - { - atmp += std::abs(work[i]); - work[i] = 0.; + double atmp = 0; + for (octave_idx_type i = 0; i < j+1; i++) + { + atmp += std::abs(work[i]); + work[i] = 0.; + } + if (atmp > ainvnorm) + ainvnorm = atmp; } - if (atmp > ainvnorm) - ainvnorm = atmp; - } - } - - rcond = 1. / ainvnorm / anorm; + rcond = 1. / ainvnorm / anorm; + } + } triangular_error: if (err != 0) { if (sing_handler) - sing_handler (rcond); + { + sing_handler (rcond); + mattype.mark_as_rectangular (); + } else (*current_liboctave_error_handler) ("SparseComplexMatrix::solve matrix singular to machine precision, rcond = %g", @@ -2333,7 +2440,10 @@ err = -2; if (sing_handler) - sing_handler (rcond); + { + sing_handler (rcond); + mattype.mark_as_rectangular (); + } else (*current_liboctave_error_handler) ("matrix singular to machine precision, rcond = %g", @@ -2350,7 +2460,8 @@ ComplexMatrix SparseComplexMatrix::ltsolve (SparseType &mattype, const Matrix& b, octave_idx_type& err, double& rcond, - solve_singularity_handler sing_handler) const + solve_singularity_handler sing_handler, + bool calc_cond) const { ComplexMatrix retval; @@ -2374,16 +2485,19 @@ double anorm = 0.; double ainvnorm = 0.; octave_idx_type b_nc = b.cols (); - rcond = 0.; - - // Calculate the 1-norm of matrix for rcond calculation - for (octave_idx_type j = 0; j < nc; j++) - { - double atmp = 0.; - for (octave_idx_type i = cidx(j); i < cidx(j+1); i++) - atmp += std::abs(data(i)); - if (atmp > anorm) - anorm = atmp; + rcond = 1.; + + if (calc_cond) + { + // Calculate the 1-norm of matrix for rcond calculation + for (octave_idx_type j = 0; j < nc; j++) + { + double atmp = 0.; + for (octave_idx_type i = cidx(j); i < cidx(j+1); i++) + atmp += std::abs(data(i)); + if (atmp > anorm) + anorm = atmp; + } } if (typ == SparseType::Permuted_Lower) @@ -2413,7 +2527,7 @@ mini = i; } - if (minr != k) + if (minr != k || data (mini) == 0.) { err = -2; goto triangular_error; @@ -2436,49 +2550,55 @@ retval (i, j) = work[i]; } - // Calculation of 1-norm of inv(*this) - for (octave_idx_type i = 0; i < nm; i++) - work[i] = 0.; - - for (octave_idx_type j = 0; j < nr; j++) - { - work[j] = 1.; - - for (octave_idx_type k = 0; k < nc; k++) + if (calc_cond) + { + // Calculation of 1-norm of inv(*this) + for (octave_idx_type i = 0; i < nm; i++) + work[i] = 0.; + + for (octave_idx_type j = 0; j < nr; j++) { - if (work[k] != 0.) + work[j] = 1.; + + for (octave_idx_type k = 0; k < nc; k++) { - octave_idx_type minr = nr; - octave_idx_type mini = 0; - - for (octave_idx_type i = cidx(k); i < cidx(k+1); i++) - if (perm[ridx(i)] < minr) - { - minr = perm[ridx(i)]; - mini = i; - } - - Complex tmp = work[k] / data(mini); - work[k] = tmp; - for (octave_idx_type i = cidx(k); i < cidx(k+1); i++) + if (work[k] != 0.) { - if (i == mini) - continue; - - octave_idx_type iidx = perm[ridx(i)]; - work[iidx] = work[iidx] - tmp * data(i); + octave_idx_type minr = nr; + octave_idx_type mini = 0; + + for (octave_idx_type i = cidx(k); + i < cidx(k+1); i++) + if (perm[ridx(i)] < minr) + { + minr = perm[ridx(i)]; + mini = i; + } + + Complex tmp = work[k] / data(mini); + work[k] = tmp; + for (octave_idx_type i = cidx(k); + i < cidx(k+1); i++) + { + if (i == mini) + continue; + + octave_idx_type iidx = perm[ridx(i)]; + work[iidx] = work[iidx] - tmp * data(i); + } } } + + double atmp = 0; + for (octave_idx_type i = j; i < nc; i++) + { + atmp += std::abs(work[i]); + work[i] = 0.; + } + if (atmp > ainvnorm) + ainvnorm = atmp; } - - double atmp = 0; - for (octave_idx_type i = j; i < nc; i++) - { - atmp += std::abs(work[i]); - work[i] = 0.; - } - if (atmp > ainvnorm) - ainvnorm = atmp; + rcond = 1. / ainvnorm / anorm; } } else @@ -2496,7 +2616,8 @@ { if (work[k] != 0.) { - if (ridx(cidx(k)) != k) + if (ridx(cidx(k)) != k || + data(cidx(k)) == 0.) { err = -2; goto triangular_error; @@ -2515,46 +2636,51 @@ retval.xelem (i, j) = work[i]; } - // Calculation of 1-norm of inv(*this) - for (octave_idx_type i = 0; i < nm; i++) - work[i] = 0.; - - for (octave_idx_type j = 0; j < nr; j++) - { - work[j] = 1.; - - for (octave_idx_type k = j; k < nc; k++) + if (calc_cond) + { + // Calculation of 1-norm of inv(*this) + for (octave_idx_type i = 0; i < nm; i++) + work[i] = 0.; + + for (octave_idx_type j = 0; j < nr; j++) { - - if (work[k] != 0.) + work[j] = 1.; + + for (octave_idx_type k = j; k < nc; k++) { - Complex tmp = work[k] / data(cidx(k)); - work[k] = tmp; - for (octave_idx_type i = cidx(k)+1; i < cidx(k+1); i++) + + if (work[k] != 0.) { - octave_idx_type iidx = ridx(i); - work[iidx] = work[iidx] - tmp * data(i); + Complex tmp = work[k] / data(cidx(k)); + work[k] = tmp; + for (octave_idx_type i = cidx(k)+1; + i < cidx(k+1); i++) + { + octave_idx_type iidx = ridx(i); + work[iidx] = work[iidx] - tmp * data(i); + } } } - } - double atmp = 0; - for (octave_idx_type i = j; i < nc; i++) - { - atmp += std::abs(work[i]); - work[i] = 0.; + double atmp = 0; + for (octave_idx_type i = j; i < nc; i++) + { + atmp += std::abs(work[i]); + work[i] = 0.; + } + if (atmp > ainvnorm) + ainvnorm = atmp; } - if (atmp > ainvnorm) - ainvnorm = atmp; - } - } - - rcond = 1. / ainvnorm / anorm; - + rcond = 1. / ainvnorm / anorm; + } + } triangular_error: if (err != 0) { if (sing_handler) - sing_handler (rcond); + { + sing_handler (rcond); + mattype.mark_as_rectangular (); + } else (*current_liboctave_error_handler) ("SparseComplexMatrix::solve matrix singular to machine precision, rcond = %g", @@ -2568,7 +2694,10 @@ err = -2; if (sing_handler) - sing_handler (rcond); + { + sing_handler (rcond); + mattype.mark_as_rectangular (); + } else (*current_liboctave_error_handler) ("matrix singular to machine precision, rcond = %g", @@ -2585,7 +2714,8 @@ SparseComplexMatrix SparseComplexMatrix::ltsolve (SparseType &mattype, const SparseMatrix& b, octave_idx_type& err, double& rcond, - solve_singularity_handler sing_handler) const + solve_singularity_handler sing_handler, + bool calc_cond) const { SparseComplexMatrix retval; @@ -2609,20 +2739,23 @@ { double anorm = 0.; double ainvnorm = 0.; - rcond = 0.; - - // Calculate the 1-norm of matrix for rcond calculation - for (octave_idx_type j = 0; j < nc; j++) - { - double atmp = 0.; - for (octave_idx_type i = cidx(j); i < cidx(j+1); i++) - atmp += std::abs(data(i)); - if (atmp > anorm) - anorm = atmp; + rcond = 1.; + + if (calc_cond) + { + // Calculate the 1-norm of matrix for rcond calculation + for (octave_idx_type j = 0; j < nc; j++) + { + double atmp = 0.; + for (octave_idx_type i = cidx(j); i < cidx(j+1); i++) + atmp += std::abs(data(i)); + if (atmp > anorm) + anorm = atmp; + } } octave_idx_type b_nc = b.cols (); - octave_idx_type b_nz = b.nzmax (); + octave_idx_type b_nz = b.nnz (); retval = SparseComplexMatrix (nc, b_nc, b_nz); retval.xcidx(0) = 0; octave_idx_type ii = 0; @@ -2654,7 +2787,7 @@ mini = i; } - if (minr != k) + if (minr != k || data (mini) == 0.) { err = -2; goto triangular_error; @@ -2699,49 +2832,55 @@ retval.maybe_compress (); - // Calculation of 1-norm of inv(*this) - for (octave_idx_type i = 0; i < nm; i++) - work[i] = 0.; - - for (octave_idx_type j = 0; j < nr; j++) - { - work[j] = 1.; - - for (octave_idx_type k = 0; k < nc; k++) + if (calc_cond) + { + // Calculation of 1-norm of inv(*this) + for (octave_idx_type i = 0; i < nm; i++) + work[i] = 0.; + + for (octave_idx_type j = 0; j < nr; j++) { - if (work[k] != 0.) + work[j] = 1.; + + for (octave_idx_type k = 0; k < nc; k++) { - octave_idx_type minr = nr; - octave_idx_type mini = 0; - - for (octave_idx_type i = cidx(k); i < cidx(k+1); i++) - if (perm[ridx(i)] < minr) - { - minr = perm[ridx(i)]; - mini = i; - } - - Complex tmp = work[k] / data(mini); - work[k] = tmp; - for (octave_idx_type i = cidx(k); i < cidx(k+1); i++) + if (work[k] != 0.) { - if (i == mini) - continue; - - octave_idx_type iidx = perm[ridx(i)]; - work[iidx] = work[iidx] - tmp * data(i); + octave_idx_type minr = nr; + octave_idx_type mini = 0; + + for (octave_idx_type i = cidx(k); + i < cidx(k+1); i++) + if (perm[ridx(i)] < minr) + { + minr = perm[ridx(i)]; + mini = i; + } + + Complex tmp = work[k] / data(mini); + work[k] = tmp; + for (octave_idx_type i = cidx(k); + i < cidx(k+1); i++) + { + if (i == mini) + continue; + + octave_idx_type iidx = perm[ridx(i)]; + work[iidx] = work[iidx] - tmp * data(i); + } } } + + double atmp = 0; + for (octave_idx_type i = j; i < nc; i++) + { + atmp += std::abs(work[i]); + work[i] = 0.; + } + if (atmp > ainvnorm) + ainvnorm = atmp; } - - double atmp = 0; - for (octave_idx_type i = j; i < nc; i++) - { - atmp += std::abs(work[i]); - work[i] = 0.; - } - if (atmp > ainvnorm) - ainvnorm = atmp; + rcond = 1. / ainvnorm / anorm; } } else @@ -2759,7 +2898,8 @@ { if (work[k] != 0.) { - if (ridx(cidx(k)) != k) + if (ridx(cidx(k)) != k || + data(cidx(k)) == 0.) { err = -2; goto triangular_error; @@ -2801,47 +2941,52 @@ retval.maybe_compress (); - // Calculation of 1-norm of inv(*this) - for (octave_idx_type i = 0; i < nm; i++) - work[i] = 0.; - - for (octave_idx_type j = 0; j < nr; j++) - { - work[j] = 1.; - - for (octave_idx_type k = j; k < nc; k++) + if (calc_cond) + { + // Calculation of 1-norm of inv(*this) + for (octave_idx_type i = 0; i < nm; i++) + work[i] = 0.; + + for (octave_idx_type j = 0; j < nr; j++) { - - if (work[k] != 0.) + work[j] = 1.; + + for (octave_idx_type k = j; k < nc; k++) { - Complex tmp = work[k] / data(cidx(k)); - work[k] = tmp; - for (octave_idx_type i = cidx(k)+1; i < cidx(k+1); i++) + + if (work[k] != 0.) { - octave_idx_type iidx = ridx(i); - work[iidx] = work[iidx] - tmp * data(i); + Complex tmp = work[k] / data(cidx(k)); + work[k] = tmp; + for (octave_idx_type i = cidx(k)+1; + i < cidx(k+1); i++) + { + octave_idx_type iidx = ridx(i); + work[iidx] = work[iidx] - tmp * data(i); + } } } - } - double atmp = 0; - for (octave_idx_type i = j; i < nc; i++) - { - atmp += std::abs(work[i]); - work[i] = 0.; + double atmp = 0; + for (octave_idx_type i = j; i < nc; i++) + { + atmp += std::abs(work[i]); + work[i] = 0.; + } + if (atmp > ainvnorm) + ainvnorm = atmp; } - if (atmp > ainvnorm) - ainvnorm = atmp; - } - - } - - rcond = 1. / ainvnorm / anorm; + rcond = 1. / ainvnorm / anorm; + } + } triangular_error: if (err != 0) { if (sing_handler) - sing_handler (rcond); + { + sing_handler (rcond); + mattype.mark_as_rectangular (); + } else (*current_liboctave_error_handler) ("SparseComplexMatrix::solve matrix singular to machine precision, rcond = %g", @@ -2855,7 +3000,10 @@ err = -2; if (sing_handler) - sing_handler (rcond); + { + sing_handler (rcond); + mattype.mark_as_rectangular (); + } else (*current_liboctave_error_handler) ("matrix singular to machine precision, rcond = %g", @@ -2872,7 +3020,8 @@ ComplexMatrix SparseComplexMatrix::ltsolve (SparseType &mattype, const ComplexMatrix& b, octave_idx_type& err, double& rcond, - solve_singularity_handler sing_handler) const + solve_singularity_handler sing_handler, + bool calc_cond) const { ComplexMatrix retval; @@ -2896,16 +3045,19 @@ double anorm = 0.; double ainvnorm = 0.; octave_idx_type b_nc = b.cols (); - rcond = 0.; - - // Calculate the 1-norm of matrix for rcond calculation - for (octave_idx_type j = 0; j < nc; j++) - { - double atmp = 0.; - for (octave_idx_type i = cidx(j); i < cidx(j+1); i++) - atmp += std::abs(data(i)); - if (atmp > anorm) - anorm = atmp; + rcond = 1.; + + if (calc_cond) + { + // Calculate the 1-norm of matrix for rcond calculation + for (octave_idx_type j = 0; j < nc; j++) + { + double atmp = 0.; + for (octave_idx_type i = cidx(j); i < cidx(j+1); i++) + atmp += std::abs(data(i)); + if (atmp > anorm) + anorm = atmp; + } } if (typ == SparseType::Permuted_Lower) @@ -2935,7 +3087,7 @@ mini = i; } - if (minr != k) + if (minr != k || data (mini) == 0.) { err = -2; goto triangular_error; @@ -2958,49 +3110,55 @@ retval (i, j) = work[i]; } - // Calculation of 1-norm of inv(*this) - for (octave_idx_type i = 0; i < nm; i++) - work[i] = 0.; - - for (octave_idx_type j = 0; j < nr; j++) - { - work[j] = 1.; - - for (octave_idx_type k = 0; k < nc; k++) + if (calc_cond) + { + // Calculation of 1-norm of inv(*this) + for (octave_idx_type i = 0; i < nm; i++) + work[i] = 0.; + + for (octave_idx_type j = 0; j < nr; j++) { - if (work[k] != 0.) + work[j] = 1.; + + for (octave_idx_type k = 0; k < nc; k++) { - octave_idx_type minr = nr; - octave_idx_type mini = 0; - - for (octave_idx_type i = cidx(k); i < cidx(k+1); i++) - if (perm[ridx(i)] < minr) - { - minr = perm[ridx(i)]; - mini = i; - } - - Complex tmp = work[k] / data(mini); - work[k] = tmp; - for (octave_idx_type i = cidx(k); i < cidx(k+1); i++) + if (work[k] != 0.) { - if (i == mini) - continue; - - octave_idx_type iidx = perm[ridx(i)]; - work[iidx] = work[iidx] - tmp * data(i); + octave_idx_type minr = nr; + octave_idx_type mini = 0; + + for (octave_idx_type i = cidx(k); + i < cidx(k+1); i++) + if (perm[ridx(i)] < minr) + { + minr = perm[ridx(i)]; + mini = i; + } + + Complex tmp = work[k] / data(mini); + work[k] = tmp; + for (octave_idx_type i = cidx(k); + i < cidx(k+1); i++) + { + if (i == mini) + continue; + + octave_idx_type iidx = perm[ridx(i)]; + work[iidx] = work[iidx] - tmp * data(i); + } } } + + double atmp = 0; + for (octave_idx_type i = j; i < nc; i++) + { + atmp += std::abs(work[i]); + work[i] = 0.; + } + if (atmp > ainvnorm) + ainvnorm = atmp; } - - double atmp = 0; - for (octave_idx_type i = j; i < nc; i++) - { - atmp += std::abs(work[i]); - work[i] = 0.; - } - if (atmp > ainvnorm) - ainvnorm = atmp; + rcond = 1. / ainvnorm / anorm; } } else @@ -3020,7 +3178,8 @@ { if (work[k] != 0.) { - if (ridx(cidx(k)) != k) + if (ridx(cidx(k)) != k || + data(cidx(k)) == 0.) { err = -2; goto triangular_error; @@ -3040,47 +3199,52 @@ retval.xelem (i, j) = work[i]; } - // Calculation of 1-norm of inv(*this) - for (octave_idx_type i = 0; i < nm; i++) - work[i] = 0.; - - for (octave_idx_type j = 0; j < nr; j++) - { - work[j] = 1.; - - for (octave_idx_type k = j; k < nc; k++) + if (calc_cond) + { + // Calculation of 1-norm of inv(*this) + for (octave_idx_type i = 0; i < nm; i++) + work[i] = 0.; + + for (octave_idx_type j = 0; j < nr; j++) { - - if (work[k] != 0.) + work[j] = 1.; + + for (octave_idx_type k = j; k < nc; k++) { - Complex tmp = work[k] / data(cidx(k)); - work[k] = tmp; - for (octave_idx_type i = cidx(k)+1; i < cidx(k+1); i++) + + if (work[k] != 0.) { - octave_idx_type iidx = ridx(i); - work[iidx] = work[iidx] - tmp * data(i); + Complex tmp = work[k] / data(cidx(k)); + work[k] = tmp; + for (octave_idx_type i = cidx(k)+1; + i < cidx(k+1); i++) + { + octave_idx_type iidx = ridx(i); + work[iidx] = work[iidx] - tmp * data(i); + } } } - } - double atmp = 0; - for (octave_idx_type i = j; i < nc; i++) - { - atmp += std::abs(work[i]); - work[i] = 0.; + double atmp = 0; + for (octave_idx_type i = j; i < nc; i++) + { + atmp += std::abs(work[i]); + work[i] = 0.; + } + if (atmp > ainvnorm) + ainvnorm = atmp; } - if (atmp > ainvnorm) - ainvnorm = atmp; - } - - } - - rcond = 1. / ainvnorm / anorm; + rcond = 1. / ainvnorm / anorm; + } + } triangular_error: if (err != 0) { if (sing_handler) - sing_handler (rcond); + { + sing_handler (rcond); + mattype.mark_as_rectangular (); + } else (*current_liboctave_error_handler) ("SparseComplexMatrix::solve matrix singular to machine precision, rcond = %g", @@ -3094,7 +3258,10 @@ err = -2; if (sing_handler) - sing_handler (rcond); + { + sing_handler (rcond); + mattype.mark_as_rectangular (); + } else (*current_liboctave_error_handler) ("matrix singular to machine precision, rcond = %g", @@ -3111,7 +3278,8 @@ SparseComplexMatrix SparseComplexMatrix::ltsolve (SparseType &mattype, const SparseComplexMatrix& b, octave_idx_type& err, double& rcond, - solve_singularity_handler sing_handler) const + solve_singularity_handler sing_handler, + bool calc_cond) const { SparseComplexMatrix retval; @@ -3134,20 +3302,23 @@ { double anorm = 0.; double ainvnorm = 0.; - rcond = 0.; - - // Calculate the 1-norm of matrix for rcond calculation - for (octave_idx_type j = 0; j < nc; j++) - { - double atmp = 0.; - for (octave_idx_type i = cidx(j); i < cidx(j+1); i++) - atmp += std::abs(data(i)); - if (atmp > anorm) - anorm = atmp; + rcond = 1.; + + if (calc_cond) + { + // Calculate the 1-norm of matrix for rcond calculation + for (octave_idx_type j = 0; j < nc; j++) + { + double atmp = 0.; + for (octave_idx_type i = cidx(j); i < cidx(j+1); i++) + atmp += std::abs(data(i)); + if (atmp > anorm) + anorm = atmp; + } } octave_idx_type b_nc = b.cols (); - octave_idx_type b_nz = b.nzmax (); + octave_idx_type b_nz = b.nnz (); retval = SparseComplexMatrix (nc, b_nc, b_nz); retval.xcidx(0) = 0; octave_idx_type ii = 0; @@ -3179,7 +3350,7 @@ mini = i; } - if (minr != k) + if (minr != k || data (mini) == 0.) { err = -2; goto triangular_error; @@ -3224,49 +3395,55 @@ retval.maybe_compress (); - // Calculation of 1-norm of inv(*this) - for (octave_idx_type i = 0; i < nm; i++) - work[i] = 0.; - - for (octave_idx_type j = 0; j < nr; j++) - { - work[j] = 1.; - - for (octave_idx_type k = 0; k < nc; k++) + if (calc_cond) + { + // Calculation of 1-norm of inv(*this) + for (octave_idx_type i = 0; i < nm; i++) + work[i] = 0.; + + for (octave_idx_type j = 0; j < nr; j++) { - if (work[k] != 0.) + work[j] = 1.; + + for (octave_idx_type k = 0; k < nc; k++) { - octave_idx_type minr = nr; - octave_idx_type mini = 0; - - for (octave_idx_type i = cidx(k); i < cidx(k+1); i++) - if (perm[ridx(i)] < minr) - { - minr = perm[ridx(i)]; - mini = i; - } - - Complex tmp = work[k] / data(mini); - work[k] = tmp; - for (octave_idx_type i = cidx(k); i < cidx(k+1); i++) + if (work[k] != 0.) { - if (i == mini) - continue; - - octave_idx_type iidx = perm[ridx(i)]; - work[iidx] = work[iidx] - tmp * data(i); + octave_idx_type minr = nr; + octave_idx_type mini = 0; + + for (octave_idx_type i = cidx(k); + i < cidx(k+1); i++) + if (perm[ridx(i)] < minr) + { + minr = perm[ridx(i)]; + mini = i; + } + + Complex tmp = work[k] / data(mini); + work[k] = tmp; + for (octave_idx_type i = cidx(k); + i < cidx(k+1); i++) + { + if (i == mini) + continue; + + octave_idx_type iidx = perm[ridx(i)]; + work[iidx] = work[iidx] - tmp * data(i); + } } } + + double atmp = 0; + for (octave_idx_type i = j; i < nc; i++) + { + atmp += std::abs(work[i]); + work[i] = 0.; + } + if (atmp > ainvnorm) + ainvnorm = atmp; } - - double atmp = 0; - for (octave_idx_type i = j; i < nc; i++) - { - atmp += std::abs(work[i]); - work[i] = 0.; - } - if (atmp > ainvnorm) - ainvnorm = atmp; + rcond = 1. / ainvnorm / anorm; } } else @@ -3284,7 +3461,8 @@ { if (work[k] != 0.) { - if (ridx(cidx(k)) != k) + if (ridx(cidx(k)) != k || + data(cidx(k)) == 0.) { err = -2; goto triangular_error; @@ -3326,47 +3504,52 @@ retval.maybe_compress (); - // Calculation of 1-norm of inv(*this) - for (octave_idx_type i = 0; i < nm; i++) - work[i] = 0.; - - for (octave_idx_type j = 0; j < nr; j++) - { - work[j] = 1.; - - for (octave_idx_type k = j; k < nc; k++) + if (calc_cond) + { + // Calculation of 1-norm of inv(*this) + for (octave_idx_type i = 0; i < nm; i++) + work[i] = 0.; + + for (octave_idx_type j = 0; j < nr; j++) { - - if (work[k] != 0.) + work[j] = 1.; + + for (octave_idx_type k = j; k < nc; k++) { - Complex tmp = work[k] / data(cidx(k)); - work[k] = tmp; - for (octave_idx_type i = cidx(k)+1; i < cidx(k+1); i++) + + if (work[k] != 0.) { - octave_idx_type iidx = ridx(i); - work[iidx] = work[iidx] - tmp * data(i); + Complex tmp = work[k] / data(cidx(k)); + work[k] = tmp; + for (octave_idx_type i = cidx(k)+1; + i < cidx(k+1); i++) + { + octave_idx_type iidx = ridx(i); + work[iidx] = work[iidx] - tmp * data(i); + } } } - } - double atmp = 0; - for (octave_idx_type i = j; i < nc; i++) - { - atmp += std::abs(work[i]); - work[i] = 0.; + double atmp = 0; + for (octave_idx_type i = j; i < nc; i++) + { + atmp += std::abs(work[i]); + work[i] = 0.; + } + if (atmp > ainvnorm) + ainvnorm = atmp; } - if (atmp > ainvnorm) - ainvnorm = atmp; - } - - } - - rcond = 1. / ainvnorm / anorm; + rcond = 1. / ainvnorm / anorm; + } + } triangular_error: if (err != 0) { if (sing_handler) - sing_handler (rcond); + { + sing_handler (rcond); + mattype.mark_as_rectangular (); + } else (*current_liboctave_error_handler) ("SparseComplexMatrix::solve matrix singular to machine precision, rcond = %g", @@ -3380,7 +3563,10 @@ err = -2; if (sing_handler) - sing_handler (rcond); + { + sing_handler (rcond); + mattype.mark_as_rectangular (); + } else (*current_liboctave_error_handler) ("matrix singular to machine precision, rcond = %g", @@ -3395,9 +3581,10 @@ } ComplexMatrix -SparseComplexMatrix::trisolve (SparseType &mattype, const Matrix& b, octave_idx_type& err, - double& rcond, - solve_singularity_handler sing_handler) const +SparseComplexMatrix::trisolve (SparseType &mattype, const Matrix& b, + octave_idx_type& err, double& rcond, + solve_singularity_handler sing_handler, + bool calc_cond) const { ComplexMatrix retval; @@ -3408,6 +3595,9 @@ if (nr == 0 || nc == 0 || nr != nc || nr != b.rows ()) (*current_liboctave_error_handler) ("matrix dimension mismatch solution of linear equations"); + else if (calc_cond) + (*current_liboctave_error_handler) + ("calculation of condition number not implemented"); else { // Print spparms("spumoni") info if requested @@ -3526,7 +3716,10 @@ err = -2; if (sing_handler) - sing_handler (rcond); + { + sing_handler (rcond); + mattype.mark_as_rectangular (); + } else (*current_liboctave_error_handler) ("matrix singular to machine precision"); @@ -3544,8 +3737,9 @@ SparseComplexMatrix SparseComplexMatrix::trisolve (SparseType &mattype, const SparseMatrix& b, - octave_idx_type& err, double& rcond, - solve_singularity_handler sing_handler) const + octave_idx_type& err, double& rcond, + solve_singularity_handler sing_handler, + bool calc_cond) const { SparseComplexMatrix retval; @@ -3556,6 +3750,9 @@ if (nr == 0 || nc == 0 || nr != nc || nr != b.rows ()) (*current_liboctave_error_handler) ("matrix dimension mismatch solution of linear equations"); + else if (calc_cond) + (*current_liboctave_error_handler) + ("calculation of condition number not implemented"); else { // Print spparms("spumoni") info if requested @@ -3614,13 +3811,16 @@ ("unrecoverable error in zgttrf"); else { - rcond = 0.0; if (err != 0) { err = -2; + rcond = 0.0; if (sing_handler) - sing_handler (rcond); + { + sing_handler (rcond); + mattype.mark_as_rectangular (); + } else (*current_liboctave_error_handler) ("matrix singular to machine precision"); @@ -3629,11 +3829,12 @@ else { char job = 'N'; - volatile octave_idx_type x_nz = b.nzmax (); + volatile octave_idx_type x_nz = b.nnz (); octave_idx_type b_nc = b.cols (); retval = SparseComplexMatrix (nr, b_nc, x_nz); retval.xcidx(0) = 0; volatile octave_idx_type ii = 0; + rcond = 1.0; OCTAVE_LOCAL_BUFFER (Complex, work, nr); @@ -3695,7 +3896,8 @@ ComplexMatrix SparseComplexMatrix::trisolve (SparseType &mattype, const ComplexMatrix& b, octave_idx_type& err, double& rcond, - solve_singularity_handler sing_handler) const + solve_singularity_handler sing_handler, + bool calc_cond) const { ComplexMatrix retval; @@ -3706,6 +3908,9 @@ if (nr == 0 || nc == 0 || nr != nc || nr != b.rows ()) (*current_liboctave_error_handler) ("matrix dimension mismatch solution of linear equations"); + else if (calc_cond) + (*current_liboctave_error_handler) + ("calculation of condition number not implemented"); else { // Print spparms("spumoni") info if requested @@ -3834,7 +4039,10 @@ err = -2; if (sing_handler) - sing_handler (rcond); + { + sing_handler (rcond); + mattype.mark_as_rectangular (); + } else (*current_liboctave_error_handler) ("matrix singular to machine precision"); @@ -3849,8 +4057,10 @@ SparseComplexMatrix SparseComplexMatrix::trisolve (SparseType &mattype, - const SparseComplexMatrix& b, octave_idx_type& err, double& rcond, - solve_singularity_handler sing_handler) const + const SparseComplexMatrix& b, + octave_idx_type& err, double& rcond, + solve_singularity_handler sing_handler, + bool calc_cond) const { SparseComplexMatrix retval; @@ -3861,6 +4071,9 @@ if (nr == 0 || nc == 0 || nr != nc || nr != b.rows ()) (*current_liboctave_error_handler) ("matrix dimension mismatch solution of linear equations"); + else if (calc_cond) + (*current_liboctave_error_handler) + ("calculation of condition number not implemented"); else { // Print spparms("spumoni") info if requested @@ -3919,13 +4132,16 @@ ("unrecoverable error in zgttrf"); else { - rcond = 0.0; if (err != 0) { + rcond = 0.0; err = -2; if (sing_handler) - sing_handler (rcond); + { + sing_handler (rcond); + mattype.mark_as_rectangular (); + } else (*current_liboctave_error_handler) ("matrix singular to machine precision"); @@ -3940,7 +4156,7 @@ // Take a first guess that the number of non-zero terms // will be as many as in b - volatile octave_idx_type x_nz = b.nzmax (); + volatile octave_idx_type x_nz = b.nnz (); volatile octave_idx_type ii = 0; retval = SparseComplexMatrix (b_nr, b_nc, x_nz); @@ -4010,9 +4226,10 @@ } ComplexMatrix -SparseComplexMatrix::bsolve (SparseType &mattype, const Matrix& b, octave_idx_type& err, - double& rcond, - solve_singularity_handler sing_handler) const +SparseComplexMatrix::bsolve (SparseType &mattype, const Matrix& b, + octave_idx_type& err, double& rcond, + solve_singularity_handler sing_handler, + bool calc_cond) const { ComplexMatrix retval; @@ -4054,7 +4271,9 @@ } // Calculate the norm of the matrix, for later use. - // double anorm = m_band.abs().sum().row(0).max(); + double anorm; + if (calc_cond) + anorm = m_band.abs().sum().row(0).max(); char job = 'L'; F77_XFCN (zpbtrf, ZPBTRF, (F77_CONST_CHAR_ARG2 (&job, 1), @@ -4066,9 +4285,9 @@ ("unrecoverable error in zpbtrf"); else { - rcond = 0.0; if (err != 0) { + rcond = 0.0; // Matrix is not positive definite!! Fall through to // unsymmetric banded solver. mattype.mark_as_unsymmetric (); @@ -4077,68 +4296,69 @@ } else { - // Unfortunately, the time to calculate the condition - // number is dominant for narrow banded matrices and - // so we rely on the "err" flag from xPBTRF to flag - // singularity. The commented code below is left here - // for reference - - //Array<double> z (3 * nr); - //Complex *pz = z.fortran_vec (); - //Array<octave_idx_type> iz (nr); - //octave_idx_type *piz = iz.fortran_vec (); - // - //F77_XFCN (zpbcon, ZGBCON, - // (F77_CONST_CHAR_ARG2 (&job, 1), - // nr, n_lower, tmp_data, ldm, - // anorm, rcond, pz, piz, err - // F77_CHAR_ARG_LEN (1))); - // - // - //if (f77_exception_encountered) - // (*current_liboctave_error_handler) - // ("unrecoverable error in zpbcon"); - // - //if (err != 0) - // err = -2; - // - //volatile double rcond_plus_one = rcond + 1.0; - // - //if (rcond_plus_one == 1.0 || xisnan (rcond)) - // { - // err = -2; - // - // if (sing_handler) - // sing_handler (rcond); - // else - // (*current_liboctave_error_handler) - // ("matrix singular to machine precision, rcond = %g", - // rcond); - // } - //else - // REST OF CODE, EXCEPT rcond=1 - - rcond = 1.; - retval = ComplexMatrix (b); - Complex *result = retval.fortran_vec (); - - octave_idx_type b_nc = b.cols (); - - F77_XFCN (zpbtrs, ZPBTRS, - (F77_CONST_CHAR_ARG2 (&job, 1), - nr, n_lower, b_nc, tmp_data, - ldm, result, b.rows(), err - F77_CHAR_ARG_LEN (1))); + if (calc_cond) + { + Array<Complex> z (2 * nr); + Complex *pz = z.fortran_vec (); + Array<double> iz (nr); + double *piz = iz.fortran_vec (); + + F77_XFCN (zpbcon, ZPBCON, + (F77_CONST_CHAR_ARG2 (&job, 1), + nr, n_lower, tmp_data, ldm, + anorm, rcond, pz, piz, err + F77_CHAR_ARG_LEN (1))); + + if (f77_exception_encountered) + (*current_liboctave_error_handler) + ("unrecoverable error in zpbcon"); + + if (err != 0) + err = -2; + + volatile double rcond_plus_one = rcond + 1.0; + + if (rcond_plus_one == 1.0 || xisnan (rcond)) + { + err = -2; + + if (sing_handler) + { + sing_handler (rcond); + mattype.mark_as_rectangular (); + } + else + (*current_liboctave_error_handler) + ("matrix singular to machine precision, rcond = %g", + rcond); + } + } + else + rcond = 1.0; + + if (err == 0) + { + retval = ComplexMatrix (b); + Complex *result = retval.fortran_vec (); + + octave_idx_type b_nc = b.cols (); + + F77_XFCN (zpbtrs, ZPBTRS, + (F77_CONST_CHAR_ARG2 (&job, 1), + nr, n_lower, b_nc, tmp_data, + ldm, result, b.rows(), err + F77_CHAR_ARG_LEN (1))); - if (f77_exception_encountered) - (*current_liboctave_error_handler) - ("unrecoverable error in zpbtrs"); - - if (err != 0) - { - (*current_liboctave_error_handler) - ("SparseMatrix::solve solve failed"); - err = -1; + if (f77_exception_encountered) + (*current_liboctave_error_handler) + ("unrecoverable error in zpbtrs"); + + if (err != 0) + { + (*current_liboctave_error_handler) + ("SparseMatrix::solve solve failed"); + err = -1; + } } } } @@ -4167,6 +4387,20 @@ for (octave_idx_type i = cidx(j); i < cidx(j+1); i++) m_band(ridx(i) - j + n_lower + n_upper, j) = data(i); + // Calculate the norm of the matrix, for later use. + double anorm; + if (calc_cond) + { + for (octave_idx_type j = 0; j < nr; j++) + { + double atmp = 0.; + for (octave_idx_type i = cidx(j); i < cidx(j+1); i++) + atmp += std::abs(data(i)); + if (atmp > anorm) + anorm = atmp; + } + } + Array<octave_idx_type> ipvt (nr); octave_idx_type *pipvt = ipvt.fortran_vec (); @@ -4180,73 +4414,81 @@ { // Throw-away extra info LAPACK gives so as to not // change output. - rcond = 0.0; if (err != 0) { + rcond = 0.0; err = -2; if (sing_handler) - sing_handler (rcond); + { + sing_handler (rcond); + mattype.mark_as_rectangular (); + } else (*current_liboctave_error_handler) ("matrix singular to machine precision"); - } else { - char job = '1'; - - // Unfortunately, the time to calculate the condition - // number is dominant for narrow banded matrices and - // so we rely on the "err" flag from xPBTRF to flag - // singularity. The commented code below is left here - // for reference - - //F77_XFCN (zgbcon, ZGBCON, - // (F77_CONST_CHAR_ARG2 (&job, 1), - // nc, n_lower, n_upper, tmp_data, ldm, pipvt, - // anorm, rcond, pz, piz, err - // F77_CHAR_ARG_LEN (1))); - // - //if (f77_exception_encountered) - // (*current_liboctave_error_handler) - // ("unrecoverable error in zgbcon"); - // - // if (err != 0) - // err = -2; - // - //volatile double rcond_plus_one = rcond + 1.0; - // - //if (rcond_plus_one == 1.0 || xisnan (rcond)) - // { - // err = -2; - // - // if (sing_handler) - // sing_handler (rcond); - // else - // (*current_liboctave_error_handler) - // ("matrix singular to machine precision, rcond = %g", - // rcond); - // } - //else - // REST OF CODE, EXCEPT rcond=1 - - rcond = 1.; - retval = ComplexMatrix (b); - Complex *result = retval.fortran_vec (); - - octave_idx_type b_nc = b.cols (); - - job = 'N'; - F77_XFCN (zgbtrs, ZGBTRS, - (F77_CONST_CHAR_ARG2 (&job, 1), - nr, n_lower, n_upper, b_nc, tmp_data, - ldm, pipvt, result, b.rows(), err - F77_CHAR_ARG_LEN (1))); + if (calc_cond) + { + char job = '1'; + Array<Complex> z (2 * nr); + Complex *pz = z.fortran_vec (); + Array<double> iz (nr); + double *piz = iz.fortran_vec (); + + F77_XFCN (zgbcon, ZGBCON, + (F77_CONST_CHAR_ARG2 (&job, 1), + nc, n_lower, n_upper, tmp_data, ldm, pipvt, + anorm, rcond, pz, piz, err + F77_CHAR_ARG_LEN (1))); + + if (f77_exception_encountered) + (*current_liboctave_error_handler) + ("unrecoverable error in zgbcon"); + + if (err != 0) + err = -2; + + volatile double rcond_plus_one = rcond + 1.0; + + if (rcond_plus_one == 1.0 || xisnan (rcond)) + { + err = -2; + + if (sing_handler) + { + sing_handler (rcond); + mattype.mark_as_rectangular (); + } + else + (*current_liboctave_error_handler) + ("matrix singular to machine precision, rcond = %g", + rcond); + } + } + else + rcond = 1.; + + if (err == 0) + { + retval = ComplexMatrix (b); + Complex *result = retval.fortran_vec (); + + octave_idx_type b_nc = b.cols (); + + char job = 'N'; + F77_XFCN (zgbtrs, ZGBTRS, + (F77_CONST_CHAR_ARG2 (&job, 1), + nr, n_lower, n_upper, b_nc, tmp_data, + ldm, pipvt, result, b.rows(), err + F77_CHAR_ARG_LEN (1))); - if (f77_exception_encountered) - (*current_liboctave_error_handler) - ("unrecoverable error in zgbtrs"); + if (f77_exception_encountered) + (*current_liboctave_error_handler) + ("unrecoverable error in zgbtrs"); + } } } } @@ -4260,7 +4502,8 @@ SparseComplexMatrix SparseComplexMatrix::bsolve (SparseType &mattype, const SparseMatrix& b, octave_idx_type& err, double& rcond, - solve_singularity_handler sing_handler) const + solve_singularity_handler sing_handler, + bool calc_cond) const { SparseComplexMatrix retval; @@ -4302,6 +4545,11 @@ m_band(ri - j, j) = data(i); } + // Calculate the norm of the matrix, for later use. + double anorm; + if (calc_cond) + anorm = m_band.abs().sum().row(0).max(); + char job = 'L'; F77_XFCN (zpbtrf, ZPBTRF, (F77_CONST_CHAR_ARG2 (&job, 1), nr, n_lower, tmp_data, ldm, err @@ -4312,75 +4560,118 @@ ("unrecoverable error in zpbtrf"); else { - rcond = 0.0; if (err != 0) { + rcond = 0.0; mattype.mark_as_unsymmetric (); typ = SparseType::Banded; err = 0; } else { - rcond = 1.; - octave_idx_type b_nr = b.rows (); - octave_idx_type b_nc = b.cols (); - OCTAVE_LOCAL_BUFFER (Complex, Bx, b_nr); - - // Take a first guess that the number of non-zero terms - // will be as many as in b - volatile octave_idx_type x_nz = b.nzmax (); - volatile octave_idx_type ii = 0; - retval = SparseComplexMatrix (b_nr, b_nc, x_nz); - - retval.xcidx(0) = 0; - for (volatile octave_idx_type j = 0; j < b_nc; j++) + if (calc_cond) + { + Array<Complex> z (2 * nr); + Complex *pz = z.fortran_vec (); + Array<double> iz (nr); + double *piz = iz.fortran_vec (); + + F77_XFCN (zpbcon, ZPBCON, + (F77_CONST_CHAR_ARG2 (&job, 1), + nr, n_lower, tmp_data, ldm, + anorm, rcond, pz, piz, err + F77_CHAR_ARG_LEN (1))); + + if (f77_exception_encountered) + (*current_liboctave_error_handler) + ("unrecoverable error in zpbcon"); + + if (err != 0) + err = -2; + + volatile double rcond_plus_one = rcond + 1.0; + + if (rcond_plus_one == 1.0 || xisnan (rcond)) + { + err = -2; + + if (sing_handler) + { + sing_handler (rcond); + mattype.mark_as_rectangular (); + } + else + (*current_liboctave_error_handler) + ("matrix singular to machine precision, rcond = %g", + rcond); + } + } + else + rcond = 1.0; + + if (err == 0) { - for (octave_idx_type i = 0; i < b_nr; i++) - Bx[i] = b.elem (i, j); - - F77_XFCN (zpbtrs, ZPBTRS, - (F77_CONST_CHAR_ARG2 (&job, 1), - nr, n_lower, 1, tmp_data, - ldm, Bx, b_nr, err - F77_CHAR_ARG_LEN (1))); + octave_idx_type b_nr = b.rows (); + octave_idx_type b_nc = b.cols (); + OCTAVE_LOCAL_BUFFER (Complex, Bx, b_nr); + + // Take a first guess that the number of non-zero terms + // will be as many as in b + volatile octave_idx_type x_nz = b.nnz (); + volatile octave_idx_type ii = 0; + retval = SparseComplexMatrix (b_nr, b_nc, x_nz); + + retval.xcidx(0) = 0; + for (volatile octave_idx_type j = 0; j < b_nc; j++) + { + for (octave_idx_type i = 0; i < b_nr; i++) + Bx[i] = b.elem (i, j); + + F77_XFCN (zpbtrs, ZPBTRS, + (F77_CONST_CHAR_ARG2 (&job, 1), + nr, n_lower, 1, tmp_data, + ldm, Bx, b_nr, err + F77_CHAR_ARG_LEN (1))); - if (f77_exception_encountered) - { - (*current_liboctave_error_handler) - ("unrecoverable error in dpbtrs"); - err = -1; - break; + if (f77_exception_encountered) + { + (*current_liboctave_error_handler) + ("unrecoverable error in dpbtrs"); + err = -1; + break; + } + + if (err != 0) + { + (*current_liboctave_error_handler) + ("SparseComplexMatrix::solve solve failed"); + err = -1; + break; + } + + for (octave_idx_type i = 0; i < b_nr; i++) + { + Complex tmp = Bx[i]; + if (tmp != 0.0) + { + if (ii == x_nz) + { + // Resize the sparse matrix + octave_idx_type sz = x_nz * + (b_nc - j) / b_nc; + sz = (sz > 10 ? sz : 10) + x_nz; + retval.change_capacity (sz); + x_nz = sz; + } + retval.xdata(ii) = tmp; + retval.xridx(ii++) = i; + } + } + retval.xcidx(j+1) = ii; } - if (err != 0) - { - (*current_liboctave_error_handler) - ("SparseComplexMatrix::solve solve failed"); - err = -1; - break; - } - - for (octave_idx_type i = 0; i < b_nr; i++) - { - Complex tmp = Bx[i]; - if (tmp != 0.0) - { - if (ii == x_nz) - { - // Resize the sparse matrix - octave_idx_type sz = x_nz * (b_nc - j) / b_nc; - sz = (sz > 10 ? sz : 10) + x_nz; - retval.change_capacity (sz); - x_nz = sz; - } - retval.xdata(ii) = tmp; - retval.xridx(ii++) = i; - } - } - retval.xcidx(j+1) = ii; + retval.maybe_compress (); } - - retval.maybe_compress (); } } } @@ -4408,6 +4699,20 @@ for (octave_idx_type i = cidx(j); i < cidx(j+1); i++) m_band(ridx(i) - j + n_lower + n_upper, j) = data(i); + // Calculate the norm of the matrix, for later use. + double anorm; + if (calc_cond) + { + for (octave_idx_type j = 0; j < nr; j++) + { + double atmp = 0.; + for (octave_idx_type i = cidx(j); i < cidx(j+1); i++) + atmp += std::abs(data(i)); + if (atmp > anorm) + anorm = atmp; + } + } + Array<octave_idx_type> ipvt (nr); octave_idx_type *pipvt = ipvt.fortran_vec (); @@ -4419,13 +4724,16 @@ ("unrecoverable error in zgbtrf"); else { - rcond = 0.0; if (err != 0) { + rcond = 0.0; err = -2; if (sing_handler) + { sing_handler (rcond); + mattype.mark_as_rectangular (); + } else (*current_liboctave_error_handler) ("matrix singular to machine precision"); @@ -4433,60 +4741,105 @@ } else { - char job = 'N'; - volatile octave_idx_type x_nz = b.nzmax (); - octave_idx_type b_nc = b.cols (); - retval = SparseComplexMatrix (nr, b_nc, x_nz); - retval.xcidx(0) = 0; - volatile octave_idx_type ii = 0; - - OCTAVE_LOCAL_BUFFER (Complex, work, nr); - - for (volatile octave_idx_type j = 0; j < b_nc; j++) + if (calc_cond) { - for (octave_idx_type i = 0; i < nr; i++) - work[i] = 0.; - for (octave_idx_type i = b.cidx(j); i < b.cidx(j+1); i++) - work[b.ridx(i)] = b.data(i); - - F77_XFCN (zgbtrs, ZGBTRS, - (F77_CONST_CHAR_ARG2 (&job, 1), - nr, n_lower, n_upper, 1, tmp_data, - ldm, pipvt, work, b.rows (), err - F77_CHAR_ARG_LEN (1))); - + char job = '1'; + Array<Complex> z (2 * nr); + Complex *pz = z.fortran_vec (); + Array<double> iz (nr); + double *piz = iz.fortran_vec (); + + F77_XFCN (zgbcon, ZGBCON, + (F77_CONST_CHAR_ARG2 (&job, 1), + nc, n_lower, n_upper, tmp_data, ldm, pipvt, + anorm, rcond, pz, piz, err + F77_CHAR_ARG_LEN (1))); + if (f77_exception_encountered) + (*current_liboctave_error_handler) + ("unrecoverable error in zgbcon"); + + if (err != 0) + err = -2; + + volatile double rcond_plus_one = rcond + 1.0; + + if (rcond_plus_one == 1.0 || xisnan (rcond)) + { + err = -2; + + if (sing_handler) + { + sing_handler (rcond); + mattype.mark_as_rectangular (); + } + else + (*current_liboctave_error_handler) + ("matrix singular to machine precision, rcond = %g", + rcond); + } + } + else + rcond = 1.; + + if (err == 0) + { + char job = 'N'; + volatile octave_idx_type x_nz = b.nnz (); + octave_idx_type b_nc = b.cols (); + retval = SparseComplexMatrix (nr, b_nc, x_nz); + retval.xcidx(0) = 0; + volatile octave_idx_type ii = 0; + + OCTAVE_LOCAL_BUFFER (Complex, work, nr); + + for (volatile octave_idx_type j = 0; j < b_nc; j++) { - (*current_liboctave_error_handler) - ("unrecoverable error in zgbtrs"); - break; + for (octave_idx_type i = 0; i < nr; i++) + work[i] = 0.; + for (octave_idx_type i = b.cidx(j); + i < b.cidx(j+1); i++) + work[b.ridx(i)] = b.data(i); + + F77_XFCN (zgbtrs, ZGBTRS, + (F77_CONST_CHAR_ARG2 (&job, 1), + nr, n_lower, n_upper, 1, tmp_data, + ldm, pipvt, work, b.rows (), err + F77_CHAR_ARG_LEN (1))); + + if (f77_exception_encountered) + { + (*current_liboctave_error_handler) + ("unrecoverable error in zgbtrs"); + break; + } + + // Count non-zeros in work vector and adjust + // space in retval if needed + octave_idx_type new_nnz = 0; + for (octave_idx_type i = 0; i < nr; i++) + if (work[i] != 0.) + new_nnz++; + + if (ii + new_nnz > x_nz) + { + // Resize the sparse matrix + octave_idx_type sz = new_nnz * (b_nc - j) + x_nz; + retval.change_capacity (sz); + x_nz = sz; + } + + for (octave_idx_type i = 0; i < nr; i++) + if (work[i] != 0.) + { + retval.xridx(ii) = i; + retval.xdata(ii++) = work[i]; + } + retval.xcidx(j+1) = ii; } - // Count non-zeros in work vector and adjust - // space in retval if needed - octave_idx_type new_nnz = 0; - for (octave_idx_type i = 0; i < nr; i++) - if (work[i] != 0.) - new_nnz++; - - if (ii + new_nnz > x_nz) - { - // Resize the sparse matrix - octave_idx_type sz = new_nnz * (b_nc - j) + x_nz; - retval.change_capacity (sz); - x_nz = sz; - } - - for (octave_idx_type i = 0; i < nr; i++) - if (work[i] != 0.) - { - retval.xridx(ii) = i; - retval.xdata(ii++) = work[i]; - } - retval.xcidx(j+1) = ii; + retval.maybe_compress (); } - - retval.maybe_compress (); } } } @@ -4500,7 +4853,8 @@ ComplexMatrix SparseComplexMatrix::bsolve (SparseType &mattype, const ComplexMatrix& b, octave_idx_type& err, double& rcond, - solve_singularity_handler sing_handler) const + solve_singularity_handler sing_handler, + bool calc_cond) const { ComplexMatrix retval; @@ -4542,6 +4896,11 @@ m_band(ri - j, j) = data(i); } + // Calculate the norm of the matrix, for later use. + double anorm; + if (calc_cond) + anorm = m_band.abs().sum().row(0).max(); + char job = 'L'; F77_XFCN (zpbtrf, ZPBTRF, (F77_CONST_CHAR_ARG2 (&job, 1), nr, n_lower, tmp_data, ldm, err @@ -4552,41 +4911,83 @@ ("unrecoverable error in zpbtrf"); else { - rcond = 0.0; if (err != 0) { // Matrix is not positive definite!! Fall through to // unsymmetric banded solver. + rcond = 0.0; mattype.mark_as_unsymmetric (); typ = SparseType::Banded; err = 0; } else { - rcond = 1.; - octave_idx_type b_nr = b.rows (); - octave_idx_type b_nc = b.cols (); - retval = ComplexMatrix (b); - Complex *result = retval.fortran_vec (); - - F77_XFCN (zpbtrs, ZPBTRS, - (F77_CONST_CHAR_ARG2 (&job, 1), - nr, n_lower, b_nc, tmp_data, - ldm, result, b_nr, err - F77_CHAR_ARG_LEN (1))); + if (calc_cond) + { + Array<Complex> z (2 * nr); + Complex *pz = z.fortran_vec (); + Array<double> iz (nr); + double *piz = iz.fortran_vec (); + + F77_XFCN (zpbcon, ZPBCON, + (F77_CONST_CHAR_ARG2 (&job, 1), + nr, n_lower, tmp_data, ldm, + anorm, rcond, pz, piz, err + F77_CHAR_ARG_LEN (1))); + + if (f77_exception_encountered) + (*current_liboctave_error_handler) + ("unrecoverable error in zpbcon"); + + if (err != 0) + err = -2; + + volatile double rcond_plus_one = rcond + 1.0; + + if (rcond_plus_one == 1.0 || xisnan (rcond)) + { + err = -2; + + if (sing_handler) + { + sing_handler (rcond); + mattype.mark_as_rectangular (); + } + else + (*current_liboctave_error_handler) + ("matrix singular to machine precision, rcond = %g", + rcond); + } + } + else + rcond = 1.0; + + if (err == 0) + { + octave_idx_type b_nr = b.rows (); + octave_idx_type b_nc = b.cols (); + retval = ComplexMatrix (b); + Complex *result = retval.fortran_vec (); + + F77_XFCN (zpbtrs, ZPBTRS, + (F77_CONST_CHAR_ARG2 (&job, 1), + nr, n_lower, b_nc, tmp_data, + ldm, result, b_nr, err + F77_CHAR_ARG_LEN (1))); - if (f77_exception_encountered) - { - (*current_liboctave_error_handler) - ("unrecoverable error in zpbtrs"); - err = -1; - } - - if (err != 0) - { - (*current_liboctave_error_handler) - ("SparseComplexMatrix::solve solve failed"); - err = -1; + if (f77_exception_encountered) + { + (*current_liboctave_error_handler) + ("unrecoverable error in zpbtrs"); + err = -1; + } + + if (err != 0) + { + (*current_liboctave_error_handler) + ("SparseComplexMatrix::solve solve failed"); + err = -1; + } } } } @@ -4615,6 +5016,20 @@ for (octave_idx_type i = cidx(j); i < cidx(j+1); i++) m_band(ridx(i) - j + n_lower + n_upper, j) = data(i); + // Calculate the norm of the matrix, for later use. + double anorm; + if (calc_cond) + { + for (octave_idx_type j = 0; j < nr; j++) + { + double atmp = 0.; + for (octave_idx_type i = cidx(j); i < cidx(j+1); i++) + atmp += std::abs(data(i)); + if (atmp > anorm) + anorm = atmp; + } + } + Array<octave_idx_type> ipvt (nr); octave_idx_type *pipvt = ipvt.fortran_vec (); @@ -4626,35 +5041,81 @@ ("unrecoverable error in zgbtrf"); else { - rcond = 0.0; if (err != 0) { err = -2; + rcond = 0.0; if (sing_handler) - sing_handler (rcond); + { + sing_handler (rcond); + mattype.mark_as_rectangular (); + } else (*current_liboctave_error_handler) ("matrix singular to machine precision"); - } else { - char job = 'N'; - octave_idx_type b_nc = b.cols (); - retval = ComplexMatrix (b); - Complex *result = retval.fortran_vec (); - - F77_XFCN (zgbtrs, ZGBTRS, - (F77_CONST_CHAR_ARG2 (&job, 1), - nr, n_lower, n_upper, b_nc, tmp_data, - ldm, pipvt, result, b.rows (), err - F77_CHAR_ARG_LEN (1))); + if (calc_cond) + { + char job = '1'; + Array<Complex> z (2 * nr); + Complex *pz = z.fortran_vec (); + Array<double> iz (nr); + double *piz = iz.fortran_vec (); + + F77_XFCN (zgbcon, ZGBCON, + (F77_CONST_CHAR_ARG2 (&job, 1), + nc, n_lower, n_upper, tmp_data, ldm, pipvt, + anorm, rcond, pz, piz, err + F77_CHAR_ARG_LEN (1))); + + if (f77_exception_encountered) + (*current_liboctave_error_handler) + ("unrecoverable error in zgbcon"); + + if (err != 0) + err = -2; + + volatile double rcond_plus_one = rcond + 1.0; + + if (rcond_plus_one == 1.0 || xisnan (rcond)) + { + err = -2; + + if (sing_handler) + { + sing_handler (rcond); + mattype.mark_as_rectangular (); + } + else + (*current_liboctave_error_handler) + ("matrix singular to machine precision, rcond = %g", + rcond); + } + } + else + rcond = 1.; + + if (err == 0) + { + char job = 'N'; + octave_idx_type b_nc = b.cols (); + retval = ComplexMatrix (b); + Complex *result = retval.fortran_vec (); + + F77_XFCN (zgbtrs, ZGBTRS, + (F77_CONST_CHAR_ARG2 (&job, 1), + nr, n_lower, n_upper, b_nc, tmp_data, + ldm, pipvt, result, b.rows (), err + F77_CHAR_ARG_LEN (1))); - if (f77_exception_encountered) - { - (*current_liboctave_error_handler) - ("unrecoverable error in dgbtrs"); + if (f77_exception_encountered) + { + (*current_liboctave_error_handler) + ("unrecoverable error in dgbtrs"); + } } } } @@ -4668,8 +5129,9 @@ SparseComplexMatrix SparseComplexMatrix::bsolve (SparseType &mattype, const SparseComplexMatrix& b, - octave_idx_type& err, double& rcond, - solve_singularity_handler sing_handler) const + octave_idx_type& err, double& rcond, + solve_singularity_handler sing_handler, + bool calc_cond) const { SparseComplexMatrix retval; @@ -4711,6 +5173,11 @@ m_band(ri - j, j) = data(i); } + // Calculate the norm of the matrix, for later use. + double anorm; + if (calc_cond) + anorm = m_band.abs().sum().row(0).max(); + char job = 'L'; F77_XFCN (zpbtrf, ZPBTRF, (F77_CONST_CHAR_ARG2 (&job, 1), nr, n_lower, tmp_data, ldm, err @@ -4721,7 +5188,6 @@ ("unrecoverable error in zpbtrf"); else { - rcond = 0.0; if (err != 0) { // Matrix is not positive definite!! Fall through to @@ -4729,77 +5195,119 @@ mattype.mark_as_unsymmetric (); typ = SparseType::Banded; + rcond = 0.0; err = 0; } else { - rcond = 1.; - octave_idx_type b_nr = b.rows (); - octave_idx_type b_nc = b.cols (); - OCTAVE_LOCAL_BUFFER (Complex, Bx, b_nr); - - // Take a first guess that the number of non-zero terms - // will be as many as in b - volatile octave_idx_type x_nz = b.nzmax (); - volatile octave_idx_type ii = 0; - retval = SparseComplexMatrix (b_nr, b_nc, x_nz); - - retval.xcidx(0) = 0; - for (volatile octave_idx_type j = 0; j < b_nc; j++) + if (calc_cond) { - - for (octave_idx_type i = 0; i < b_nr; i++) - Bx[i] = b (i,j); - - F77_XFCN (zpbtrs, ZPBTRS, - (F77_CONST_CHAR_ARG2 (&job, 1), - nr, n_lower, 1, tmp_data, - ldm, Bx, b_nr, err - F77_CHAR_ARG_LEN (1))); - + Array<Complex> z (2 * nr); + Complex *pz = z.fortran_vec (); + Array<double> iz (nr); + double *piz = iz.fortran_vec (); + + F77_XFCN (zpbcon, ZPBCON, + (F77_CONST_CHAR_ARG2 (&job, 1), + nr, n_lower, tmp_data, ldm, + anorm, rcond, pz, piz, err + F77_CHAR_ARG_LEN (1))); + if (f77_exception_encountered) - { - (*current_liboctave_error_handler) - ("unrecoverable error in zpbtrs"); - err = -1; - break; - } - - if (err != 0) + (*current_liboctave_error_handler) + ("unrecoverable error in zpbcon"); + + if (err != 0) + err = -2; + + volatile double rcond_plus_one = rcond + 1.0; + + if (rcond_plus_one == 1.0 || xisnan (rcond)) + { + err = -2; + + if (sing_handler) + { + sing_handler (rcond); + mattype.mark_as_rectangular (); + } + else + (*current_liboctave_error_handler) + ("matrix singular to machine precision, rcond = %g", + rcond); + } + } + else + rcond = 1.0; + + if (err == 0) + { + octave_idx_type b_nr = b.rows (); + octave_idx_type b_nc = b.cols (); + OCTAVE_LOCAL_BUFFER (Complex, Bx, b_nr); + + // Take a first guess that the number of non-zero terms + // will be as many as in b + volatile octave_idx_type x_nz = b.nnz (); + volatile octave_idx_type ii = 0; + retval = SparseComplexMatrix (b_nr, b_nc, x_nz); + + retval.xcidx(0) = 0; + for (volatile octave_idx_type j = 0; j < b_nc; j++) { - (*current_liboctave_error_handler) - ("SparseMatrix::solve solve failed"); - err = -1; - break; - } - - - // Count non-zeros in work vector and adjust - // space in retval if needed - octave_idx_type new_nnz = 0; - for (octave_idx_type i = 0; i < nr; i++) - if (Bx[i] != 0.) - new_nnz++; + + for (octave_idx_type i = 0; i < b_nr; i++) + Bx[i] = b (i,j); + + F77_XFCN (zpbtrs, ZPBTRS, + (F77_CONST_CHAR_ARG2 (&job, 1), + nr, n_lower, 1, tmp_data, + ldm, Bx, b_nr, err + F77_CHAR_ARG_LEN (1))); + + if (f77_exception_encountered) + { + (*current_liboctave_error_handler) + ("unrecoverable error in zpbtrs"); + err = -1; + break; + } + + if (err != 0) + { + (*current_liboctave_error_handler) + ("SparseMatrix::solve solve failed"); + err = -1; + break; + } + + // Count non-zeros in work vector and adjust + // space in retval if needed + octave_idx_type new_nnz = 0; + for (octave_idx_type i = 0; i < nr; i++) + if (Bx[i] != 0.) + new_nnz++; - if (ii + new_nnz > x_nz) - { - // Resize the sparse matrix - octave_idx_type sz = new_nnz * (b_nc - j) + x_nz; - retval.change_capacity (sz); - x_nz = sz; - } + if (ii + new_nnz > x_nz) + { + // Resize the sparse matrix + octave_idx_type sz = new_nnz * (b_nc - j) + x_nz; + retval.change_capacity (sz); + x_nz = sz; + } - for (octave_idx_type i = 0; i < nr; i++) - if (Bx[i] != 0.) - { - retval.xridx(ii) = i; - retval.xdata(ii++) = Bx[i]; - } - - retval.xcidx(j+1) = ii; + for (octave_idx_type i = 0; i < nr; i++) + if (Bx[i] != 0.) + { + retval.xridx(ii) = i; + retval.xdata(ii++) = Bx[i]; + } + + retval.xcidx(j+1) = ii; + } + + retval.maybe_compress (); } - - retval.maybe_compress (); } } } @@ -4827,6 +5335,20 @@ for (octave_idx_type i = cidx(j); i < cidx(j+1); i++) m_band(ridx(i) - j + n_lower + n_upper, j) = data(i); + // Calculate the norm of the matrix, for later use. + double anorm; + if (calc_cond) + { + for (octave_idx_type j = 0; j < nr; j++) + { + double atmp = 0.; + for (octave_idx_type i = cidx(j); i < cidx(j+1); i++) + atmp += std::abs(data(i)); + if (atmp > anorm) + anorm = atmp; + } + } + Array<octave_idx_type> ipvt (nr); octave_idx_type *pipvt = ipvt.fortran_vec (); @@ -4838,13 +5360,16 @@ ("unrecoverable error in xgbtrf"); else { - rcond = 0.0; if (err != 0) { err = -2; + rcond = 0.0; if (sing_handler) - sing_handler (rcond); + { + sing_handler (rcond); + mattype.mark_as_rectangular (); + } else (*current_liboctave_error_handler) ("matrix singular to machine precision"); @@ -4852,61 +5377,106 @@ } else { - char job = 'N'; - volatile octave_idx_type x_nz = b.nzmax (); - octave_idx_type b_nc = b.cols (); - retval = SparseComplexMatrix (nr, b_nc, x_nz); - retval.xcidx(0) = 0; - volatile octave_idx_type ii = 0; - - OCTAVE_LOCAL_BUFFER (Complex, Bx, nr); - - for (volatile octave_idx_type j = 0; j < b_nc; j++) + if (calc_cond) { - for (octave_idx_type i = 0; i < nr; i++) - Bx[i] = 0.; - - for (octave_idx_type i = b.cidx(j); i < b.cidx(j+1); i++) - Bx[b.ridx(i)] = b.data(i); - - F77_XFCN (zgbtrs, ZGBTRS, - (F77_CONST_CHAR_ARG2 (&job, 1), - nr, n_lower, n_upper, 1, tmp_data, - ldm, pipvt, Bx, b.rows (), err - F77_CHAR_ARG_LEN (1))); - + char job = '1'; + Array<Complex> z (2 * nr); + Complex *pz = z.fortran_vec (); + Array<double> iz (nr); + double *piz = iz.fortran_vec (); + + F77_XFCN (zgbcon, ZGBCON, + (F77_CONST_CHAR_ARG2 (&job, 1), + nc, n_lower, n_upper, tmp_data, ldm, pipvt, + anorm, rcond, pz, piz, err + F77_CHAR_ARG_LEN (1))); + if (f77_exception_encountered) + (*current_liboctave_error_handler) + ("unrecoverable error in zgbcon"); + + if (err != 0) + err = -2; + + volatile double rcond_plus_one = rcond + 1.0; + + if (rcond_plus_one == 1.0 || xisnan (rcond)) + { + err = -2; + + if (sing_handler) + { + sing_handler (rcond); + mattype.mark_as_rectangular (); + } + else + (*current_liboctave_error_handler) + ("matrix singular to machine precision, rcond = %g", + rcond); + } + } + else + rcond = 1.; + + if (err == 0) + { + char job = 'N'; + volatile octave_idx_type x_nz = b.nnz (); + octave_idx_type b_nc = b.cols (); + retval = SparseComplexMatrix (nr, b_nc, x_nz); + retval.xcidx(0) = 0; + volatile octave_idx_type ii = 0; + + OCTAVE_LOCAL_BUFFER (Complex, Bx, nr); + + for (volatile octave_idx_type j = 0; j < b_nc; j++) { - (*current_liboctave_error_handler) - ("unrecoverable error in dgbtrs"); - break; + for (octave_idx_type i = 0; i < nr; i++) + Bx[i] = 0.; + + for (octave_idx_type i = b.cidx(j); + i < b.cidx(j+1); i++) + Bx[b.ridx(i)] = b.data(i); + + F77_XFCN (zgbtrs, ZGBTRS, + (F77_CONST_CHAR_ARG2 (&job, 1), + nr, n_lower, n_upper, 1, tmp_data, + ldm, pipvt, Bx, b.rows (), err + F77_CHAR_ARG_LEN (1))); + + if (f77_exception_encountered) + { + (*current_liboctave_error_handler) + ("unrecoverable error in dgbtrs"); + break; + } + + // Count non-zeros in work vector and adjust + // space in retval if needed + octave_idx_type new_nnz = 0; + for (octave_idx_type i = 0; i < nr; i++) + if (Bx[i] != 0.) + new_nnz++; + + if (ii + new_nnz > x_nz) + { + // Resize the sparse matrix + octave_idx_type sz = new_nnz * (b_nc - j) + x_nz; + retval.change_capacity (sz); + x_nz = sz; + } + + for (octave_idx_type i = 0; i < nr; i++) + if (Bx[i] != 0.) + { + retval.xridx(ii) = i; + retval.xdata(ii++) = Bx[i]; + } + retval.xcidx(j+1) = ii; } - // Count non-zeros in work vector and adjust - // space in retval if needed - octave_idx_type new_nnz = 0; - for (octave_idx_type i = 0; i < nr; i++) - if (Bx[i] != 0.) - new_nnz++; - - if (ii + new_nnz > x_nz) - { - // Resize the sparse matrix - octave_idx_type sz = new_nnz * (b_nc - j) + x_nz; - retval.change_capacity (sz); - x_nz = sz; - } - - for (octave_idx_type i = 0; i < nr; i++) - if (Bx[i] != 0.) - { - retval.xridx(ii) = i; - retval.xdata(ii++) = Bx[i]; - } - retval.xcidx(j+1) = ii; + retval.maybe_compress (); } - - retval.maybe_compress (); } } } @@ -4918,9 +5488,10 @@ } void * -SparseComplexMatrix::factorize (octave_idx_type& err, double &rcond, Matrix &Control, - Matrix &Info, - solve_singularity_handler sing_handler) const +SparseComplexMatrix::factorize (octave_idx_type& err, double &rcond, + Matrix &Control, Matrix &Info, + solve_singularity_handler sing_handler, + bool calc_cond) const { // The return values void *Numeric = 0; @@ -4985,7 +5556,10 @@ Symbolic, &Numeric, control, info) ; UMFPACK_ZNAME (free_symbolic) (&Symbolic) ; - rcond = Info (UMFPACK_RCOND); + if (calc_cond) + rcond = Info (UMFPACK_RCOND); + else + rcond = 1.; volatile double rcond_plus_one = rcond + 1.0; if (status == UMFPACK_WARNING_singular_matrix || @@ -5029,9 +5603,10 @@ } ComplexMatrix -SparseComplexMatrix::fsolve (SparseType &mattype, const Matrix& b, octave_idx_type& err, - double& rcond, - solve_singularity_handler sing_handler) const +SparseComplexMatrix::fsolve (SparseType &mattype, const Matrix& b, + octave_idx_type& err, double& rcond, + solve_singularity_handler sing_handler, + bool calc_cond) const { ComplexMatrix retval; @@ -5139,7 +5714,10 @@ BEGIN_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE; L = CHOLMOD_NAME(analyze) (A, cm); CHOLMOD_NAME(factorize) (A, L, cm); - rcond = CHOLMOD_NAME(rcond)(L, cm); + if (calc_cond) + rcond = CHOLMOD_NAME(rcond)(L, cm); + else + rcond = 1.; END_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE; if (rcond == 0.0) @@ -5157,7 +5735,10 @@ err = -2; if (sing_handler) - sing_handler (rcond); + { + sing_handler (rcond); + mattype.mark_as_rectangular (); + } else (*current_liboctave_error_handler) ("SparseMatrix::solve matrix singular to machine precision, rcond = %g", @@ -5200,7 +5781,7 @@ #ifdef HAVE_UMFPACK Matrix Control, Info; void *Numeric = factorize (err, rcond, Control, Info, - sing_handler); + sing_handler, calc_cond); if (err == 0) { @@ -5264,6 +5845,9 @@ UMFPACK_ZNAME (free_numeric) (&Numeric); } + else + mattype.mark_as_rectangular (); + #else (*current_liboctave_error_handler) ("UMFPACK not installed"); #endif @@ -5278,7 +5862,8 @@ SparseComplexMatrix SparseComplexMatrix::fsolve (SparseType &mattype, const SparseMatrix& b, octave_idx_type& err, double& rcond, - solve_singularity_handler sing_handler) const + solve_singularity_handler sing_handler, + bool calc_cond) const { SparseComplexMatrix retval; @@ -5397,7 +5982,10 @@ BEGIN_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE; L = CHOLMOD_NAME(analyze) (A, cm); CHOLMOD_NAME(factorize) (A, L, cm); - rcond = CHOLMOD_NAME(rcond)(L, cm); + if (calc_cond) + rcond = CHOLMOD_NAME(rcond)(L, cm); + else + rcond = 1.; END_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE; if (rcond == 0.0) @@ -5415,7 +6003,10 @@ err = -2; if (sing_handler) - sing_handler (rcond); + { + sing_handler (rcond); + mattype.mark_as_rectangular (); + } else (*current_liboctave_error_handler) ("SparseMatrix::solve matrix singular to machine precision, rcond = %g", @@ -5463,7 +6054,8 @@ { #ifdef HAVE_UMFPACK Matrix Control, Info; - void *Numeric = factorize (err, rcond, Control, Info, sing_handler); + void *Numeric = factorize (err, rcond, Control, Info, + sing_handler, calc_cond); if (err == 0) { @@ -5487,7 +6079,7 @@ // Take a first guess that the number of non-zero terms // will be as many as in b - octave_idx_type x_nz = b.nzmax (); + octave_idx_type x_nz = b.nnz (); octave_idx_type ii = 0; retval = SparseComplexMatrix (b_nr, b_nc, x_nz); @@ -5557,6 +6149,9 @@ UMFPACK_ZNAME (free_numeric) (&Numeric); } + else + mattype.mark_as_rectangular (); + #else (*current_liboctave_error_handler) ("UMFPACK not installed"); #endif @@ -5571,7 +6166,8 @@ ComplexMatrix SparseComplexMatrix::fsolve (SparseType &mattype, const ComplexMatrix& b, octave_idx_type& err, double& rcond, - solve_singularity_handler sing_handler) const + solve_singularity_handler sing_handler, + bool calc_cond) const { ComplexMatrix retval; @@ -5680,7 +6276,10 @@ BEGIN_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE; L = CHOLMOD_NAME(analyze) (A, cm); CHOLMOD_NAME(factorize) (A, L, cm); - rcond = CHOLMOD_NAME(rcond)(L, cm); + if (calc_cond) + rcond = CHOLMOD_NAME(rcond)(L, cm); + else + rcond = 1.; END_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE; if (rcond == 0.0) @@ -5698,7 +6297,10 @@ err = -2; if (sing_handler) - sing_handler (rcond); + { + sing_handler (rcond); + mattype.mark_as_rectangular (); + } else (*current_liboctave_error_handler) ("SparseMatrix::solve matrix singular to machine precision, rcond = %g", @@ -5740,7 +6342,8 @@ { #ifdef HAVE_UMFPACK Matrix Control, Info; - void *Numeric = factorize (err, rcond, Control, Info, sing_handler); + void *Numeric = factorize (err, rcond, Control, Info, + sing_handler, calc_cond); if (err == 0) { @@ -5783,6 +6386,9 @@ UMFPACK_ZNAME (free_numeric) (&Numeric); } + else + mattype.mark_as_rectangular (); + #else (*current_liboctave_error_handler) ("UMFPACK not installed"); #endif @@ -5797,7 +6403,8 @@ SparseComplexMatrix SparseComplexMatrix::fsolve (SparseType &mattype, const SparseComplexMatrix& b, octave_idx_type& err, double& rcond, - solve_singularity_handler sing_handler) const + solve_singularity_handler sing_handler, + bool calc_cond) const { SparseComplexMatrix retval; @@ -5916,7 +6523,10 @@ BEGIN_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE; L = CHOLMOD_NAME(analyze) (A, cm); CHOLMOD_NAME(factorize) (A, L, cm); - rcond = CHOLMOD_NAME(rcond)(L, cm); + if (calc_cond) + rcond = CHOLMOD_NAME(rcond)(L, cm); + else + rcond = 1.; END_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE; if (rcond == 0.0) @@ -5934,7 +6544,10 @@ err = -2; if (sing_handler) - sing_handler (rcond); + { + sing_handler (rcond); + mattype.mark_as_rectangular (); + } else (*current_liboctave_error_handler) ("SparseMatrix::solve matrix singular to machine precision, rcond = %g", @@ -5982,7 +6595,8 @@ { #ifdef HAVE_UMFPACK Matrix Control, Info; - void *Numeric = factorize (err, rcond, Control, Info, sing_handler); + void *Numeric = factorize (err, rcond, Control, Info, + sing_handler, calc_cond); if (err == 0) { @@ -5999,7 +6613,7 @@ // Take a first guess that the number of non-zero terms // will be as many as in b - octave_idx_type x_nz = b.nzmax (); + octave_idx_type x_nz = b.nnz (); octave_idx_type ii = 0; retval = SparseComplexMatrix (b_nr, b_nc, x_nz); @@ -6072,6 +6686,9 @@ UMFPACK_ZNAME (free_numeric) (&Numeric); } + else + mattype.mark_as_rectangular (); + #else (*current_liboctave_error_handler) ("UMFPACK not installed"); #endif @@ -6111,30 +6728,43 @@ double& rcond, solve_singularity_handler sing_handler) const { + ComplexMatrix retval; int typ = mattype.type (false); if (typ == SparseType::Unknown) typ = mattype.type (*this); if (typ == SparseType::Diagonal || typ == SparseType::Permuted_Diagonal) - return dsolve (mattype, b, err, rcond, sing_handler); + retval = dsolve (mattype, b, err, rcond, sing_handler, false); else if (typ == SparseType::Upper || typ == SparseType::Permuted_Upper) - return utsolve (mattype, b, err, rcond, sing_handler); + retval = utsolve (mattype, b, err, rcond, sing_handler, false); else if (typ == SparseType::Lower || typ == SparseType::Permuted_Lower) - return ltsolve (mattype, b, err, rcond, sing_handler); + retval = ltsolve (mattype, b, err, rcond, sing_handler, false); else if (typ == SparseType::Banded || typ == SparseType::Banded_Hermitian) - return bsolve (mattype, b, err, rcond, sing_handler); + retval = bsolve (mattype, b, err, rcond, sing_handler, false); else if (typ == SparseType::Tridiagonal || typ == SparseType::Tridiagonal_Hermitian) - return trisolve (mattype, b, err, rcond, sing_handler); + retval = trisolve (mattype, b, err, rcond, sing_handler, false); else if (typ == SparseType::Full || typ == SparseType::Hermitian) - return fsolve (mattype, b, err, rcond, sing_handler); - else + retval = fsolve (mattype, b, err, rcond, sing_handler, true); + else if (typ != SparseType::Rectangular) { - (*current_liboctave_error_handler) - ("matrix dimension mismatch solution of linear equations"); + (*current_liboctave_error_handler) ("unknown matrix type"); return ComplexMatrix (); } + + if (mattype.type(false) == SparseType::Rectangular) + { + rcond = 1.; +#ifdef USE_QRSOLVE + retval = qrsolve (*this, b, err); +#else + retval = dmsolve<ComplexMatrix, SparseComplexMatrix, + Matrix> (*this, b, err); +#endif + } + + return retval; } SparseComplexMatrix @@ -6165,30 +6795,43 @@ octave_idx_type& err, double& rcond, solve_singularity_handler sing_handler) const { + SparseComplexMatrix retval; int typ = mattype.type (false); if (typ == SparseType::Unknown) typ = mattype.type (*this); if (typ == SparseType::Diagonal || typ == SparseType::Permuted_Diagonal) - return dsolve (mattype, b, err, rcond, sing_handler); + retval = dsolve (mattype, b, err, rcond, sing_handler, false); else if (typ == SparseType::Upper || typ == SparseType::Permuted_Upper) - return utsolve (mattype, b, err, rcond, sing_handler); + retval = utsolve (mattype, b, err, rcond, sing_handler, false); else if (typ == SparseType::Lower || typ == SparseType::Permuted_Lower) - return ltsolve (mattype, b, err, rcond, sing_handler); + retval = ltsolve (mattype, b, err, rcond, sing_handler, false); else if (typ == SparseType::Banded || typ == SparseType::Banded_Hermitian) - return bsolve (mattype, b, err, rcond, sing_handler); + retval = bsolve (mattype, b, err, rcond, sing_handler, false); else if (typ == SparseType::Tridiagonal || typ == SparseType::Tridiagonal_Hermitian) - return trisolve (mattype, b, err, rcond, sing_handler); + retval = trisolve (mattype, b, err, rcond, sing_handler, false); else if (typ == SparseType::Full || typ == SparseType::Hermitian) - return fsolve (mattype, b, err, rcond, sing_handler); - else + retval = fsolve (mattype, b, err, rcond, sing_handler, true); + else if (typ != SparseType::Rectangular) { - (*current_liboctave_error_handler) - ("matrix dimension mismatch solution of linear equations"); + (*current_liboctave_error_handler) ("unknown matrix type"); return SparseComplexMatrix (); } + + if (mattype.type(false) == SparseType::Rectangular) + { + rcond = 1.; +#ifdef USE_QRSOLVE + retval = qrsolve (*this, b, err); +#else + retval = dmsolve<SparseComplexMatrix, SparseComplexMatrix, + SparseMatrix> (*this, b, err); +#endif + } + + return retval; } ComplexMatrix @@ -6219,30 +6862,43 @@ octave_idx_type& err, double& rcond, solve_singularity_handler sing_handler) const { + ComplexMatrix retval; int typ = mattype.type (false); if (typ == SparseType::Unknown) typ = mattype.type (*this); if (typ == SparseType::Diagonal || typ == SparseType::Permuted_Diagonal) - return dsolve (mattype, b, err, rcond, sing_handler); + retval = dsolve (mattype, b, err, rcond, sing_handler, false); else if (typ == SparseType::Upper || typ == SparseType::Permuted_Upper) - return utsolve (mattype, b, err, rcond, sing_handler); + retval = utsolve (mattype, b, err, rcond, sing_handler, false); else if (typ == SparseType::Lower || typ == SparseType::Permuted_Lower) - return ltsolve (mattype, b, err, rcond, sing_handler); + retval = ltsolve (mattype, b, err, rcond, sing_handler, false); else if (typ == SparseType::Banded || typ == SparseType::Banded_Hermitian) - return bsolve (mattype, b, err, rcond, sing_handler); + retval = bsolve (mattype, b, err, rcond, sing_handler, false); else if (typ == SparseType::Tridiagonal || typ == SparseType::Tridiagonal_Hermitian) - return trisolve (mattype, b, err, rcond, sing_handler); + retval = trisolve (mattype, b, err, rcond, sing_handler, false); else if (typ == SparseType::Full || typ == SparseType::Hermitian) - return fsolve (mattype, b, err, rcond, sing_handler); - else + retval = fsolve (mattype, b, err, rcond, sing_handler, true); + else if (typ != SparseType::Rectangular) { - (*current_liboctave_error_handler) - ("matrix dimension mismatch solution of linear equations"); + (*current_liboctave_error_handler) ("unknown matrix type"); return ComplexMatrix (); } + + if (mattype.type(false) == SparseType::Rectangular) + { + rcond = 1.; +#ifdef USE_QRSOLVE + retval = qrsolve (*this, b, err); +#else + retval = dmsolve<ComplexMatrix, SparseComplexMatrix, + ComplexMatrix> (*this, b, err); +#endif + } + + return retval; } SparseComplexMatrix @@ -6274,30 +6930,43 @@ octave_idx_type& err, double& rcond, solve_singularity_handler sing_handler) const { + SparseComplexMatrix retval; int typ = mattype.type (false); if (typ == SparseType::Unknown) typ = mattype.type (*this); if (typ == SparseType::Diagonal || typ == SparseType::Permuted_Diagonal) - return dsolve (mattype, b, err, rcond, sing_handler); + retval = dsolve (mattype, b, err, rcond, sing_handler, false); else if (typ == SparseType::Upper || typ == SparseType::Permuted_Upper) - return utsolve (mattype, b, err, rcond, sing_handler); + retval = utsolve (mattype, b, err, rcond, sing_handler, false); else if (typ == SparseType::Lower || typ == SparseType::Permuted_Lower) - return ltsolve (mattype, b, err, rcond, sing_handler); + retval = ltsolve (mattype, b, err, rcond, sing_handler, false); else if (typ == SparseType::Banded || typ == SparseType::Banded_Hermitian) - return bsolve (mattype, b, err, rcond, sing_handler); + retval = bsolve (mattype, b, err, rcond, sing_handler, false); else if (typ == SparseType::Tridiagonal || typ == SparseType::Tridiagonal_Hermitian) - return trisolve (mattype, b, err, rcond, sing_handler); + retval = trisolve (mattype, b, err, rcond, sing_handler, false); else if (typ == SparseType::Full || typ == SparseType::Hermitian) - return fsolve (mattype, b, err, rcond, sing_handler); - else + retval = fsolve (mattype, b, err, rcond, sing_handler, true); + else if (typ != SparseType::Rectangular) { - (*current_liboctave_error_handler) - ("matrix dimension mismatch solution of linear equations"); + (*current_liboctave_error_handler) ("unknown matrix type"); return SparseComplexMatrix (); } + + if (mattype.type(false) == SparseType::Rectangular) + { + rcond = 1.; +#ifdef USE_QRSOLVE + retval = qrsolve (*this, b, err); +#else + retval = dmsolve<SparseComplexMatrix, SparseComplexMatrix, + SparseComplexMatrix> (*this, b, err); +#endif + } + + return retval; } ComplexColumnVector @@ -6543,145 +7212,13 @@ return solve (tmp, info, rcond, sing_handler).column (static_cast<octave_idx_type> (0)); } -ComplexMatrix -SparseComplexMatrix::lssolve (const Matrix& b) const -{ - octave_idx_type info; - octave_idx_type rank; - return lssolve (b, info, rank); -} - -ComplexMatrix -SparseComplexMatrix::lssolve (const Matrix& b, octave_idx_type& info) const -{ - octave_idx_type rank; - return lssolve (b, info, rank); -} - -ComplexMatrix -SparseComplexMatrix::lssolve (const Matrix& b, octave_idx_type& info, octave_idx_type&) const -{ - return qrsolve (*this, b, info); -} - -SparseComplexMatrix -SparseComplexMatrix::lssolve (const SparseMatrix& b) const -{ - octave_idx_type info; - octave_idx_type rank; - return lssolve (b, info, rank); -} - -SparseComplexMatrix -SparseComplexMatrix::lssolve (const SparseMatrix& b, octave_idx_type& info) const -{ - octave_idx_type rank; - return lssolve (b, info, rank); -} - -SparseComplexMatrix -SparseComplexMatrix::lssolve (const SparseMatrix& b, octave_idx_type& info, - octave_idx_type&) const -{ - return qrsolve (*this, b, info); -} - -ComplexMatrix -SparseComplexMatrix::lssolve (const ComplexMatrix& b) const -{ - octave_idx_type info; - octave_idx_type rank; - return lssolve (b, info, rank); -} - -ComplexMatrix -SparseComplexMatrix::lssolve (const ComplexMatrix& b, octave_idx_type& info) const -{ - octave_idx_type rank; - return lssolve (b, info, rank); -} - -ComplexMatrix -SparseComplexMatrix::lssolve (const ComplexMatrix& b, octave_idx_type& info, - octave_idx_type&) const -{ - return qrsolve (*this, b, info); -} - -SparseComplexMatrix -SparseComplexMatrix::lssolve (const SparseComplexMatrix& b) const -{ - octave_idx_type info; - octave_idx_type rank; - return lssolve (b, info, rank); -} - -SparseComplexMatrix -SparseComplexMatrix::lssolve (const SparseComplexMatrix& b, octave_idx_type& info) const -{ - octave_idx_type rank; - return lssolve (b, info, rank); -} - -SparseComplexMatrix -SparseComplexMatrix::lssolve (const SparseComplexMatrix& b, octave_idx_type& info, - octave_idx_type&) const -{ - return qrsolve (*this, b, info); -} - -ComplexColumnVector -SparseComplexMatrix::lssolve (const ColumnVector& b) const -{ - octave_idx_type info; - octave_idx_type rank; - return lssolve (b, info, rank); -} - -ComplexColumnVector -SparseComplexMatrix::lssolve (const ColumnVector& b, octave_idx_type& info) const -{ - octave_idx_type rank; - return lssolve (b, info, rank); -} - -ComplexColumnVector -SparseComplexMatrix::lssolve (const ColumnVector& b, octave_idx_type& info, octave_idx_type& rank) const -{ - Matrix tmp (b); - return lssolve (tmp, info, rank).column (static_cast<octave_idx_type> (0)); -} - -ComplexColumnVector -SparseComplexMatrix::lssolve (const ComplexColumnVector& b) const -{ - octave_idx_type info; - octave_idx_type rank; - return lssolve (b, info, rank); -} - -ComplexColumnVector -SparseComplexMatrix::lssolve (const ComplexColumnVector& b, octave_idx_type& info) const -{ - octave_idx_type rank; - return lssolve (b, info, rank); -} - -ComplexColumnVector -SparseComplexMatrix::lssolve (const ComplexColumnVector& b, octave_idx_type& info, - octave_idx_type& rank) const -{ - ComplexMatrix tmp (b); - return lssolve (tmp, info, rank).column (static_cast<octave_idx_type> (0)); -} - // unary operations SparseBoolMatrix SparseComplexMatrix::operator ! (void) const { octave_idx_type nr = rows (); octave_idx_type nc = cols (); - octave_idx_type nz1 = nzmax (); + octave_idx_type nz1 = nnz (); octave_idx_type nz2 = nr*nc - nz1; SparseBoolMatrix r (nr, nc, nz2); @@ -6755,7 +7292,7 @@ { octave_idx_type nr = rows (); octave_idx_type nc = cols (); - octave_idx_type nz = nzmax (); + octave_idx_type nz = nnz (); bool f_zero = (f(0.0) == 0.0); // Count number of non-zero elements @@ -6805,7 +7342,7 @@ { octave_idx_type nr = rows (); octave_idx_type nc = cols (); - octave_idx_type nz = nzmax (); + octave_idx_type nz = nnz (); bool f_zero = (f(0.0) == 0.0); // Count number of non-zero elements @@ -6855,7 +7392,7 @@ { octave_idx_type nr = rows (); octave_idx_type nc = cols (); - octave_idx_type nz = nzmax (); + octave_idx_type nz = nnz (); bool f_zero = f(0.0); // Count number of non-zero elements @@ -6910,7 +7447,7 @@ bool SparseComplexMatrix::any_element_is_inf_or_nan (void) const { - octave_idx_type nel = nzmax (); + octave_idx_type nel = nnz (); for (octave_idx_type i = 0; i < nel; i++) { @@ -6927,7 +7464,7 @@ bool SparseComplexMatrix::all_elements_are_real (void) const { - octave_idx_type nel = nzmax (); + octave_idx_type nel = nnz (); for (octave_idx_type i = 0; i < nel; i++) { @@ -6947,7 +7484,7 @@ bool SparseComplexMatrix::all_integers (double& max_val, double& min_val) const { - octave_idx_type nel = nzmax (); + octave_idx_type nel = nnz (); if (nel == 0) return false; @@ -6984,7 +7521,7 @@ bool SparseComplexMatrix::too_large_for_float (void) const { - octave_idx_type nel = nzmax (); + octave_idx_type nel = nnz (); for (octave_idx_type i = 0; i < nel; i++) { @@ -7062,7 +7599,7 @@ SparseMatrix SparseComplexMatrix::abs (void) const { - octave_idx_type nz = nzmax (); + octave_idx_type nz = nnz (); octave_idx_type nc = cols (); SparseMatrix retval (rows(), nc, nz); @@ -7237,74 +7774,55 @@ SparseComplexMatrix operator * (const SparseComplexMatrix& m, const SparseMatrix& a) { - SparseComplexMatrix tmp (a); - return m * tmp; + SPARSE_SPARSE_MUL (SparseComplexMatrix, Complex, double); } SparseComplexMatrix operator * (const SparseMatrix& m, const SparseComplexMatrix& a) { - SparseComplexMatrix tmp (m); - return tmp * a; + SPARSE_SPARSE_MUL (SparseComplexMatrix, Complex, Complex); } SparseComplexMatrix operator * (const SparseComplexMatrix& m, const SparseComplexMatrix& a) { -#ifdef HAVE_SPARSE_BLAS - // XXX FIXME XXX Isn't there a sparse BLAS ?? -#else - // Use Andy's sparse matrix multiply function - SPARSE_SPARSE_MUL (SparseComplexMatrix, Complex); -#endif + SPARSE_SPARSE_MUL (SparseComplexMatrix, Complex, Complex); } ComplexMatrix operator * (const ComplexMatrix& m, const SparseMatrix& a) { - SparseComplexMatrix tmp (a); - return m * tmp; + FULL_SPARSE_MUL (ComplexMatrix, double, Complex (0.,0.)); } ComplexMatrix operator * (const Matrix& m, const SparseComplexMatrix& a) { - ComplexMatrix tmp (m); - return tmp * a; + FULL_SPARSE_MUL (ComplexMatrix, Complex, Complex (0.,0.)); } ComplexMatrix operator * (const ComplexMatrix& m, const SparseComplexMatrix& a) { -#ifdef HAVE_SPARSE_BLAS - // XXX FIXME XXX Isn't there a sparse BLAS ?? -#else - FULL_SPARSE_MUL (ComplexMatrix, Complex); -#endif + FULL_SPARSE_MUL (ComplexMatrix, Complex, Complex (0.,0.)); } ComplexMatrix operator * (const SparseComplexMatrix& m, const Matrix& a) { - ComplexMatrix tmp (a); - return m * tmp; + SPARSE_FULL_MUL (ComplexMatrix, double, Complex (0.,0.)); } ComplexMatrix operator * (const SparseMatrix& m, const ComplexMatrix& a) { - SparseComplexMatrix tmp (m); - return tmp * a; + SPARSE_FULL_MUL (ComplexMatrix, Complex, Complex (0.,0.)); } ComplexMatrix operator * (const SparseComplexMatrix& m, const ComplexMatrix& a) { -#ifdef HAVE_SPARSE_BLAS - // XXX FIXME XXX Isn't there a sparse BLAS ?? -#else - SPARSE_FULL_MUL (ComplexMatrix, Complex); -#endif + SPARSE_FULL_MUL (ComplexMatrix, Complex, Complex (0.,0.)); } // XXX FIXME XXX -- it would be nice to share code among the min/max @@ -7357,14 +7875,14 @@ octave_idx_type b_nr = b.rows (); octave_idx_type b_nc = b.cols (); - if (a_nr == 0 || b_nc == 0 || a.nzmax () == 0 || b.nzmax () == 0) + if (a_nr == 0 || b_nc == 0 || a.nnz () == 0 || b.nnz () == 0) return SparseComplexMatrix (a_nr, a_nc); if (a_nr != b_nr || a_nc != b_nc) gripe_nonconformant ("min", a_nr, a_nc, b_nr, b_nc); else { - r = SparseComplexMatrix (a_nr, a_nc, (a.nzmax () + b.nzmax ())); + r = SparseComplexMatrix (a_nr, a_nc, (a.nnz () + b.nnz ())); octave_idx_type jx = 0; r.cidx (0) = 0; @@ -7479,16 +7997,16 @@ if (a_nr == 0 || b_nc == 0) return SparseComplexMatrix (a_nr, a_nc); - if (a.nzmax () == 0) + if (a.nnz () == 0) return SparseComplexMatrix (b); - if (b.nzmax () == 0) + if (b.nnz () == 0) return SparseComplexMatrix (a); if (a_nr != b_nr || a_nc != b_nc) gripe_nonconformant ("min", a_nr, a_nc, b_nr, b_nc); else { - r = SparseComplexMatrix (a_nr, a_nc, (a.nzmax () + b.nzmax ())); + r = SparseComplexMatrix (a_nr, a_nc, (a.nnz () + b.nnz ())); octave_idx_type jx = 0; r.cidx (0) = 0;
--- a/liboctave/CSparse.h +++ b/liboctave/CSparse.h @@ -146,90 +146,129 @@ private: // Diagonal matrix solvers ComplexMatrix dsolve (SparseType &typ, const Matrix& b, octave_idx_type& info, - double& rcond, solve_singularity_handler sing_handler) const; + double& rcond, solve_singularity_handler sing_handler, + bool calc_cond = false) const; - ComplexMatrix dsolve (SparseType &typ, const ComplexMatrix& b, octave_idx_type& info, - double& rcond, solve_singularity_handler sing_handler) const; + ComplexMatrix dsolve (SparseType &typ, const ComplexMatrix& b, + octave_idx_type& info, double& rcond, + solve_singularity_handler sing_handler, + bool calc_cond = false) const; - SparseComplexMatrix dsolve (SparseType &typ, const SparseMatrix& b, octave_idx_type& info, - double& rcond, solve_singularity_handler sing_handler) const; + SparseComplexMatrix dsolve (SparseType &typ, const SparseMatrix& b, + octave_idx_type& info, double& rcond, + solve_singularity_handler sing_handler, + bool calc_cond = false) const; SparseComplexMatrix dsolve (SparseType &typ, const SparseComplexMatrix& b, octave_idx_type& info, double& rcond, - solve_singularity_handler sing_handler) const; + solve_singularity_handler sing_handler, + bool calc_cond = false) const; // Upper triangular matrix solvers ComplexMatrix utsolve (SparseType &typ, const Matrix& b, octave_idx_type& info, - double& rcond, solve_singularity_handler sing_handler) const; + double& rcond, solve_singularity_handler sing_handler, + bool calc_cond = false) const; - ComplexMatrix utsolve (SparseType &typ, const ComplexMatrix& b, octave_idx_type& info, - double& rcond, solve_singularity_handler sing_handler) const; + ComplexMatrix utsolve (SparseType &typ, const ComplexMatrix& b, + octave_idx_type& info, double& rcond, + solve_singularity_handler sing_handler, + bool calc_cond = false) const; - SparseComplexMatrix utsolve (SparseType &typ, const SparseMatrix& b, octave_idx_type& info, - double& rcond, solve_singularity_handler sing_handler) const; + SparseComplexMatrix utsolve (SparseType &typ, const SparseMatrix& b, + octave_idx_type& info, double& rcond, + solve_singularity_handler sing_handler, + bool calc_cond = false) const; SparseComplexMatrix utsolve (SparseType &typ, const SparseComplexMatrix& b, octave_idx_type& info, double& rcond, - solve_singularity_handler sing_handler) const; + solve_singularity_handler sing_handler, + bool calc_cond = false) const; // Lower triangular matrix solvers - ComplexMatrix ltsolve (SparseType &typ, const Matrix& b, octave_idx_type& info, - double& rcond, solve_singularity_handler sing_handler) const; + ComplexMatrix ltsolve (SparseType &typ, const Matrix& b, + octave_idx_type& info, double& rcond, + solve_singularity_handler sing_handler, + bool calc_cond = false) const; - ComplexMatrix ltsolve (SparseType &typ, const ComplexMatrix& b, octave_idx_type& info, - double& rcond, solve_singularity_handler sing_handler) const; + ComplexMatrix ltsolve (SparseType &typ, const ComplexMatrix& b, + octave_idx_type& info, double& rcond, + solve_singularity_handler sing_handler, + bool calc_cond = false) const; - SparseComplexMatrix ltsolve (SparseType &typ, const SparseMatrix& b, octave_idx_type& info, - double& rcond, solve_singularity_handler sing_handler) const; + SparseComplexMatrix ltsolve (SparseType &typ, const SparseMatrix& b, + octave_idx_type& info, double& rcond, + solve_singularity_handler sing_handler, + bool calc_cond = false) const; SparseComplexMatrix ltsolve (SparseType &typ, const SparseComplexMatrix& b, octave_idx_type& info, double& rcond, - solve_singularity_handler sing_handler) const; + solve_singularity_handler sing_handler, + bool calc_cond = false) const; // Tridiagonal matrix solvers - ComplexMatrix trisolve (SparseType &typ, const Matrix& b, octave_idx_type& info, - double& rcond, solve_singularity_handler sing_handler) const; + ComplexMatrix trisolve (SparseType &typ, const Matrix& b, + octave_idx_type& info, double& rcond, + solve_singularity_handler sing_handler, + bool calc_cond = false) const; - ComplexMatrix trisolve (SparseType &typ, const ComplexMatrix& b, octave_idx_type& info, - double& rcond, solve_singularity_handler sing_handler) const; + ComplexMatrix trisolve (SparseType &typ, const ComplexMatrix& b, + octave_idx_type& info, double& rcond, + solve_singularity_handler sing_handler, + bool calc_cond = false) const; - SparseComplexMatrix trisolve (SparseType &typ, const SparseMatrix& b, octave_idx_type& info, - double& rcond, solve_singularity_handler sing_handler) const; + SparseComplexMatrix trisolve (SparseType &typ, const SparseMatrix& b, + octave_idx_type& info, double& rcond, + solve_singularity_handler sing_handler, + bool calc_cond = false) const; SparseComplexMatrix trisolve (SparseType &typ, const SparseComplexMatrix& b, octave_idx_type& info, double& rcond, - solve_singularity_handler sing_handler) const; + solve_singularity_handler sing_handler, + bool calc_cond = false) const; // Banded matrix solvers (umfpack/cholesky) ComplexMatrix bsolve (SparseType &typ, const Matrix& b, octave_idx_type& info, - double& rcond, solve_singularity_handler sing_handler) const; + double& rcond, solve_singularity_handler sing_handler, + bool calc_cond = false) const; - ComplexMatrix bsolve (SparseType &typ, const ComplexMatrix& b, octave_idx_type& info, - double& rcond, solve_singularity_handler sing_handler) const; + ComplexMatrix bsolve (SparseType &typ, const ComplexMatrix& b, + octave_idx_type& info, double& rcond, + solve_singularity_handler sing_handler, + bool calc_cond = false) const; - SparseComplexMatrix bsolve (SparseType &typ, const SparseMatrix& b, octave_idx_type& info, - double& rcond, solve_singularity_handler sing_handler) const; + SparseComplexMatrix bsolve (SparseType &typ, const SparseMatrix& b, + octave_idx_type& info, double& rcond, + solve_singularity_handler sing_handler, + bool calc_cond = false) const; SparseComplexMatrix bsolve (SparseType &typ, const SparseComplexMatrix& b, octave_idx_type& info, double& rcond, - solve_singularity_handler sing_handler) const; + solve_singularity_handler sing_handler, + bool calc_cond = false) const; // Full matrix solvers (umfpack/cholesky) - void * factorize (octave_idx_type& err, double &rcond, Matrix &Control, Matrix &Info, - solve_singularity_handler sing_handler) const; + void * factorize (octave_idx_type& err, double &rcond, Matrix &Control, + Matrix &Info, solve_singularity_handler sing_handler, + bool calc_cond) const; ComplexMatrix fsolve (SparseType &typ, const Matrix& b, octave_idx_type& info, - double& rcond, solve_singularity_handler sing_handler) const; + double& rcond, solve_singularity_handler sing_handler, + bool calc_cond = false) const; - ComplexMatrix fsolve (SparseType &typ, const ComplexMatrix& b, octave_idx_type& info, - double& rcond, solve_singularity_handler sing_handler) const; + ComplexMatrix fsolve (SparseType &typ, const ComplexMatrix& b, + octave_idx_type& info, double& rcond, + solve_singularity_handler sing_handler, + bool calc_cond = false) const; - SparseComplexMatrix fsolve (SparseType &typ, const SparseMatrix& b, octave_idx_type& info, - double& rcond, solve_singularity_handler sing_handler) const; + SparseComplexMatrix fsolve (SparseType &typ, const SparseMatrix& b, + octave_idx_type& info, double& rcond, + solve_singularity_handler sing_handler, + bool calc_cond = false) const; SparseComplexMatrix fsolve (SparseType &typ, const SparseComplexMatrix& b, octave_idx_type& info, double& rcond, - solve_singularity_handler sing_handler) const; + solve_singularity_handler sing_handler, + bool calc_cond = false) const; public: // Generic interface to solver with no probing of type @@ -328,36 +367,6 @@ double& rcond, solve_singularity_handler sing_handler) const; - ComplexMatrix lssolve (const Matrix& b) const; - ComplexMatrix lssolve (const Matrix& b, octave_idx_type& info) const; - ComplexMatrix lssolve (const Matrix& b, octave_idx_type& info, octave_idx_type& rank) const; - - ComplexMatrix lssolve (const ComplexMatrix& b) const; - ComplexMatrix lssolve (const ComplexMatrix& b, octave_idx_type& info) const; - ComplexMatrix lssolve (const ComplexMatrix& b, octave_idx_type& info, - octave_idx_type& rank) const; - - SparseComplexMatrix lssolve (const SparseMatrix& b) const; - SparseComplexMatrix lssolve (const SparseMatrix& b, octave_idx_type& info) const; - SparseComplexMatrix lssolve (const SparseMatrix& b, octave_idx_type& info, - octave_idx_type& rank) const; - - SparseComplexMatrix lssolve (const SparseComplexMatrix& b) const; - SparseComplexMatrix lssolve (const SparseComplexMatrix& b, - octave_idx_type& info) const; - SparseComplexMatrix lssolve (const SparseComplexMatrix& b, octave_idx_type& info, - octave_idx_type& rank) const; - - ComplexColumnVector lssolve (const ColumnVector& b) const; - ComplexColumnVector lssolve (const ColumnVector& b, octave_idx_type& info) const; - ComplexColumnVector lssolve (const ColumnVector& b, octave_idx_type& info, - octave_idx_type& rank) const; - - ComplexColumnVector lssolve (const ComplexColumnVector& b) const; - ComplexColumnVector lssolve (const ComplexColumnVector& b, octave_idx_type& info) const; - ComplexColumnVector lssolve (const ComplexColumnVector& b, octave_idx_type& info, - octave_idx_type& rank) const; - SparseComplexMatrix squeeze (void) const; SparseComplexMatrix index (idx_vector& i, int resize_ok) const;
--- a/liboctave/ChangeLog +++ b/liboctave/ChangeLog @@ -1,3 +1,53 @@ +2006-03-16 David Bateman <dbateman@free.fr> + + * CSparse.cc: Change use of nzmax to nnz to allow automatic + reduction of matrix size, except for a couple of cases where nzmax + is needed. + (zpbcon): Correct declaration of lapack zpbcon function. + (dsolve, utsolve, ltsolve, trisolve, bsolve, factorize, fsolve): Add + an argument to allow the calculation of condition number to be + optional. + (bsolve): Add code for the calculation of the condition number + using zpbcon and zgbcon. + (dsolve): Bug fix for rectangular matrices with sparse RHS. + (utsolve, ltsolve, trisolve, bsolve, fsolve): Mark matrix type as + singular if singularity is detected. + (solve): Use optional argument to disable calculation of + condition number for all but fsolve, for speed. Add code to + allow rectnagular matrices or matrices identified as singular + to be treated. + (lssolve): delete. + (operator *): Don't recast real matrices as complex, but + rather use the macro directly on the real data. + * dSparse.cc: ditto. + * CSparse.h (dsolve, utsolve, ltsolve, trisolve, bsolve, + fsolve, factorize): Update declaration for new argument to + calculate the condition number. + (lssolve): delete. + * dSparse.h: ditto. + * Msparse.h: Change use of nxmax to nnz to allow automatic + reduction of matrix size, except for a couple of cases where + nzmax is needed. + * Sparse.cc: Change use of nxmax to nnz to allow automatic + reduction of matrix size, except for a couple of cases where + nzmax is needed. + (Sparse<T>::index (idx_vector&, idx_vector&, int) const): + Special case strict permutations for speed. + * Sparse-op-defs.h: Change use of nxmax to nnz to allow automatic + reduction of matrix size, except for a couple of cases where + nzmax is needed. + (SPARSE_SPARSE_MUL, SPARSE_FULL_MUL, FULL_SPARSE_MUL): Update + macros to allow mixed complex/real arguments. + * SparseCmplxQR.cc (OCTAVE_C99_ZERO): New macro for C99 zero + value. + (qrsolve): Use it to zero temporary buffers used bt CXSPARSE. + * SparseType.cc (SparseType::SparseType ()): Correct detection + of permutated triangular matrices to avoid seg-faults. Disable + detection of underdetermined lower and over-determined upper + matrix due to problems with non minimum norm solutions. + * sparse-dmsolve.cc: New file for Dulmage-Mendelsohn solver. + * Makefile.in: add sparse-dmsolve.cc to targets. + 2006-03-15 William Poetra Yoga Hadisoeseno <williampoetra@gmail.com> * oct-time.cc (octave_strptime::init): Return useful character count.
--- a/liboctave/MSparse.cc +++ b/liboctave/MSparse.cc @@ -52,7 +52,7 @@ gripe_nonconformant ("operator +=" , a_nr, a_nc, b_nr, b_nc); else { - r = MSparse<T> (a_nr, a_nc, (a.nzmax () + b.nzmax ())); + r = MSparse<T> (a_nr, a_nc, (a.nnz () + b.nnz ())); octave_idx_type jx = 0; for (octave_idx_type i = 0 ; i < a_nc ; i++) @@ -125,7 +125,7 @@ gripe_nonconformant ("operator -=" , a_nr, a_nc, b_nr, b_nc); else { - r = MSparse<T> (a_nr, a_nc, (a.nzmax () + b.nzmax ())); + r = MSparse<T> (a_nr, a_nc, (a.nnz () + b.nnz ())); octave_idx_type jx = 0; for (octave_idx_type i = 0 ; i < a_nc ; i++) @@ -207,7 +207,7 @@ { \ octave_idx_type nr = a.rows (); \ octave_idx_type nc = a.cols (); \ - octave_idx_type nz = a.nzmax (); \ + octave_idx_type nz = a.nnz (); \ \ MSparse<T> r (nr, nc, nz); \ \ @@ -253,7 +253,7 @@ { \ octave_idx_type nr = a.rows (); \ octave_idx_type nc = a.cols (); \ - octave_idx_type nz = a.nzmax (); \ + octave_idx_type nz = a.nnz (); \ \ MSparse<T> r (nr, nc, nz); \ \ @@ -292,7 +292,7 @@ gripe_nonconformant ("operator " # OP, a_nr, a_nc, b_nr, b_nc); \ else \ { \ - r = MSparse<T> (a_nr, a_nc, (a.nzmax () + b.nzmax ())); \ + r = MSparse<T> (a_nr, a_nc, (a.nnz () + b.nnz ())); \ \ octave_idx_type jx = 0; \ r.cidx (0) = 0; \ @@ -367,7 +367,7 @@ gripe_nonconformant (#FCN, a_nr, a_nc, b_nr, b_nc); \ else \ { \ - r = MSparse<T> (a_nr, a_nc, (a.nzmax () > b.nzmax () ? a.nzmax () : b.nzmax ())); \ + r = MSparse<T> (a_nr, a_nc, (a.nnz () > b.nnz () ? a.nnz () : b.nnz ())); \ \ octave_idx_type jx = 0; \ r.cidx (0) = 0; \ @@ -494,7 +494,7 @@ operator - (const MSparse<T>& a) { MSparse<T> retval (a); - octave_idx_type nz = a.nzmax (); + octave_idx_type nz = a.nnz (); for (octave_idx_type i = 0; i < nz; i++) retval.data(i) = - retval.data(i); return retval;
--- a/liboctave/Makefile.in +++ b/liboctave/Makefile.in @@ -37,8 +37,9 @@ dbleHESS.h dbleLU.h dbleQR.h dbleQRP.h dbleSCHUR.h dbleSVD.h \ boolSparse.h CSparse.h dSparse.h MSparse-defs.h MSparse.h \ Sparse.h sparse-base-lu.h SparseCmplxLU.h SparsedbleLU.h \ - sparse-base-chol.h SparseCmplxCHOL.h SparsedbleCHOL.h \ - SparseCmplxQR.h SparseQR.h Sparse-op-defs.h SparseType.h \ + sparse-base-chol.h sparse-dmsolve.cc SparseCmplxCHOL.h \ + SparsedbleCHOL.h SparseCmplxQR.h SparseQR.h Sparse-op-defs.h \ + SparseType.h \ int8NDArray.h uint8NDArray.h int16NDArray.h uint16NDArray.h \ int32NDArray.h uint32NDArray.h int64NDArray.h uint64NDArray.h \ intNDArray.h @@ -79,7 +80,8 @@ TEMPLATE_SRC := Array.cc ArrayN.cc DiagArray2.cc \ MArray.cc MArray2.cc MArrayN.cc MDiagArray2.cc \ - base-lu.cc oct-sort.cc sparse-base-lu.cc sparse-base-chol.cc + base-lu.cc oct-sort.cc sparse-base-lu.cc sparse-base-chol.cc \ + sparse-dmsolve.cc TI_SRC := Array-C.cc Array-b.cc Array-ch.cc Array-i.cc Array-d.cc \ Array-s.cc Array-so.cc Array-str.cc Array-idx-vec.cc \
--- a/liboctave/Sparse-op-defs.h +++ b/liboctave/Sparse-op-defs.h @@ -63,7 +63,7 @@ { \ octave_idx_type nr = m.rows (); \ octave_idx_type nc = m.cols (); \ - octave_idx_type nz = m.nzmax (); \ + octave_idx_type nz = m.nnz (); \ \ R r (nr, nc, nz); \ \ @@ -103,7 +103,7 @@ { \ /* Count num of non-zero elements */ \ octave_idx_type nel = 0; \ - octave_idx_type nz = m.nzmax (); \ + octave_idx_type nz = m.nnz (); \ if (MC (MZ) OP SC (s)) \ nel += m.numel() - nz; \ for (octave_idx_type i = 0; i < nz; i++) \ @@ -178,7 +178,7 @@ { \ /* Count num of non-zero elements */ \ octave_idx_type nel = 0; \ - octave_idx_type nz = m.nzmax (); \ + octave_idx_type nz = m.nnz (); \ if (LHS_ZERO OP (s != RHS_ZERO)) \ nel += m.numel() - nz; \ for (octave_idx_type i = 0; i < nz; i++) \ @@ -273,7 +273,7 @@ { \ octave_idx_type nr = m.rows (); \ octave_idx_type nc = m.cols (); \ - octave_idx_type nz = m.nzmax (); \ + octave_idx_type nz = m.nnz (); \ \ R r (nr, nc, nz); \ \ @@ -313,7 +313,7 @@ { \ /* Count num of non-zero elements */ \ octave_idx_type nel = 0; \ - octave_idx_type nz = m.nzmax (); \ + octave_idx_type nz = m.nnz (); \ if (SC (s) OP MC (MZ)) \ nel += m.numel() - nz; \ for (octave_idx_type i = 0; i < nz; i++) \ @@ -388,7 +388,7 @@ { \ /* Count num of non-zero elements */ \ octave_idx_type nel = 0; \ - octave_idx_type nz = m.nzmax (); \ + octave_idx_type nz = m.nnz (); \ if ((s != LHS_ZERO) OP RHS_ZERO) \ nel += m.numel() - nz; \ for (octave_idx_type i = 0; i < nz; i++) \ @@ -477,7 +477,7 @@ gripe_nonconformant (#F, m1_nr, m1_nc, m2_nr, m2_nc); \ else \ { \ - r = R (m1_nr, m1_nc, (m1.nzmax () + m2.nzmax ())); \ + r = R (m1_nr, m1_nc, (m1.nnz () + m2.nnz ())); \ \ octave_idx_type jx = 0; \ r.cidx (0) = 0; \ @@ -551,7 +551,7 @@ gripe_nonconformant (#F, m1_nr, m1_nc, m2_nr, m2_nc); \ else \ { \ - r = R (m1_nr, m1_nc, (m1.nzmax () > m2.nzmax () ? m1.nzmax () : m2.nzmax ())); \ + r = R (m1_nr, m1_nc, (m1.nnz () > m2.nnz () ? m1.nnz () : m2.nnz ())); \ \ octave_idx_type jx = 0; \ r.cidx (0) = 0; \ @@ -1533,7 +1533,7 @@ #define SPARSE_ANY_OP(DIM) SPARSE_ANY_ALL_OP (DIM, false, !=, true) -#define SPARSE_SPARSE_MUL( RET_TYPE, EL_TYPE ) \ +#define SPARSE_SPARSE_MUL( RET_TYPE, RET_EL_TYPE, EL_TYPE ) \ octave_idx_type nr = m.rows (); \ octave_idx_type nc = m.cols (); \ \ @@ -1577,7 +1577,7 @@ for (octave_idx_type i = 0; i < nr; i++) \ w[i] = 0; \ \ - OCTAVE_LOCAL_BUFFER (EL_TYPE, Xcol, nr); \ + OCTAVE_LOCAL_BUFFER (RET_EL_TYPE, Xcol, nr); \ \ RET_TYPE retval (nr, a_nc, nel); \ octave_idx_type ii = 0; \ @@ -1663,7 +1663,7 @@ } \ } -#define SPARSE_FULL_MUL( RET_TYPE, EL_TYPE ) \ +#define SPARSE_FULL_MUL( RET_TYPE, EL_TYPE, ZERO ) \ octave_idx_type nr = m.rows (); \ octave_idx_type nc = m.cols (); \ \ @@ -1677,7 +1677,7 @@ } \ else \ { \ - RET_TYPE retval (nr, a_nc, EL_TYPE ()); \ + RET_TYPE retval (nr, a_nc, ZERO); \ \ for (octave_idx_type i = 0; i < a_nc ; i++) \ { \ @@ -1693,7 +1693,7 @@ return retval; \ } -#define FULL_SPARSE_MUL( RET_TYPE, EL_TYPE ) \ +#define FULL_SPARSE_MUL( RET_TYPE, EL_TYPE, ZERO ) \ octave_idx_type nr = m.rows (); \ octave_idx_type nc = m.cols (); \ \ @@ -1707,7 +1707,7 @@ } \ else \ { \ - RET_TYPE retval (nr, a_nc, EL_TYPE ()); \ + RET_TYPE retval (nr, a_nc, ZERO); \ \ for (octave_idx_type i = 0; i < a_nc ; i++) \ { \
--- a/liboctave/Sparse.cc +++ b/liboctave/Sparse.cc @@ -202,13 +202,13 @@ Sparse<T>::Sparse (const Sparse<U>& a) : dimensions (a.dimensions), idx (0), idx_count (0) { - if (a.nzmax () == 0) + if (a.nnz () == 0) rep = new typename Sparse<T>::SparseRep (rows (), cols()); else { - rep = new typename Sparse<T>::SparseRep (rows (), cols (), a.nzmax ()); + rep = new typename Sparse<T>::SparseRep (rows (), cols (), a.nnz ()); - octave_idx_type nz = nzmax (); + octave_idx_type nz = a.nnz (); octave_idx_type nc = cols (); for (octave_idx_type i = 0; i < nz; i++) { @@ -276,7 +276,7 @@ else { dim_vector old_dims = a.dims(); - octave_idx_type new_nzmx = a.nzmax (); + octave_idx_type new_nzmx = a.nnz (); octave_idx_type new_nr = dv (0); octave_idx_type new_nc = dv (1); octave_idx_type old_nr = old_dims (0); @@ -740,12 +740,12 @@ { if (dimensions.numel () == new_dims.numel ()) { - octave_idx_type new_nzmx = nzmax (); + octave_idx_type new_nnz = nnz (); octave_idx_type new_nr = new_dims (0); octave_idx_type new_nc = new_dims (1); octave_idx_type old_nr = rows (); octave_idx_type old_nc = cols (); - retval = Sparse<T> (new_nr, new_nc, new_nzmx); + retval = Sparse<T> (new_nr, new_nc, new_nnz); octave_idx_type kk = 0; retval.xcidx(0) = 0; @@ -762,7 +762,7 @@ retval.xridx(j) = ii; } for (octave_idx_type k = kk; k < new_nc; k++) - retval.xcidx(k+1) = new_nzmx; + retval.xcidx(k+1) = new_nnz; } else (*current_liboctave_error_handler) ("reshape: size mismatch"); @@ -855,7 +855,7 @@ octave_idx_type nc = cols (); octave_idx_type nr = rows (); - if (nzmax () == 0 || r == 0 || c == 0) + if (nnz () == 0 || r == 0 || c == 0) // Special case of redimensioning to/from a sparse matrix with // no elements rep = new typename Sparse<T>::SparseRep (r, c); @@ -944,7 +944,7 @@ } // First count the number of elements in the final array - octave_idx_type nel = cidx(c) + a.nzmax (); + octave_idx_type nel = cidx(c) + a.nnz (); if (c + a_cols < nc) nel += cidx(nc) - cidx(c + a_cols); @@ -1142,7 +1142,7 @@ if (num_to_delete != 0) { octave_idx_type new_n = n; - octave_idx_type new_nzmx = nzmax (); + octave_idx_type new_nnz = nnz (); octave_idx_type iidx = 0; @@ -1158,7 +1158,7 @@ new_n--; if (tmp.elem (i) != T ()) - new_nzmx--; + new_nnz--; if (iidx == num_to_delete) break; @@ -1170,9 +1170,9 @@ rep->count--; if (nr == 1) - rep = new typename Sparse<T>::SparseRep (1, new_n, new_nzmx); + rep = new typename Sparse<T>::SparseRep (1, new_n, new_nnz); else - rep = new typename Sparse<T>::SparseRep (new_n, 1, new_nzmx); + rep = new typename Sparse<T>::SparseRep (new_n, 1, new_nnz); octave_idx_type ii = 0; octave_idx_type jj = 0; @@ -1215,7 +1215,7 @@ else { cidx(0) = 0; - cidx(1) = new_nzmx; + cidx(1) = new_nnz; dimensions(0) = new_n; dimensions(1) = 1; } @@ -1287,7 +1287,7 @@ else { octave_idx_type new_nc = nc; - octave_idx_type new_nzmx = nzmax (); + octave_idx_type new_nnz = nnz (); octave_idx_type iidx = 0; @@ -1300,7 +1300,7 @@ iidx++; new_nc--; - new_nzmx -= cidx(j+1) - cidx(j); + new_nnz -= cidx(j+1) - cidx(j); if (iidx == num_to_delete) break; @@ -1312,7 +1312,7 @@ const Sparse<T> tmp (*this); --rep->count; rep = new typename Sparse<T>::SparseRep (nr, new_nc, - new_nzmx); + new_nnz); octave_idx_type ii = 0; octave_idx_type jj = 0; iidx = 0; @@ -1362,7 +1362,7 @@ else { octave_idx_type new_nr = nr; - octave_idx_type new_nzmx = nzmax (); + octave_idx_type new_nnz = nnz (); octave_idx_type iidx = 0; @@ -1375,9 +1375,9 @@ iidx++; new_nr--; - for (octave_idx_type j = 0; j < nzmax (); j++) + for (octave_idx_type j = 0; j < nnz (); j++) if (ridx(j) == i) - new_nzmx--; + new_nnz--; if (iidx == num_to_delete) break; @@ -1389,7 +1389,7 @@ const Sparse<T> tmp (*this); --rep->count; rep = new typename Sparse<T>::SparseRep (new_nr, nc, - new_nzmx); + new_nnz); octave_idx_type jj = 0; cidx(0) = 0; @@ -1483,7 +1483,7 @@ octave_idx_type nr = dim1 (); octave_idx_type nc = dim2 (); - octave_idx_type nz = nzmax (); + octave_idx_type nz = nnz (); octave_idx_type orig_len = nr * nc; @@ -1838,66 +1838,151 @@ { retval.resize_no_fill (n, m); } - else if (idx_i.is_colon_equiv (nr) && idx_j.is_colon_equiv (nc)) - { - retval = *this; - } - else + else { - // First count the number of non-zero elements - octave_idx_type new_nzmx = 0; - for (octave_idx_type j = 0; j < m; j++) + int idx_i_colon = idx_i.is_colon_equiv (nr); + int idx_j_colon = idx_j.is_colon_equiv (nc); + + if (idx_i_colon && idx_j_colon) + { + retval = *this; + } + else { - octave_idx_type jj = idx_j.elem (j); - for (octave_idx_type i = 0; i < n; i++) + // Identify if the indices have any repeated values + bool permutation = true; + + OCTAVE_LOCAL_BUFFER (octave_idx_type, itmp, + (nr > nc ? nr : nc)); + octave_sort<octave_idx_type> sort; + + if (n > nr || m > nc) + permutation = false; + + if (permutation && ! idx_i_colon) + { + // Can't use something like + // idx_vector tmp_idx = idx_i; + // tmp_idx.sort (true); + // if (tmp_idx.length(nr) != n) + // permutation = false; + // here as there is no make_unique function + // for idx_vector type. + for (octave_idx_type i = 0; i < n; i++) + itmp [i] = idx_i.elem (i); + sort.sort (itmp, n); + for (octave_idx_type i = 1; i < n; i++) + if (itmp[i-1] == itmp[i]) + { + permutation = false; + break; + } + } + if (permutation && ! idx_j_colon) + { + for (octave_idx_type i = 0; i < m; i++) + itmp [i] = idx_j.elem (i); + sort.sort (itmp, m); + for (octave_idx_type i = 1; i < m; i++) + if (itmp[i-1] == itmp[i]) + { + permutation = false; + break; + } + } + + if (permutation) { - OCTAVE_QUIT; - - octave_idx_type ii = idx_i.elem (i); - if (ii < nr && jj < nc) + // Special case permutation like indexing for speed + retval = Sparse<T> (n, m, nnz ()); + octave_idx_type *ri = retval.xridx (); + + // Can't use OCTAVE_LOCAL_BUFFER with bool, and so + // can't with T either + T X [n]; + for (octave_idx_type i = 0; i < nr; i++) + itmp [i] = -1; + for (octave_idx_type i = 0; i < n; i++) + itmp[idx_i.elem(i)] = i; + + octave_idx_type kk = 0; + retval.xcidx(0) = 0; + for (octave_idx_type j = 0; j < m; j++) + { + octave_idx_type jj = idx_j.elem (j); + for (octave_idx_type i = cidx(jj); i < cidx(jj+1); i++) + { + octave_idx_type ii = itmp [ridx(i)]; + if (ii >= 0) + { + X [ii] = data (i); + retval.xridx (kk++) = ii; + } + } + sort.sort (ri + retval.xcidx (j), kk - retval.xcidx (j)); + for (octave_idx_type p = retval.xcidx (j); p < kk; p++) + retval.xdata (p) = X [retval.xridx (p)]; + retval.xcidx(j+1) = kk; + } + retval.maybe_compress (); + } + else + { + // First count the number of non-zero elements + octave_idx_type new_nzmx = 0; + for (octave_idx_type j = 0; j < m; j++) { - for (octave_idx_type k = cidx(jj); k < cidx(jj+1); k++) + octave_idx_type jj = idx_j.elem (j); + for (octave_idx_type i = 0; i < n; i++) { - if (ridx(k) == ii) - new_nzmx++; - if (ridx(k) >= ii) - break; + OCTAVE_QUIT; + + octave_idx_type ii = idx_i.elem (i); + if (ii < nr && jj < nc) + { + for (octave_idx_type k = cidx(jj); k < cidx(jj+1); k++) + { + if (ridx(k) == ii) + new_nzmx++; + if (ridx(k) >= ii) + break; + } + } } } + + retval = Sparse<T> (n, m, new_nzmx); + + octave_idx_type kk = 0; + retval.xcidx(0) = 0; + for (octave_idx_type j = 0; j < m; j++) + { + octave_idx_type jj = idx_j.elem (j); + for (octave_idx_type i = 0; i < n; i++) + { + OCTAVE_QUIT; + + octave_idx_type ii = idx_i.elem (i); + if (ii < nr && jj < nc) + { + for (octave_idx_type k = cidx(jj); k < cidx(jj+1); k++) + { + if (ridx(k) == ii) + { + retval.xdata(kk) = data(k); + retval.xridx(kk++) = i; + } + if (ridx(k) >= ii) + break; + } + } + } + retval.xcidx(j+1) = kk; + } } } - - retval = Sparse<T> (n, m, new_nzmx); - - octave_idx_type kk = 0; - retval.xcidx(0) = 0; - for (octave_idx_type j = 0; j < m; j++) - { - octave_idx_type jj = idx_j.elem (j); - for (octave_idx_type i = 0; i < n; i++) - { - OCTAVE_QUIT; - - octave_idx_type ii = idx_i.elem (i); - if (ii < nr && jj < nc) - { - for (octave_idx_type k = cidx(jj); k < cidx(jj+1); k++) - { - if (ridx(k) == ii) - { - retval.xdata(kk) = data(k); - retval.xridx(kk++) = i; - } - if (ridx(k) >= ii) - break; - } - } - } - retval.xcidx(j+1) = kk; - } } } - // idx_vector::freeze() printed an error message for us. return retval; @@ -1955,7 +2040,7 @@ octave_idx_type nr = lhs.rows (); octave_idx_type nc = lhs.cols (); - octave_idx_type nz = lhs.nzmax (); + octave_idx_type nz = lhs.nnz (); octave_idx_type n = lhs_idx.freeze (lhs_len, "vector", true, liboctave_wrore_flag); @@ -1971,7 +2056,7 @@ if (rhs_len == n) { - octave_idx_type new_nzmx = lhs.nzmax (); + octave_idx_type new_nzmx = lhs.nnz (); OCTAVE_LOCAL_BUFFER (octave_idx_type, rhs_idx, n); if (! lhs_idx.is_colon ()) @@ -2026,7 +2111,7 @@ { Sparse<LT> tmp (max_idx, 1, new_nzmx); tmp.cidx(0) = 0; - tmp.cidx(1) = tmp.nzmax (); + tmp.cidx(1) = new_nzmx; octave_idx_type i = 0; octave_idx_type ii = 0; @@ -2124,7 +2209,7 @@ } else if (rhs_len == 1) { - octave_idx_type new_nzmx = lhs.nzmax (); + octave_idx_type new_nzmx = lhs.nnz (); RT scalar = rhs.elem (0); bool scalar_non_zero = (scalar != RT ()); lhs_idx.sort (true); @@ -2145,7 +2230,7 @@ { Sparse<LT> tmp (max_idx, 1, new_nzmx); tmp.cidx(0) = 0; - tmp.cidx(1) = tmp.nzmax (); + tmp.cidx(1) = new_nzmx; octave_idx_type i = 0; octave_idx_type ii = 0; @@ -2248,7 +2333,7 @@ if (lhs_len == 0) { - octave_idx_type new_nzmx = rhs.nzmax (); + octave_idx_type new_nzmx = rhs.nnz (); Sparse<LT> tmp (1, rhs_len, new_nzmx); octave_idx_type ii = 0; @@ -2296,7 +2381,7 @@ octave_idx_type lhs_nr = lhs.rows (); octave_idx_type lhs_nc = lhs.cols (); - octave_idx_type lhs_nz = lhs.nzmax (); + octave_idx_type lhs_nz = lhs.nnz (); octave_idx_type rhs_nr = rhs.rows (); octave_idx_type rhs_nc = rhs.cols (); @@ -2364,7 +2449,7 @@ RT scalar = rhs.elem (0, 0); // Count the number of non-zero terms - octave_idx_type new_nzmx = lhs.nzmax (); + octave_idx_type new_nzmx = lhs.nnz (); for (octave_idx_type j = 0; j < m; j++) { octave_idx_type jj = idx_j.elem (j); @@ -2545,7 +2630,7 @@ rhs_idx_j[i] = i; // Count the number of non-zero terms - octave_idx_type new_nzmx = lhs.nzmax (); + octave_idx_type new_nzmx = lhs.nnz (); for (octave_idx_type j = 0; j < m; j++) { octave_idx_type jj = idx_j.elem (j);
--- a/liboctave/SparseCmplxQR.cc +++ b/liboctave/SparseCmplxQR.cc @@ -34,6 +34,8 @@ OCTAVE_LOCAL_BUFFER (double, buf ## tmp, (2 * (n))); \ double _Complex *buf = reinterpret_cast<double _Complex *> (buf ## tmp); +#define OCTAVE_C99_ZERO (0. + 0.iF); + SparseComplexQR::SparseComplexQR_rep::SparseComplexQR_rep (const SparseComplexMatrix& a, int order) { @@ -233,6 +235,8 @@ OCTAVE_QUIT; for (octave_idx_type j = 0; j < b_nr; j++) Xx[j] = b.xelem(j,i); + for (octave_idx_type j = nr; j < q.S()->m2; j++) + buf[j] = OCTAVE_C99_ZERO; BEGIN_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE; CXSPARSE_ZNAME (_ipvec) (nr, q.S()->Pinv, reinterpret_cast<double _Complex *>(Xx), buf); @@ -262,7 +266,8 @@ x.resize(nc, b_nc); double _Complex *vec = reinterpret_cast<double _Complex *> (x.fortran_vec()); - OCTAVE_C99_COMPLEX (buf, nc > q.S()->m2 ? nc : q.S()->m2); + volatile octave_idx_type nbuf = (nc > q.S()->m2 ? nc : q.S()->m2); + OCTAVE_C99_COMPLEX (buf, nbuf); OCTAVE_LOCAL_BUFFER (Complex, Xx, b_nr); OCTAVE_LOCAL_BUFFER (Complex, B, nr); for (octave_idx_type i = 0; i < nr; i++) @@ -272,6 +277,8 @@ OCTAVE_QUIT; for (octave_idx_type j = 0; j < b_nr; j++) Xx[j] = b.xelem(j,i); + for (octave_idx_type j = nr; j < nbuf; j++) + buf[j] = OCTAVE_C99_ZERO; BEGIN_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE; CXSPARSE_ZNAME (_pvec) (nr, q.S()->Q, reinterpret_cast<double _Complex *>(Xx), buf); @@ -332,6 +339,8 @@ OCTAVE_QUIT; for (octave_idx_type j = 0; j < b_nr; j++) Xx[j] = b.xelem(j,i); + for (octave_idx_type j = nr; j < q.S()->m2; j++) + buf[j] = OCTAVE_C99_ZERO; BEGIN_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE; CXSPARSE_ZNAME (_ipvec) (nr, q.S()->Pinv, reinterpret_cast<double _Complex *>(Xx), buf); @@ -382,8 +391,9 @@ x.xcidx(0) = 0; x_nz = b.nzmax(); ii = 0; + volatile octave_idx_type nbuf = (nc > q.S()->m2 ? nc : q.S()->m2); OCTAVE_LOCAL_BUFFER (Complex, Xx, (b_nr > nc ? b_nr : nc)); - OCTAVE_C99_COMPLEX (buf, nc > q.S()->m2 ? nc : q.S()->m2); + OCTAVE_C99_COMPLEX (buf, nbuf); OCTAVE_LOCAL_BUFFER (Complex, B, nr); for (octave_idx_type i = 0; i < nr; i++) B[i] = conj (reinterpret_cast<Complex *>(q.N()->B) [i]); @@ -392,6 +402,8 @@ OCTAVE_QUIT; for (octave_idx_type j = 0; j < b_nr; j++) Xx[j] = b.xelem(j,i); + for (octave_idx_type j = nr; j < nbuf; j++) + buf[j] = OCTAVE_C99_ZERO; BEGIN_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE; CXSPARSE_ZNAME (_pvec) (nr, q.S()->Q, reinterpret_cast<double _Complex *>(Xx), buf); @@ -470,6 +482,8 @@ i++, idx+=nc, bidx+=b_nr) { OCTAVE_QUIT; + for (octave_idx_type j = nr; j < q.S()->m2; j++) + buf[j] = OCTAVE_C99_ZERO; BEGIN_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE; CXSPARSE_ZNAME (_ipvec) (nr, q.S()->Pinv, bvec + bidx, buf); END_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE; @@ -498,7 +512,8 @@ x.resize(nc, b_nc); double _Complex *vec = reinterpret_cast<double _Complex *> (x.fortran_vec()); - OCTAVE_C99_COMPLEX (buf, nc > q.S()->m2 ? nc : q.S()->m2); + volatile octave_idx_type nbuf = (nc > q.S()->m2 ? nc : q.S()->m2); + OCTAVE_C99_COMPLEX (buf, nbuf); OCTAVE_LOCAL_BUFFER (Complex, B, nr); for (octave_idx_type i = 0; i < nr; i++) B[i] = conj (reinterpret_cast<Complex *>(q.N()->B) [i]); @@ -506,6 +521,8 @@ i++, idx+=nc, bidx+=b_nr) { OCTAVE_QUIT; + for (octave_idx_type j = nr; j < nbuf; j++) + buf[j] = OCTAVE_C99_ZERO; BEGIN_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE; CXSPARSE_ZNAME (_pvec) (nr, q.S()->Q, bvec + bidx, buf); CXSPARSE_ZNAME (_utsolve) (q.N()->U, buf); @@ -564,6 +581,8 @@ OCTAVE_QUIT; for (octave_idx_type j = 0; j < b_nr; j++) Xx[j] = b.xelem(j,i); + for (octave_idx_type j = nr; j < q.S()->m2; j++) + buf[j] = OCTAVE_C99_ZERO; BEGIN_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE; CXSPARSE_ZNAME (_ipvec) (nr, q.S()->Pinv, reinterpret_cast<double _Complex *>(Xx), buf); @@ -614,8 +633,9 @@ x.xcidx(0) = 0; x_nz = b.nzmax(); ii = 0; + volatile octave_idx_type nbuf = (nc > q.S()->m2 ? nc : q.S()->m2); OCTAVE_LOCAL_BUFFER (Complex, Xx, (b_nr > nc ? b_nr : nc)); - OCTAVE_C99_COMPLEX (buf, nc > q.S()->m2 ? nc : q.S()->m2); + OCTAVE_C99_COMPLEX (buf, nbuf); OCTAVE_LOCAL_BUFFER (Complex, B, nr); for (octave_idx_type i = 0; i < nr; i++) B[i] = conj (reinterpret_cast<Complex *>(q.N()->B) [i]); @@ -624,6 +644,8 @@ OCTAVE_QUIT; for (octave_idx_type j = 0; j < b_nr; j++) Xx[j] = b.xelem(j,i); + for (octave_idx_type j = nr; j < nbuf; j++) + buf[j] = OCTAVE_C99_ZERO; BEGIN_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE; CXSPARSE_ZNAME (_pvec) (nr, q.S()->Q, reinterpret_cast<double _Complex *>(Xx), buf); @@ -675,4 +697,3 @@ ;;; mode: C++ *** ;;; End: *** */ -
--- a/liboctave/SparseQR.cc +++ b/liboctave/SparseQR.cc @@ -170,6 +170,8 @@ for (volatile octave_idx_type j = 0, idx = 0; j < b_nc; j++, idx+=b_nr) { OCTAVE_QUIT; + for (octave_idx_type i = nr; i < S->m2; i++) + buf[i] = 0.; volatile octave_idx_type nm = (nr < nc ? nr : nc); BEGIN_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE; CXSPARSE_DNAME (_ipvec) (b_nr, S->Pinv, bvec + idx, buf); @@ -222,6 +224,8 @@ i++, idx+=nc, bidx+=b_nr) { OCTAVE_QUIT; + for (octave_idx_type j = nr; j < q.S()->m2; j++) + buf[j] = 0.; BEGIN_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE; CXSPARSE_DNAME (_ipvec) (nr, q.S()->Pinv, bvec + bidx, buf); END_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE; @@ -249,11 +253,14 @@ } x.resize(nc, b_nc); double *vec = x.fortran_vec(); - OCTAVE_LOCAL_BUFFER (double, buf, nc > q.S()->m2 ? nc : q.S()->m2); + volatile octave_idx_type nbuf = (nc > q.S()->m2 ? nc : q.S()->m2); + OCTAVE_LOCAL_BUFFER (double, buf, nbuf); for (volatile octave_idx_type i = 0, idx = 0, bidx = 0; i < b_nc; i++, idx+=nc, bidx+=b_nr) { OCTAVE_QUIT; + for (octave_idx_type j = nr; j < nbuf; j++) + buf[j] = 0.; BEGIN_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE; CXSPARSE_DNAME (_pvec) (nr, q.S()->Q, bvec + bidx, buf); CXSPARSE_DNAME (_utsolve) (q.N()->U, buf); @@ -311,6 +318,8 @@ OCTAVE_QUIT; for (octave_idx_type j = 0; j < b_nr; j++) Xx[j] = b.xelem(j,i); + for (octave_idx_type j = nr; j < q.S()->m2; j++) + buf[j] = 0.; BEGIN_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE; CXSPARSE_DNAME (_ipvec) (nr, q.S()->Pinv, Xx, buf); END_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE; @@ -359,13 +368,16 @@ x.xcidx(0) = 0; x_nz = b.nzmax(); ii = 0; + volatile octave_idx_type nbuf = (nc > q.S()->m2 ? nc : q.S()->m2); OCTAVE_LOCAL_BUFFER (double, Xx, (b_nr > nc ? b_nr : nc)); - OCTAVE_LOCAL_BUFFER (double, buf, nc > q.S()->m2 ? nc : q.S()->m2); + OCTAVE_LOCAL_BUFFER (double, buf, nbuf); for (volatile octave_idx_type i = 0, idx = 0; i < b_nc; i++, idx+=nc) { OCTAVE_QUIT; for (octave_idx_type j = 0; j < b_nr; j++) Xx[j] = b.xelem(j,i); + for (octave_idx_type j = nr; j < nbuf; j++) + buf[j] = 0.; BEGIN_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE; CXSPARSE_DNAME (_pvec) (nr, q.S()->Q, Xx, buf); CXSPARSE_DNAME (_utsolve) (q.N()->U, buf); @@ -445,6 +457,8 @@ Xx[j] = std::real (c); Xz[j] = std::imag (c); } + for (octave_idx_type j = nr; j < q.S()->m2; j++) + buf[j] = 0.; BEGIN_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE; CXSPARSE_DNAME (_ipvec) (nr, q.S()->Pinv, Xx, buf); END_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE; @@ -459,6 +473,8 @@ CXSPARSE_DNAME (_usolve) (q.N()->U, buf); CXSPARSE_DNAME (_ipvec) (nc, q.S()->Q, buf, Xx); + for (octave_idx_type j = nr; j < q.S()->m2; j++) + buf[j] = 0.; CXSPARSE_DNAME (_ipvec) (nr, q.S()->Pinv, Xz, buf); END_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE; for (volatile octave_idx_type j = 0; j < nc; j++) @@ -487,9 +503,10 @@ } x.resize(nc, b_nc); Complex *vec = x.fortran_vec(); + volatile octave_idx_type nbuf = (nc > q.S()->m2 ? nc : q.S()->m2); OCTAVE_LOCAL_BUFFER (double, Xx, (b_nr > nc ? b_nr : nc)); OCTAVE_LOCAL_BUFFER (double, Xz, (b_nr > nc ? b_nr : nc)); - OCTAVE_LOCAL_BUFFER (double, buf, nc > q.S()->m2 ? nc : q.S()->m2); + OCTAVE_LOCAL_BUFFER (double, buf, nbuf); for (volatile octave_idx_type i = 0, idx = 0; i < b_nc; i++, idx+=nc) { OCTAVE_QUIT; @@ -499,6 +516,8 @@ Xx[j] = std::real (c); Xz[j] = std::imag (c); } + for (octave_idx_type j = nr; j < nbuf; j++) + buf[j] = 0.; BEGIN_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE; CXSPARSE_DNAME (_pvec) (nr, q.S()->Q, Xx, buf); CXSPARSE_DNAME (_utsolve) (q.N()->U, buf); @@ -512,6 +531,10 @@ } BEGIN_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE; CXSPARSE_DNAME (_pvec) (nc, q.S()->Pinv, buf, Xx); + END_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE; + for (octave_idx_type j = nr; j < nbuf; j++) + buf[j] = 0.; + BEGIN_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE; CXSPARSE_DNAME (_pvec) (nr, q.S()->Q, Xz, buf); CXSPARSE_DNAME (_utsolve) (q.N()->U, buf); END_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE; @@ -575,6 +598,8 @@ Xx[j] = std::real (c); Xz[j] = std::imag (c); } + for (octave_idx_type j = nr; j < q.S()->m2; j++) + buf[j] = 0.; BEGIN_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE; CXSPARSE_DNAME (_ipvec) (nr, q.S()->Pinv, Xx, buf); END_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE; @@ -588,6 +613,10 @@ BEGIN_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE; CXSPARSE_DNAME (_usolve) (q.N()->U, buf); CXSPARSE_DNAME (_ipvec) (nc, q.S()->Q, buf, Xx); + END_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE; + for (octave_idx_type j = nr; j < q.S()->m2; j++) + buf[j] = 0.; + BEGIN_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE; CXSPARSE_DNAME (_ipvec) (nr, q.S()->Pinv, Xz, buf); END_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE; for (volatile octave_idx_type j = 0; j < nc; j++) @@ -635,9 +664,10 @@ x.xcidx(0) = 0; x_nz = b.nzmax(); ii = 0; + volatile octave_idx_type nbuf = (nc > q.S()->m2 ? nc : q.S()->m2); OCTAVE_LOCAL_BUFFER (double, Xx, (b_nr > nc ? b_nr : nc)); OCTAVE_LOCAL_BUFFER (double, Xz, (b_nr > nc ? b_nr : nc)); - OCTAVE_LOCAL_BUFFER (double, buf, nc > q.S()->m2 ? nc : q.S()->m2); + OCTAVE_LOCAL_BUFFER (double, buf, nbuf); for (volatile octave_idx_type i = 0, idx = 0; i < b_nc; i++, idx+=nc) { OCTAVE_QUIT; @@ -647,6 +677,8 @@ Xx[j] = std::real (c); Xz[j] = std::imag (c); } + for (octave_idx_type j = nr; j < nbuf; j++) + buf[j] = 0.; BEGIN_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE; CXSPARSE_DNAME (_pvec) (nr, q.S()->Q, Xx, buf); CXSPARSE_DNAME (_utsolve) (q.N()->U, buf); @@ -660,6 +692,10 @@ } BEGIN_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE; CXSPARSE_DNAME (_pvec) (nc, q.S()->Pinv, buf, Xx); + END_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE; + for (octave_idx_type j = nr; j < nbuf; j++) + buf[j] = 0.; + BEGIN_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE; CXSPARSE_DNAME (_pvec) (nr, q.S()->Q, Xz, buf); CXSPARSE_DNAME (_utsolve) (q.N()->U, buf); END_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE;
--- a/liboctave/SparseType.cc +++ b/liboctave/SparseType.cc @@ -192,7 +192,10 @@ bool found = false; nperm = ncols; - perm = new octave_idx_type [nperm]; + perm = new octave_idx_type [ncols]; + + for (octave_idx_type i = 0; i < ncols; i++) + perm [i] = -1; for (octave_idx_type i = 0; i < nm; i++) { @@ -200,9 +203,8 @@ for (octave_idx_type j = 0; j < ncols; j++) { - if ((a.cidx(j+1) - a.cidx(j)) > 0 && - a.ridx(a.cidx(j+1)-1) == i) + (a.ridx(a.cidx(j+1)-1) == i)) { perm [i] = j; found = true; @@ -215,15 +217,24 @@ } if (found) - typ = SparseType::Permuted_Upper; - else { - delete [] perm; + typ = SparseType::Permuted_Upper; + if (ncols > nrows) + { + octave_idx_type k = nrows; + for (octave_idx_type i = 0; i < ncols; i++) + if (perm [i] == -1) + perm[i] = k++; + } + } + else if (a.cidx(nm) == a.cidx(ncols)) + { nperm = nrows; - perm = new octave_idx_type [nperm]; - OCTAVE_LOCAL_BUFFER (octave_idx_type, tmp, nperm); + delete [] perm; + perm = new octave_idx_type [nrows]; + OCTAVE_LOCAL_BUFFER (octave_idx_type, tmp, nrows); - for (octave_idx_type i = 0; i < nperm; i++) + for (octave_idx_type i = 0; i < nrows; i++) { perm [i] = -1; tmp [i] = -1; @@ -231,10 +242,10 @@ for (octave_idx_type j = 0; j < ncols; j++) for (octave_idx_type i = a.cidx(j); i < a.cidx(j+1); i++) - perm [a.ridx(i)] = j; - + perm [a.ridx(i)] = j; + found = true; - for (octave_idx_type i = 0; i < nperm; i++) + for (octave_idx_type i = 0; i < nm; i++) if (perm[i] == -1) { found = false; @@ -246,12 +257,24 @@ } if (found) - for (octave_idx_type i = 0; i < nm; i++) - if (tmp[i] == -1) + { + octave_idx_type k = ncols; + for (octave_idx_type i = 0; i < nrows; i++) { - found = false; - break; + if (tmp[i] == -1) + { + if (k < nrows) + { + perm[k++] = i; + } + else + { + found = false; + break; + } + } } + } if (found) typ = SparseType::Permuted_Lower; @@ -261,6 +284,27 @@ nperm = 0; } } + else + { + delete [] perm; + nperm = 0; + } + } + + // XXX FIXME XXX + // Disable lower under-determined and upper over-determined problems + // as being detected, and force to treat as singular. As this seems + // to cause issues + if (((typ == SparseType::Lower || typ == SparseType::Permuted_Lower) + && nrows > ncols) || + ((typ == SparseType::Upper || typ == SparseType::Permuted_Upper) + && nrows < ncols)) + { + typ = SparseType::Rectangular; + if (typ == SparseType::Permuted_Upper || + typ == SparseType::Permuted_Lower) + delete [] perm; + nperm = 0; } if (typ == SparseType::Full && ncols != nrows) @@ -473,7 +517,10 @@ bool found = false; nperm = ncols; - perm = new octave_idx_type [nperm]; + perm = new octave_idx_type [ncols]; + + for (octave_idx_type i = 0; i < ncols; i++) + perm [i] = -1; for (octave_idx_type i = 0; i < nm; i++) { @@ -481,9 +528,8 @@ for (octave_idx_type j = 0; j < ncols; j++) { - if ((a.cidx(j+1) - a.cidx(j)) > 0 && - a.ridx(a.cidx(j+1)-1) == i) + (a.ridx(a.cidx(j+1)-1) == i)) { perm [i] = j; found = true; @@ -496,15 +542,24 @@ } if (found) - typ = SparseType::Permuted_Upper; - else { - delete [] perm; + typ = SparseType::Permuted_Upper; + if (ncols > nrows) + { + octave_idx_type k = nrows; + for (octave_idx_type i = 0; i < ncols; i++) + if (perm [i] == -1) + perm[i] = k++; + } + } + else if (a.cidx(nm) == a.cidx(ncols)) + { nperm = nrows; - perm = new octave_idx_type [nperm]; - OCTAVE_LOCAL_BUFFER (octave_idx_type, tmp, nperm); + delete [] perm; + perm = new octave_idx_type [nrows]; + OCTAVE_LOCAL_BUFFER (octave_idx_type, tmp, nrows); - for (octave_idx_type i = 0; i < nperm; i++) + for (octave_idx_type i = 0; i < nrows; i++) { perm [i] = -1; tmp [i] = -1; @@ -512,10 +567,10 @@ for (octave_idx_type j = 0; j < ncols; j++) for (octave_idx_type i = a.cidx(j); i < a.cidx(j+1); i++) - perm [a.ridx(i)] = j; - + perm [a.ridx(i)] = j; + found = true; - for (octave_idx_type i = 0; i < nperm; i++) + for (octave_idx_type i = 0; i < nm; i++) if (perm[i] == -1) { found = false; @@ -527,12 +582,24 @@ } if (found) - for (octave_idx_type i = 0; i < nm; i++) - if (tmp[i] == -1) + { + octave_idx_type k = ncols; + for (octave_idx_type i = 0; i < nrows; i++) { - found = false; - break; + if (tmp[i] == -1) + { + if (k < nrows) + { + perm[k++] = i; + } + else + { + found = false; + break; + } + } } + } if (found) typ = SparseType::Permuted_Lower; @@ -542,6 +609,27 @@ nperm = 0; } } + else + { + delete [] perm; + nperm = 0; + } + } + + // XXX FIXME XXX + // Disable lower under-determined and upper over-determined problems + // as being detected, and force to treat as singular. As this seems + // to cause issues + if (((typ == SparseType::Lower || typ == SparseType::Permuted_Lower) + && nrows > ncols) || + ((typ == SparseType::Upper || typ == SparseType::Permuted_Upper) + && nrows < ncols)) + { + typ = SparseType::Rectangular; + if (typ == SparseType::Permuted_Upper || + typ == SparseType::Permuted_Lower) + delete [] perm; + nperm = 0; } if (typ == SparseType::Full && ncols != nrows)
--- a/liboctave/dSparse.cc +++ b/liboctave/dSparse.cc @@ -48,6 +48,13 @@ #include "oct-sort.h" +// Define whether to use a basic QR solver or one that uses a Dulmange +// Mendelsohn factorization to seperate the problem into under-determined, +// well-determined and over-determined parts and solves them seperately +#ifndef USE_QRSOLVE +#include "sparse-dmsolve.cc" +#endif + // Fortran functions we call. extern "C" { @@ -115,10 +122,10 @@ } SparseMatrix::SparseMatrix (const SparseBoolMatrix &a) - : MSparse<double> (a.rows (), a.cols (), a.nzmax ()) + : MSparse<double> (a.rows (), a.cols (), a.nnz ()) { octave_idx_type nc = cols (); - octave_idx_type nz = nzmax (); + octave_idx_type nz = a.nnz (); for (octave_idx_type i = 0; i < nc + 1; i++) cidx (i) = a.cidx (i); @@ -135,10 +142,10 @@ { octave_idx_type nr = rows (); octave_idx_type nc = cols (); - octave_idx_type nz = nzmax (); + octave_idx_type nz = nnz (); octave_idx_type nr_a = a.rows (); octave_idx_type nc_a = a.cols (); - octave_idx_type nz_a = a.nzmax (); + octave_idx_type nz_a = a.nnz (); if (nr != nr_a || nc != nc_a || nz != nz_a) return false; @@ -498,7 +505,7 @@ { octave_idx_type nr = a.rows (); octave_idx_type nc = a.cols (); - octave_idx_type nz = a.nzmax (); + octave_idx_type nz = a.nnz (); SparseMatrix r (nr, nc, nz); for (octave_idx_type i = 0; i < nc +1; i++) @@ -518,7 +525,7 @@ { octave_idx_type nr = a.rows (); octave_idx_type nc = a.cols (); - octave_idx_type nz = a.nzmax (); + octave_idx_type nz = a.nnz (); SparseMatrix r (nr, nc, nz); for (octave_idx_type i = 0; i < nc +1; i++) @@ -560,7 +567,7 @@ { octave_idx_type nr = x.rows (); octave_idx_type nc = x.cols (); - octave_idx_type nz = x.nzmax (); + octave_idx_type nz = x.nnz (); SparseMatrix retval (nr, nc, nz); @@ -613,7 +620,7 @@ gripe_nonconformant ("atan2", x_nr, x_nc, y_nr, y_nc); else { - r = SparseMatrix (x_nr, x_nc, (x.nzmax () + y.nzmax ())); + r = SparseMatrix (x_nr, x_nc, (x.nnz () + y.nnz ())); octave_idx_type jx = 0; r.cidx (0) = 0; @@ -790,7 +797,7 @@ if (typ == SparseType::Upper || typ == SparseType::Lower) { - octave_idx_type nz = nzmax (); + octave_idx_type nz = nnz (); octave_idx_type cx = 0; octave_idx_type nz2 = nz; retval = SparseMatrix (nr, nc, nz2); @@ -875,7 +882,7 @@ } else { - octave_idx_type nz = nzmax (); + octave_idx_type nz = nnz (); octave_idx_type cx = 0; octave_idx_type nz2 = nz; retval = SparseMatrix (nr, nc, nz2); @@ -1187,8 +1194,9 @@ } Matrix -SparseMatrix::dsolve (SparseType &mattype, const Matrix& b, octave_idx_type& err, - double& rcond, solve_singularity_handler) const +SparseMatrix::dsolve (SparseType &mattype, const Matrix& b, octave_idx_type& err, + double& rcond, solve_singularity_handler, + bool calc_cond) const { Matrix retval; @@ -1220,16 +1228,21 @@ for (octave_idx_type i = cidx(k); i < cidx(k+1); i++) retval(k,j) = b(ridx(i),j) / data (i); - double dmax = 0., dmin = octave_Inf; - for (octave_idx_type i = 0; i < nm; i++) - { - double tmp = fabs(data(i)); - if (tmp > dmax) - dmax = tmp; - if (tmp < dmin) - dmin = tmp; - } - rcond = dmin / dmax; + if (calc_cond) + { + double dmax = 0., dmin = octave_Inf; + for (octave_idx_type i = 0; i < nm; i++) + { + double tmp = fabs(data(i)); + if (tmp > dmax) + dmax = tmp; + if (tmp < dmin) + dmin = tmp; + } + rcond = dmin / dmax; + } + else + rcond = 1.; } else (*current_liboctave_error_handler) ("incorrect matrix type"); @@ -1240,8 +1253,8 @@ SparseMatrix SparseMatrix::dsolve (SparseType &mattype, const SparseMatrix& b, - octave_idx_type& err, - double& rcond, solve_singularity_handler) const + octave_idx_type& err, double& rcond, + solve_singularity_handler, bool calc_cond) const { SparseMatrix retval; @@ -1263,23 +1276,25 @@ typ == SparseType::Permuted_Diagonal) { octave_idx_type b_nc = b.cols (); - octave_idx_type b_nz = b.nzmax (); + octave_idx_type b_nz = b.nnz (); retval = SparseMatrix (nc, b_nc, b_nz); retval.xcidx(0) = 0; octave_idx_type ii = 0; if (typ == SparseType::Diagonal) - for (octave_idx_type j = 0; j < b.cols(); j++) + for (octave_idx_type j = 0; j < b_nc; j++) { for (octave_idx_type i = b.cidx(j); i < b.cidx(j+1); i++) { + if (b.ridx(i) >= nm) + break; retval.xridx (ii) = b.ridx(i); retval.xdata (ii++) = b.data(i) / data (b.ridx (i)); } retval.xcidx(j+1) = ii; } else - for (octave_idx_type j = 0; j < b.cols(); j++) + for (octave_idx_type j = 0; j < b_nc; j++) { for (octave_idx_type l = 0; l < nc; l++) for (octave_idx_type i = cidx(l); i < cidx(l+1); i++) @@ -1301,16 +1316,21 @@ retval.xcidx(j+1) = ii; } - double dmax = 0., dmin = octave_Inf; - for (octave_idx_type i = 0; i < nm; i++) - { - double tmp = fabs(data(i)); - if (tmp > dmax) - dmax = tmp; - if (tmp < dmin) - dmin = tmp; - } - rcond = dmin / dmax; + if (calc_cond) + { + double dmax = 0., dmin = octave_Inf; + for (octave_idx_type i = 0; i < nm; i++) + { + double tmp = fabs(data(i)); + if (tmp > dmax) + dmax = tmp; + if (tmp < dmin) + dmin = tmp; + } + rcond = dmin / dmax; + } + else + rcond = 1.; } else (*current_liboctave_error_handler) ("incorrect matrix type"); @@ -1321,8 +1341,8 @@ ComplexMatrix SparseMatrix::dsolve (SparseType &mattype, const ComplexMatrix& b, - octave_idx_type& err, - double& rcond, solve_singularity_handler) const + octave_idx_type& err, double& rcond, + solve_singularity_handler, bool calc_cond) const { ComplexMatrix retval; @@ -1354,16 +1374,21 @@ for (octave_idx_type i = cidx(k); i < cidx(k+1); i++) retval(k,j) = b(ridx(i),j) / data (i); - double dmax = 0., dmin = octave_Inf; - for (octave_idx_type i = 0; i < nm; i++) - { - double tmp = fabs(data(i)); - if (tmp > dmax) - dmax = tmp; - if (tmp < dmin) - dmin = tmp; - } - rcond = dmin / dmax; + if (calc_cond) + { + double dmax = 0., dmin = octave_Inf; + for (octave_idx_type i = 0; i < nm; i++) + { + double tmp = fabs(data(i)); + if (tmp > dmax) + dmax = tmp; + if (tmp < dmin) + dmin = tmp; + } + rcond = dmin / dmax; + } + else + rcond = 1.; } else (*current_liboctave_error_handler) ("incorrect matrix type"); @@ -1375,7 +1400,7 @@ SparseComplexMatrix SparseMatrix::dsolve (SparseType &mattype, const SparseComplexMatrix& b, octave_idx_type& err, double& rcond, - solve_singularity_handler) const + solve_singularity_handler, bool calc_cond) const { SparseComplexMatrix retval; @@ -1397,7 +1422,7 @@ typ == SparseType::Permuted_Diagonal) { octave_idx_type b_nc = b.cols (); - octave_idx_type b_nz = b.nzmax (); + octave_idx_type b_nz = b.nnz (); retval = SparseComplexMatrix (nc, b_nc, b_nz); retval.xcidx(0) = 0; @@ -1407,6 +1432,8 @@ { for (octave_idx_type i = b.cidx(j); i < b.cidx(j+1); i++) { + if (b.ridx(i) >= nm) + break; retval.xridx (ii) = b.ridx(i); retval.xdata (ii++) = b.data(i) / data (b.ridx (i)); } @@ -1435,16 +1462,21 @@ retval.xcidx(j+1) = ii; } - double dmax = 0., dmin = octave_Inf; - for (octave_idx_type i = 0; i < nm; i++) - { - double tmp = fabs(data(i)); - if (tmp > dmax) - dmax = tmp; - if (tmp < dmin) - dmin = tmp; - } - rcond = dmin / dmax; + if (calc_cond) + { + double dmax = 0., dmin = octave_Inf; + for (octave_idx_type i = 0; i < nm; i++) + { + double tmp = fabs(data(i)); + if (tmp > dmax) + dmax = tmp; + if (tmp < dmin) + dmin = tmp; + } + rcond = dmin / dmax; + } + else + rcond = 1.; } else (*current_liboctave_error_handler) ("incorrect matrix type"); @@ -1456,7 +1488,8 @@ Matrix SparseMatrix::utsolve (SparseType &mattype, const Matrix& b, octave_idx_type& err, double& rcond, - solve_singularity_handler sing_handler) const + solve_singularity_handler sing_handler, + bool calc_cond) const { Matrix retval; @@ -1480,16 +1513,19 @@ double anorm = 0.; double ainvnorm = 0.; octave_idx_type b_nc = b.cols (); - rcond = 0.; - - // Calculate the 1-norm of matrix for rcond calculation - for (octave_idx_type j = 0; j < nc; j++) - { - double atmp = 0.; - for (octave_idx_type i = cidx(j); i < cidx(j+1); i++) - atmp += fabs(data(i)); - if (atmp > anorm) - anorm = atmp; + rcond = 1.; + + if (calc_cond) + { + // Calculate the 1-norm of matrix for rcond calculation + for (octave_idx_type j = 0; j < nc; j++) + { + double atmp = 0.; + for (octave_idx_type i = cidx(j); i < cidx(j+1); i++) + atmp += fabs(data(i)); + if (atmp > anorm) + anorm = atmp; + } } if (typ == SparseType::Permuted_Upper) @@ -1511,7 +1547,8 @@ if (work[k] != 0.) { - if (ridx(cidx(kidx+1)-1) != k) + if (ridx(cidx(kidx+1)-1) != k || + data(cidx(kidx+1)-1) == 0.) { err = -2; goto triangular_error; @@ -1532,37 +1569,42 @@ retval.xelem (perm[i], j) = work[i]; } - // Calculation of 1-norm of inv(*this) - for (octave_idx_type i = 0; i < nm; i++) - work[i] = 0.; - - for (octave_idx_type j = 0; j < nr; j++) - { - work[j] = 1.; - - for (octave_idx_type k = j; k >= 0; k--) + if (calc_cond) + { + // Calculation of 1-norm of inv(*this) + for (octave_idx_type i = 0; i < nm; i++) + work[i] = 0.; + + for (octave_idx_type j = 0; j < nr; j++) { - octave_idx_type iidx = perm[k]; - - if (work[k] != 0.) + work[j] = 1.; + + for (octave_idx_type k = j; k >= 0; k--) { - double tmp = work[k] / data(cidx(iidx+1)-1); - work[k] = tmp; - for (octave_idx_type i = cidx(iidx); i < cidx(iidx+1)-1; i++) + octave_idx_type iidx = perm[k]; + + if (work[k] != 0.) { - octave_idx_type idx2 = ridx(i); - work[idx2] = work[idx2] - tmp * data(i); + double tmp = work[k] / data(cidx(iidx+1)-1); + work[k] = tmp; + for (octave_idx_type i = cidx(iidx); + i < cidx(iidx+1)-1; i++) + { + octave_idx_type idx2 = ridx(i); + work[idx2] = work[idx2] - tmp * data(i); + } } } + double atmp = 0; + for (octave_idx_type i = 0; i < j+1; i++) + { + atmp += fabs(work[i]); + work[i] = 0.; + } + if (atmp > ainvnorm) + ainvnorm = atmp; } - double atmp = 0; - for (octave_idx_type i = 0; i < j+1; i++) - { - atmp += fabs(work[i]); - work[i] = 0.; - } - if (atmp > ainvnorm) - ainvnorm = atmp; + rcond = 1. / ainvnorm / anorm; } } else @@ -1581,7 +1623,8 @@ { if (work[k] != 0.) { - if (ridx(cidx(k+1)-1) != k) + if (ridx(cidx(k+1)-1) != k || + data(cidx(k+1)-1) == 0.) { err = -2; goto triangular_error; @@ -1601,45 +1644,50 @@ retval.xelem (i, j) = work[i]; } - // Calculation of 1-norm of inv(*this) - for (octave_idx_type i = 0; i < nm; i++) - work[i] = 0.; - - for (octave_idx_type j = 0; j < nr; j++) - { - work[j] = 1.; - - for (octave_idx_type k = j; k >= 0; k--) + if (calc_cond) + { + // Calculation of 1-norm of inv(*this) + for (octave_idx_type i = 0; i < nm; i++) + work[i] = 0.; + + for (octave_idx_type j = 0; j < nr; j++) { - if (work[k] != 0.) + work[j] = 1.; + + for (octave_idx_type k = j; k >= 0; k--) { - double tmp = work[k] / data(cidx(k+1)-1); - work[k] = tmp; - for (octave_idx_type i = cidx(k); i < cidx(k+1)-1; i++) + if (work[k] != 0.) { - octave_idx_type iidx = ridx(i); - work[iidx] = work[iidx] - tmp * data(i); + double tmp = work[k] / data(cidx(k+1)-1); + work[k] = tmp; + for (octave_idx_type i = cidx(k); i < cidx(k+1)-1; i++) + { + octave_idx_type iidx = ridx(i); + work[iidx] = work[iidx] - tmp * data(i); + } } } - } - double atmp = 0; - for (octave_idx_type i = 0; i < j+1; i++) - { - atmp += fabs(work[i]); - work[i] = 0.; + double atmp = 0; + for (octave_idx_type i = 0; i < j+1; i++) + { + atmp += fabs(work[i]); + work[i] = 0.; + } + if (atmp > ainvnorm) + ainvnorm = atmp; } - if (atmp > ainvnorm) - ainvnorm = atmp; - } - } - - rcond = 1. / ainvnorm / anorm; + rcond = 1. / ainvnorm / anorm; + } + } triangular_error: if (err != 0) { if (sing_handler) - sing_handler (rcond); + { + sing_handler (rcond); + mattype.mark_as_rectangular (); + } else (*current_liboctave_error_handler) ("SparseMatrix::solve matrix singular to machine precision, rcond = %g", @@ -1653,7 +1701,10 @@ err = -2; if (sing_handler) - sing_handler (rcond); + { + sing_handler (rcond); + mattype.mark_as_rectangular (); + } else (*current_liboctave_error_handler) ("matrix singular to machine precision, rcond = %g", @@ -1670,7 +1721,8 @@ SparseMatrix SparseMatrix::utsolve (SparseType &mattype, const SparseMatrix& b, octave_idx_type& err, double& rcond, - solve_singularity_handler sing_handler) const + solve_singularity_handler sing_handler, + bool calc_cond) const { SparseMatrix retval; @@ -1693,20 +1745,23 @@ { double anorm = 0.; double ainvnorm = 0.; - rcond = 0.; - - // Calculate the 1-norm of matrix for rcond calculation - for (octave_idx_type j = 0; j < nc; j++) - { - double atmp = 0.; - for (octave_idx_type i = cidx(j); i < cidx(j+1); i++) - atmp += fabs(data(i)); - if (atmp > anorm) - anorm = atmp; + rcond = 1.; + + if (calc_cond) + { + // Calculate the 1-norm of matrix for rcond calculation + for (octave_idx_type j = 0; j < nc; j++) + { + double atmp = 0.; + for (octave_idx_type i = cidx(j); i < cidx(j+1); i++) + atmp += fabs(data(i)); + if (atmp > anorm) + anorm = atmp; + } } octave_idx_type b_nc = b.cols (); - octave_idx_type b_nz = b.nzmax (); + octave_idx_type b_nz = b.nnz (); retval = SparseMatrix (nc, b_nc, b_nz); retval.xcidx(0) = 0; octave_idx_type ii = 0; @@ -1734,7 +1789,8 @@ if (work[k] != 0.) { - if (ridx(cidx(kidx+1)-1) != k) + if (ridx(cidx(kidx+1)-1) != k || + data(cidx(kidx+1)-1) == 0.) { err = -2; goto triangular_error; @@ -1777,37 +1833,42 @@ retval.maybe_compress (); - // Calculation of 1-norm of inv(*this) - for (octave_idx_type i = 0; i < nm; i++) - work[i] = 0.; - - for (octave_idx_type j = 0; j < nr; j++) - { - work[j] = 1.; - - for (octave_idx_type k = j; k >= 0; k--) + if (calc_cond) + { + // Calculation of 1-norm of inv(*this) + for (octave_idx_type i = 0; i < nm; i++) + work[i] = 0.; + + for (octave_idx_type j = 0; j < nr; j++) { - octave_idx_type iidx = perm[k]; - - if (work[k] != 0.) + work[j] = 1.; + + for (octave_idx_type k = j; k >= 0; k--) { - double tmp = work[k] / data(cidx(iidx+1)-1); - work[k] = tmp; - for (octave_idx_type i = cidx(iidx); i < cidx(iidx+1)-1; i++) + octave_idx_type iidx = perm[k]; + + if (work[k] != 0.) { - octave_idx_type idx2 = ridx(i); - work[idx2] = work[idx2] - tmp * data(i); + double tmp = work[k] / data(cidx(iidx+1)-1); + work[k] = tmp; + for (octave_idx_type i = cidx(iidx); + i < cidx(iidx+1)-1; i++) + { + octave_idx_type idx2 = ridx(i); + work[idx2] = work[idx2] - tmp * data(i); + } } } + double atmp = 0; + for (octave_idx_type i = 0; i < j+1; i++) + { + atmp += fabs(work[i]); + work[i] = 0.; + } + if (atmp > ainvnorm) + ainvnorm = atmp; } - double atmp = 0; - for (octave_idx_type i = 0; i < j+1; i++) - { - atmp += fabs(work[i]); - work[i] = 0.; - } - if (atmp > ainvnorm) - ainvnorm = atmp; + rcond = 1. / ainvnorm / anorm; } } else @@ -1825,7 +1886,8 @@ { if (work[k] != 0.) { - if (ridx(cidx(k+1)-1) != k) + if (ridx(cidx(k+1)-1) != k || + data(cidx(k+1)-1) == 0.) { err = -2; goto triangular_error; @@ -1867,45 +1929,51 @@ retval.maybe_compress (); - // Calculation of 1-norm of inv(*this) - for (octave_idx_type i = 0; i < nm; i++) - work[i] = 0.; - - for (octave_idx_type j = 0; j < nr; j++) - { - work[j] = 1.; - - for (octave_idx_type k = j; k >= 0; k--) + if (calc_cond) + { + // Calculation of 1-norm of inv(*this) + for (octave_idx_type i = 0; i < nm; i++) + work[i] = 0.; + + for (octave_idx_type j = 0; j < nr; j++) { - if (work[k] != 0.) + work[j] = 1.; + + for (octave_idx_type k = j; k >= 0; k--) { - double tmp = work[k] / data(cidx(k+1)-1); - work[k] = tmp; - for (octave_idx_type i = cidx(k); i < cidx(k+1)-1; i++) + if (work[k] != 0.) { - octave_idx_type iidx = ridx(i); - work[iidx] = work[iidx] - tmp * data(i); + double tmp = work[k] / data(cidx(k+1)-1); + work[k] = tmp; + for (octave_idx_type i = cidx(k); + i < cidx(k+1)-1; i++) + { + octave_idx_type iidx = ridx(i); + work[iidx] = work[iidx] - tmp * data(i); + } } } - } - double atmp = 0; - for (octave_idx_type i = 0; i < j+1; i++) - { - atmp += fabs(work[i]); - work[i] = 0.; + double atmp = 0; + for (octave_idx_type i = 0; i < j+1; i++) + { + atmp += fabs(work[i]); + work[i] = 0.; + } + if (atmp > ainvnorm) + ainvnorm = atmp; } - if (atmp > ainvnorm) - ainvnorm = atmp; - } - } - - rcond = 1. / ainvnorm / anorm; + rcond = 1. / ainvnorm / anorm; + } + } triangular_error: if (err != 0) { if (sing_handler) - sing_handler (rcond); + { + sing_handler (rcond); + mattype.mark_as_rectangular (); + } else (*current_liboctave_error_handler) ("SparseMatrix::solve matrix singular to machine precision, rcond = %g", @@ -1919,7 +1987,10 @@ err = -2; if (sing_handler) - sing_handler (rcond); + { + sing_handler (rcond); + mattype.mark_as_rectangular (); + } else (*current_liboctave_error_handler) ("matrix singular to machine precision, rcond = %g", @@ -1935,7 +2006,8 @@ ComplexMatrix SparseMatrix::utsolve (SparseType &mattype, const ComplexMatrix& b, octave_idx_type& err, double& rcond, - solve_singularity_handler sing_handler) const + solve_singularity_handler sing_handler, + bool calc_cond) const { ComplexMatrix retval; @@ -1959,16 +2031,19 @@ double anorm = 0.; double ainvnorm = 0.; octave_idx_type b_nc = b.cols (); - rcond = 0.; - - // Calculate the 1-norm of matrix for rcond calculation - for (octave_idx_type j = 0; j < nc; j++) - { - double atmp = 0.; - for (octave_idx_type i = cidx(j); i < cidx(j+1); i++) - atmp += fabs(data(i)); - if (atmp > anorm) - anorm = atmp; + rcond = 1.; + + if (calc_cond) + { + // Calculate the 1-norm of matrix for rcond calculation + for (octave_idx_type j = 0; j < nc; j++) + { + double atmp = 0.; + for (octave_idx_type i = cidx(j); i < cidx(j+1); i++) + atmp += fabs(data(i)); + if (atmp > anorm) + anorm = atmp; + } } if (typ == SparseType::Permuted_Upper) @@ -1990,7 +2065,8 @@ if (cwork[k] != 0.) { - if (ridx(cidx(kidx+1)-1) != k) + if (ridx(cidx(kidx+1)-1) != k || + data(cidx(kidx+1)-1) == 0.) { err = -2; goto triangular_error; @@ -2011,38 +2087,43 @@ retval.xelem (perm[i], j) = cwork[i]; } - // Calculation of 1-norm of inv(*this) - OCTAVE_LOCAL_BUFFER (double, work, nm); - for (octave_idx_type i = 0; i < nm; i++) - work[i] = 0.; - - for (octave_idx_type j = 0; j < nr; j++) - { - work[j] = 1.; - - for (octave_idx_type k = j; k >= 0; k--) + if (calc_cond) + { + // Calculation of 1-norm of inv(*this) + OCTAVE_LOCAL_BUFFER (double, work, nm); + for (octave_idx_type i = 0; i < nm; i++) + work[i] = 0.; + + for (octave_idx_type j = 0; j < nr; j++) { - octave_idx_type iidx = perm[k]; - - if (work[k] != 0.) + work[j] = 1.; + + for (octave_idx_type k = j; k >= 0; k--) { - double tmp = work[k] / data(cidx(iidx+1)-1); - work[k] = tmp; - for (octave_idx_type i = cidx(iidx); i < cidx(iidx+1)-1; i++) + octave_idx_type iidx = perm[k]; + + if (work[k] != 0.) { - octave_idx_type idx2 = ridx(i); - work[idx2] = work[idx2] - tmp * data(i); + double tmp = work[k] / data(cidx(iidx+1)-1); + work[k] = tmp; + for (octave_idx_type i = cidx(iidx); + i < cidx(iidx+1)-1; i++) + { + octave_idx_type idx2 = ridx(i); + work[idx2] = work[idx2] - tmp * data(i); + } } } + double atmp = 0; + for (octave_idx_type i = 0; i < j+1; i++) + { + atmp += fabs(work[i]); + work[i] = 0.; + } + if (atmp > ainvnorm) + ainvnorm = atmp; } - double atmp = 0; - for (octave_idx_type i = 0; i < j+1; i++) - { - atmp += fabs(work[i]); - work[i] = 0.; - } - if (atmp > ainvnorm) - ainvnorm = atmp; + rcond = 1. / ainvnorm / anorm; } } else @@ -2061,7 +2142,8 @@ { if (cwork[k] != 0.) { - if (ridx(cidx(k+1)-1) != k) + if (ridx(cidx(k+1)-1) != k || + data(cidx(k+1)-1) == 0.) { err = -2; goto triangular_error; @@ -2081,46 +2163,52 @@ retval.xelem (i, j) = cwork[i]; } - // Calculation of 1-norm of inv(*this) - OCTAVE_LOCAL_BUFFER (double, work, nm); - for (octave_idx_type i = 0; i < nm; i++) - work[i] = 0.; - - for (octave_idx_type j = 0; j < nr; j++) - { - work[j] = 1.; - - for (octave_idx_type k = j; k >= 0; k--) + if (calc_cond) + { + // Calculation of 1-norm of inv(*this) + OCTAVE_LOCAL_BUFFER (double, work, nm); + for (octave_idx_type i = 0; i < nm; i++) + work[i] = 0.; + + for (octave_idx_type j = 0; j < nr; j++) { - if (work[k] != 0.) + work[j] = 1.; + + for (octave_idx_type k = j; k >= 0; k--) { - double tmp = work[k] / data(cidx(k+1)-1); - work[k] = tmp; - for (octave_idx_type i = cidx(k); i < cidx(k+1)-1; i++) + if (work[k] != 0.) { - octave_idx_type iidx = ridx(i); - work[iidx] = work[iidx] - tmp * data(i); + double tmp = work[k] / data(cidx(k+1)-1); + work[k] = tmp; + for (octave_idx_type i = cidx(k); + i < cidx(k+1)-1; i++) + { + octave_idx_type iidx = ridx(i); + work[iidx] = work[iidx] - tmp * data(i); + } } } - } - double atmp = 0; - for (octave_idx_type i = 0; i < j+1; i++) - { - atmp += fabs(work[i]); - work[i] = 0.; + double atmp = 0; + for (octave_idx_type i = 0; i < j+1; i++) + { + atmp += fabs(work[i]); + work[i] = 0.; + } + if (atmp > ainvnorm) + ainvnorm = atmp; } - if (atmp > ainvnorm) - ainvnorm = atmp; - } - } - - rcond = 1. / ainvnorm / anorm; + rcond = 1. / ainvnorm / anorm; + } + } triangular_error: if (err != 0) { if (sing_handler) - sing_handler (rcond); + { + sing_handler (rcond); + mattype.mark_as_rectangular (); + } else (*current_liboctave_error_handler) ("SparseMatrix::solve matrix singular to machine precision, rcond = %g", @@ -2134,7 +2222,10 @@ err = -2; if (sing_handler) - sing_handler (rcond); + { + sing_handler (rcond); + mattype.mark_as_rectangular (); + } else (*current_liboctave_error_handler) ("matrix singular to machine precision, rcond = %g", @@ -2151,7 +2242,8 @@ SparseComplexMatrix SparseMatrix::utsolve (SparseType &mattype, const SparseComplexMatrix& b, octave_idx_type& err, double& rcond, - solve_singularity_handler sing_handler) const + solve_singularity_handler sing_handler, + bool calc_cond) const { SparseComplexMatrix retval; @@ -2174,20 +2266,23 @@ { double anorm = 0.; double ainvnorm = 0.; - rcond = 0.; - - // Calculate the 1-norm of matrix for rcond calculation - for (octave_idx_type j = 0; j < nc; j++) - { - double atmp = 0.; - for (octave_idx_type i = cidx(j); i < cidx(j+1); i++) - atmp += fabs(data(i)); - if (atmp > anorm) - anorm = atmp; + rcond = 1.; + + if (calc_cond) + { + // Calculate the 1-norm of matrix for rcond calculation + for (octave_idx_type j = 0; j < nc; j++) + { + double atmp = 0.; + for (octave_idx_type i = cidx(j); i < cidx(j+1); i++) + atmp += fabs(data(i)); + if (atmp > anorm) + anorm = atmp; + } } octave_idx_type b_nc = b.cols (); - octave_idx_type b_nz = b.nzmax (); + octave_idx_type b_nz = b.nnz (); retval = SparseComplexMatrix (nc, b_nc, b_nz); retval.xcidx(0) = 0; octave_idx_type ii = 0; @@ -2215,7 +2310,8 @@ if (cwork[k] != 0.) { - if (ridx(cidx(kidx+1)-1) != k) + if (ridx(cidx(kidx+1)-1) != k || + data(cidx(kidx+1)-1) == 0.) { err = -2; goto triangular_error; @@ -2258,38 +2354,43 @@ retval.maybe_compress (); - // Calculation of 1-norm of inv(*this) - OCTAVE_LOCAL_BUFFER (double, work, nm); - for (octave_idx_type i = 0; i < nm; i++) - work[i] = 0.; - - for (octave_idx_type j = 0; j < nr; j++) - { - work[j] = 1.; - - for (octave_idx_type k = j; k >= 0; k--) + if (calc_cond) + { + // Calculation of 1-norm of inv(*this) + OCTAVE_LOCAL_BUFFER (double, work, nm); + for (octave_idx_type i = 0; i < nm; i++) + work[i] = 0.; + + for (octave_idx_type j = 0; j < nr; j++) { - octave_idx_type iidx = perm[k]; - - if (work[k] != 0.) + work[j] = 1.; + + for (octave_idx_type k = j; k >= 0; k--) { - double tmp = work[k] / data(cidx(iidx+1)-1); - work[k] = tmp; - for (octave_idx_type i = cidx(iidx); i < cidx(iidx+1)-1; i++) + octave_idx_type iidx = perm[k]; + + if (work[k] != 0.) { - octave_idx_type idx2 = ridx(i); - work[idx2] = work[idx2] - tmp * data(i); + double tmp = work[k] / data(cidx(iidx+1)-1); + work[k] = tmp; + for (octave_idx_type i = cidx(iidx); + i < cidx(iidx+1)-1; i++) + { + octave_idx_type idx2 = ridx(i); + work[idx2] = work[idx2] - tmp * data(i); + } } } + double atmp = 0; + for (octave_idx_type i = 0; i < j+1; i++) + { + atmp += fabs(work[i]); + work[i] = 0.; + } + if (atmp > ainvnorm) + ainvnorm = atmp; } - double atmp = 0; - for (octave_idx_type i = 0; i < j+1; i++) - { - atmp += fabs(work[i]); - work[i] = 0.; - } - if (atmp > ainvnorm) - ainvnorm = atmp; + rcond = 1. / ainvnorm / anorm; } } else @@ -2307,7 +2408,8 @@ { if (cwork[k] != 0.) { - if (ridx(cidx(k+1)-1) != k) + if (ridx(cidx(k+1)-1) != k || + data(cidx(k+1)-1) == 0.) { err = -2; goto triangular_error; @@ -2349,46 +2451,52 @@ retval.maybe_compress (); - // Calculation of 1-norm of inv(*this) - OCTAVE_LOCAL_BUFFER (double, work, nm); - for (octave_idx_type i = 0; i < nm; i++) - work[i] = 0.; - - for (octave_idx_type j = 0; j < nr; j++) - { - work[j] = 1.; - - for (octave_idx_type k = j; k >= 0; k--) + if (calc_cond) + { + // Calculation of 1-norm of inv(*this) + OCTAVE_LOCAL_BUFFER (double, work, nm); + for (octave_idx_type i = 0; i < nm; i++) + work[i] = 0.; + + for (octave_idx_type j = 0; j < nr; j++) { - if (work[k] != 0.) + work[j] = 1.; + + for (octave_idx_type k = j; k >= 0; k--) { - double tmp = work[k] / data(cidx(k+1)-1); - work[k] = tmp; - for (octave_idx_type i = cidx(k); i < cidx(k+1)-1; i++) + if (work[k] != 0.) { - octave_idx_type iidx = ridx(i); - work[iidx] = work[iidx] - tmp * data(i); + double tmp = work[k] / data(cidx(k+1)-1); + work[k] = tmp; + for (octave_idx_type i = cidx(k); + i < cidx(k+1)-1; i++) + { + octave_idx_type iidx = ridx(i); + work[iidx] = work[iidx] - tmp * data(i); + } } } - } - double atmp = 0; - for (octave_idx_type i = 0; i < j+1; i++) - { - atmp += fabs(work[i]); - work[i] = 0.; + double atmp = 0; + for (octave_idx_type i = 0; i < j+1; i++) + { + atmp += fabs(work[i]); + work[i] = 0.; + } + if (atmp > ainvnorm) + ainvnorm = atmp; } - if (atmp > ainvnorm) - ainvnorm = atmp; - } - } - - rcond = 1. / ainvnorm / anorm; + rcond = 1. / ainvnorm / anorm; + } + } triangular_error: if (err != 0) { if (sing_handler) - sing_handler (rcond); + { + sing_handler (rcond); + mattype.mark_as_rectangular (); + } else (*current_liboctave_error_handler) ("SparseMatrix::solve matrix singular to machine precision, rcond = %g", @@ -2402,7 +2510,10 @@ err = -2; if (sing_handler) - sing_handler (rcond); + { + sing_handler (rcond); + mattype.mark_as_rectangular (); + } else (*current_liboctave_error_handler) ("matrix singular to machine precision, rcond = %g", @@ -2419,7 +2530,8 @@ Matrix SparseMatrix::ltsolve (SparseType &mattype, const Matrix& b, octave_idx_type& err, double& rcond, - solve_singularity_handler sing_handler) const + solve_singularity_handler sing_handler, + bool calc_cond) const { Matrix retval; @@ -2443,16 +2555,19 @@ double anorm = 0.; double ainvnorm = 0.; octave_idx_type b_nc = b.cols (); - rcond = 0.; - - // Calculate the 1-norm of matrix for rcond calculation - for (octave_idx_type j = 0; j < nc; j++) - { - double atmp = 0.; - for (octave_idx_type i = cidx(j); i < cidx(j+1); i++) - atmp += fabs(data(i)); - if (atmp > anorm) - anorm = atmp; + rcond = 1.; + + if (calc_cond) + { + // Calculate the 1-norm of matrix for rcond calculation + for (octave_idx_type j = 0; j < nc; j++) + { + double atmp = 0.; + for (octave_idx_type i = cidx(j); i < cidx(j+1); i++) + atmp += fabs(data(i)); + if (atmp > anorm) + anorm = atmp; + } } if (typ == SparseType::Permuted_Lower) @@ -2483,7 +2598,7 @@ mini = i; } - if (minr != k) + if (minr != k || data(mini) == 0) { err = -2; goto triangular_error; @@ -2506,49 +2621,55 @@ retval (i, j) = work[i]; } - // Calculation of 1-norm of inv(*this) - for (octave_idx_type i = 0; i < nm; i++) - work[i] = 0.; - - for (octave_idx_type j = 0; j < nr; j++) - { - work[j] = 1.; - - for (octave_idx_type k = 0; k < nc; k++) + if (calc_cond) + { + // Calculation of 1-norm of inv(*this) + for (octave_idx_type i = 0; i < nm; i++) + work[i] = 0.; + + for (octave_idx_type j = 0; j < nr; j++) { - if (work[k] != 0.) + work[j] = 1.; + + for (octave_idx_type k = 0; k < nc; k++) { - octave_idx_type minr = nr; - octave_idx_type mini = 0; - - for (octave_idx_type i = cidx(k); i < cidx(k+1); i++) - if (perm[ridx(i)] < minr) - { - minr = perm[ridx(i)]; - mini = i; - } - - double tmp = work[k] / data(mini); - work[k] = tmp; - for (octave_idx_type i = cidx(k); i < cidx(k+1); i++) + if (work[k] != 0.) { - if (i == mini) - continue; - - octave_idx_type iidx = perm[ridx(i)]; - work[iidx] = work[iidx] - tmp * data(i); + octave_idx_type minr = nr; + octave_idx_type mini = 0; + + for (octave_idx_type i = cidx(k); + i < cidx(k+1); i++) + if (perm[ridx(i)] < minr) + { + minr = perm[ridx(i)]; + mini = i; + } + + double tmp = work[k] / data(mini); + work[k] = tmp; + for (octave_idx_type i = cidx(k); + i < cidx(k+1); i++) + { + if (i == mini) + continue; + + octave_idx_type iidx = perm[ridx(i)]; + work[iidx] = work[iidx] - tmp * data(i); + } } } + + double atmp = 0; + for (octave_idx_type i = j; i < nc; i++) + { + atmp += fabs(work[i]); + work[i] = 0.; + } + if (atmp > ainvnorm) + ainvnorm = atmp; } - - double atmp = 0; - for (octave_idx_type i = j; i < nc; i++) - { - atmp += fabs(work[i]); - work[i] = 0.; - } - if (atmp > ainvnorm) - ainvnorm = atmp; + rcond = 1. / ainvnorm / anorm; } } else @@ -2566,7 +2687,8 @@ { if (work[k] != 0.) { - if (ridx(cidx(k)) != k) + if (ridx(cidx(k)) != k || + data(cidx(k)) == 0.) { err = -2; goto triangular_error; @@ -2587,47 +2709,52 @@ retval.xelem (i, j) = work[i]; } - // Calculation of 1-norm of inv(*this) - for (octave_idx_type i = 0; i < nm; i++) - work[i] = 0.; - - for (octave_idx_type j = 0; j < nr; j++) - { - work[j] = 1.; - - for (octave_idx_type k = j; k < nc; k++) + if (calc_cond) + { + // Calculation of 1-norm of inv(*this) + for (octave_idx_type i = 0; i < nm; i++) + work[i] = 0.; + + for (octave_idx_type j = 0; j < nr; j++) { - - if (work[k] != 0.) + work[j] = 1.; + + for (octave_idx_type k = j; k < nc; k++) { - double tmp = work[k] / data(cidx(k)); - work[k] = tmp; - for (octave_idx_type i = cidx(k)+1; i < cidx(k+1); i++) + + if (work[k] != 0.) { - octave_idx_type iidx = ridx(i); - work[iidx] = work[iidx] - tmp * data(i); + double tmp = work[k] / data(cidx(k)); + work[k] = tmp; + for (octave_idx_type i = cidx(k)+1; + i < cidx(k+1); i++) + { + octave_idx_type iidx = ridx(i); + work[iidx] = work[iidx] - tmp * data(i); + } } } - } - double atmp = 0; - for (octave_idx_type i = j; i < nc; i++) - { - atmp += fabs(work[i]); - work[i] = 0.; + double atmp = 0; + for (octave_idx_type i = j; i < nc; i++) + { + atmp += fabs(work[i]); + work[i] = 0.; + } + if (atmp > ainvnorm) + ainvnorm = atmp; } - if (atmp > ainvnorm) - ainvnorm = atmp; - } - - } - - rcond = 1. / ainvnorm / anorm; + rcond = 1. / ainvnorm / anorm; + } + } triangular_error: if (err != 0) { if (sing_handler) - sing_handler (rcond); + { + sing_handler (rcond); + mattype.mark_as_rectangular (); + } else (*current_liboctave_error_handler) ("SparseMatrix::solve matrix singular to machine precision, rcond = %g", @@ -2641,7 +2768,10 @@ err = -2; if (sing_handler) - sing_handler (rcond); + { + sing_handler (rcond); + mattype.mark_as_rectangular (); + } else (*current_liboctave_error_handler) ("matrix singular to machine precision, rcond = %g", @@ -2658,7 +2788,8 @@ SparseMatrix SparseMatrix::ltsolve (SparseType &mattype, const SparseMatrix& b, octave_idx_type& err, double& rcond, - solve_singularity_handler sing_handler) const + solve_singularity_handler sing_handler, + bool calc_cond) const { SparseMatrix retval; @@ -2681,29 +2812,31 @@ { double anorm = 0.; double ainvnorm = 0.; - rcond = 0.; - - // Calculate the 1-norm of matrix for rcond calculation - for (octave_idx_type j = 0; j < nc; j++) - { - double atmp = 0.; - for (octave_idx_type i = cidx(j); i < cidx(j+1); i++) - atmp += fabs(data(i)); - if (atmp > anorm) - anorm = atmp; - } - - octave_idx_type b_nr = b.rows (); + rcond = 1.; + + if (calc_cond) + { + // Calculate the 1-norm of matrix for rcond calculation + for (octave_idx_type j = 0; j < nc; j++) + { + double atmp = 0.; + for (octave_idx_type i = cidx(j); i < cidx(j+1); i++) + atmp += fabs(data(i)); + if (atmp > anorm) + anorm = atmp; + } + } + octave_idx_type b_nc = b.cols (); - octave_idx_type b_nz = b.nzmax (); - retval = SparseMatrix (b_nr, b_nc, b_nz); + octave_idx_type b_nz = b.nnz (); + retval = SparseMatrix (nc, b_nc, b_nz); retval.xcidx(0) = 0; octave_idx_type ii = 0; octave_idx_type x_nz = b_nz; if (typ == SparseType::Permuted_Lower) { - OCTAVE_LOCAL_BUFFER (double, work, nr); + OCTAVE_LOCAL_BUFFER (double, work, nm); octave_idx_type *perm = mattype.triangular_perm (); for (octave_idx_type j = 0; j < b_nc; j++) @@ -2727,7 +2860,7 @@ mini = i; } - if (minr != k) + if (minr != k || data(mini) == 0) { err = -2; goto triangular_error; @@ -2772,54 +2905,60 @@ retval.maybe_compress (); - // Calculation of 1-norm of inv(*this) - for (octave_idx_type i = 0; i < nm; i++) - work[i] = 0.; - - for (octave_idx_type j = 0; j < nr; j++) - { - work[j] = 1.; - - for (octave_idx_type k = 0; k < nc; k++) + if (calc_cond) + { + // Calculation of 1-norm of inv(*this) + for (octave_idx_type i = 0; i < nm; i++) + work[i] = 0.; + + for (octave_idx_type j = 0; j < nr; j++) { - if (work[k] != 0.) + work[j] = 1.; + + for (octave_idx_type k = 0; k < nc; k++) { - octave_idx_type minr = nr; - octave_idx_type mini = 0; - - for (octave_idx_type i = cidx(k); i < cidx(k+1); i++) - if (perm[ridx(i)] < minr) - { - minr = perm[ridx(i)]; - mini = i; - } - - double tmp = work[k] / data(mini); - work[k] = tmp; - for (octave_idx_type i = cidx(k); i < cidx(k+1); i++) + if (work[k] != 0.) { - if (i == mini) - continue; - - octave_idx_type iidx = perm[ridx(i)]; - work[iidx] = work[iidx] - tmp * data(i); + octave_idx_type minr = nr; + octave_idx_type mini = 0; + + for (octave_idx_type i = cidx(k); + i < cidx(k+1); i++) + if (perm[ridx(i)] < minr) + { + minr = perm[ridx(i)]; + mini = i; + } + + double tmp = work[k] / data(mini); + work[k] = tmp; + for (octave_idx_type i = cidx(k); + i < cidx(k+1); i++) + { + if (i == mini) + continue; + + octave_idx_type iidx = perm[ridx(i)]; + work[iidx] = work[iidx] - tmp * data(i); + } } } + + double atmp = 0; + for (octave_idx_type i = j; i < nr; i++) + { + atmp += fabs(work[i]); + work[i] = 0.; + } + if (atmp > ainvnorm) + ainvnorm = atmp; } - - double atmp = 0; - for (octave_idx_type i = j; i < nr; i++) - { - atmp += fabs(work[i]); - work[i] = 0.; - } - if (atmp > ainvnorm) - ainvnorm = atmp; + rcond = 1. / ainvnorm / anorm; } } else { - OCTAVE_LOCAL_BUFFER (double, work, nr); + OCTAVE_LOCAL_BUFFER (double, work, nm); for (octave_idx_type j = 0; j < b_nc; j++) { @@ -2832,7 +2971,8 @@ { if (work[k] != 0.) { - if (ridx(cidx(k)) != k) + if (ridx(cidx(k)) != k || + data(cidx(k)) == 0.) { err = -2; goto triangular_error; @@ -2874,47 +3014,52 @@ retval.maybe_compress (); - // Calculation of 1-norm of inv(*this) - for (octave_idx_type i = 0; i < nm; i++) - work[i] = 0.; - - for (octave_idx_type j = 0; j < nr; j++) - { - work[j] = 1.; - - for (octave_idx_type k = j; k < nc; k++) + if (calc_cond) + { + // Calculation of 1-norm of inv(*this) + for (octave_idx_type i = 0; i < nm; i++) + work[i] = 0.; + + for (octave_idx_type j = 0; j < nr; j++) { - - if (work[k] != 0.) + work[j] = 1.; + + for (octave_idx_type k = j; k < nc; k++) { - double tmp = work[k] / data(cidx(k)); - work[k] = tmp; - for (octave_idx_type i = cidx(k)+1; i < cidx(k+1); i++) + + if (work[k] != 0.) { - octave_idx_type iidx = ridx(i); - work[iidx] = work[iidx] - tmp * data(i); + double tmp = work[k] / data(cidx(k)); + work[k] = tmp; + for (octave_idx_type i = cidx(k)+1; + i < cidx(k+1); i++) + { + octave_idx_type iidx = ridx(i); + work[iidx] = work[iidx] - tmp * data(i); + } } } - } - double atmp = 0; - for (octave_idx_type i = j; i < nc; i++) - { - atmp += fabs(work[i]); - work[i] = 0.; + double atmp = 0; + for (octave_idx_type i = j; i < nc; i++) + { + atmp += fabs(work[i]); + work[i] = 0.; + } + if (atmp > ainvnorm) + ainvnorm = atmp; } - if (atmp > ainvnorm) - ainvnorm = atmp; - } - - } - - rcond = 1. / ainvnorm / anorm; + rcond = 1. / ainvnorm / anorm; + } + } triangular_error: if (err != 0) { if (sing_handler) - sing_handler (rcond); + { + sing_handler (rcond); + mattype.mark_as_rectangular (); + } else (*current_liboctave_error_handler) ("SparseMatrix::solve matrix singular to machine precision, rcond = %g", @@ -2928,7 +3073,10 @@ err = -2; if (sing_handler) - sing_handler (rcond); + { + sing_handler (rcond); + mattype.mark_as_rectangular (); + } else (*current_liboctave_error_handler) ("matrix singular to machine precision, rcond = %g", @@ -2945,7 +3093,8 @@ ComplexMatrix SparseMatrix::ltsolve (SparseType &mattype, const ComplexMatrix& b, octave_idx_type& err, double& rcond, - solve_singularity_handler sing_handler) const + solve_singularity_handler sing_handler, + bool calc_cond) const { ComplexMatrix retval; @@ -2969,22 +3118,25 @@ double anorm = 0.; double ainvnorm = 0.; octave_idx_type b_nc = b.cols (); - rcond = 0.; - - // Calculate the 1-norm of matrix for rcond calculation - for (octave_idx_type j = 0; j < nc; j++) - { - double atmp = 0.; - for (octave_idx_type i = cidx(j); i < cidx(j+1); i++) - atmp += fabs(data(i)); - if (atmp > anorm) - anorm = atmp; + rcond = 1.; + + if (calc_cond) + { + // Calculate the 1-norm of matrix for rcond calculation + for (octave_idx_type j = 0; j < nc; j++) + { + double atmp = 0.; + for (octave_idx_type i = cidx(j); i < cidx(j+1); i++) + atmp += fabs(data(i)); + if (atmp > anorm) + anorm = atmp; + } } if (typ == SparseType::Permuted_Lower) { retval.resize (nc, b_nc); - OCTAVE_LOCAL_BUFFER (Complex, cwork, nr); + OCTAVE_LOCAL_BUFFER (Complex, cwork, nm); octave_idx_type *perm = mattype.triangular_perm (); for (octave_idx_type j = 0; j < b_nc; j++) @@ -3008,7 +3160,7 @@ mini = i; } - if (minr != k) + if (minr != k || data(mini) == 0) { err = -2; goto triangular_error; @@ -3031,50 +3183,56 @@ retval (i, j) = cwork[i]; } - // Calculation of 1-norm of inv(*this) - OCTAVE_LOCAL_BUFFER (double, work, nm); - for (octave_idx_type i = 0; i < nm; i++) - work[i] = 0.; - - for (octave_idx_type j = 0; j < nr; j++) - { - work[j] = 1.; - - for (octave_idx_type k = 0; k < nc; k++) + if (calc_cond) + { + // Calculation of 1-norm of inv(*this) + OCTAVE_LOCAL_BUFFER (double, work, nm); + for (octave_idx_type i = 0; i < nm; i++) + work[i] = 0.; + + for (octave_idx_type j = 0; j < nr; j++) { - if (work[k] != 0.) + work[j] = 1.; + + for (octave_idx_type k = 0; k < nc; k++) { - octave_idx_type minr = nr; - octave_idx_type mini = 0; - - for (octave_idx_type i = cidx(k); i < cidx(k+1); i++) - if (perm[ridx(i)] < minr) - { - minr = perm[ridx(i)]; - mini = i; - } - - double tmp = work[k] / data(mini); - work[k] = tmp; - for (octave_idx_type i = cidx(k); i < cidx(k+1); i++) + if (work[k] != 0.) { - if (i == mini) - continue; - - octave_idx_type iidx = perm[ridx(i)]; - work[iidx] = work[iidx] - tmp * data(i); + octave_idx_type minr = nr; + octave_idx_type mini = 0; + + for (octave_idx_type i = cidx(k); + i < cidx(k+1); i++) + if (perm[ridx(i)] < minr) + { + minr = perm[ridx(i)]; + mini = i; + } + + double tmp = work[k] / data(mini); + work[k] = tmp; + for (octave_idx_type i = cidx(k); + i < cidx(k+1); i++) + { + if (i == mini) + continue; + + octave_idx_type iidx = perm[ridx(i)]; + work[iidx] = work[iidx] - tmp * data(i); + } } } + + double atmp = 0; + for (octave_idx_type i = j; i < nc; i++) + { + atmp += fabs(work[i]); + work[i] = 0.; + } + if (atmp > ainvnorm) + ainvnorm = atmp; } - - double atmp = 0; - for (octave_idx_type i = j; i < nc; i++) - { - atmp += fabs(work[i]); - work[i] = 0.; - } - if (atmp > ainvnorm) - ainvnorm = atmp; + rcond = 1. / ainvnorm / anorm; } } else @@ -3093,7 +3251,8 @@ { if (cwork[k] != 0.) { - if (ridx(cidx(k)) != k) + if (ridx(cidx(k)) != k || + data(cidx(k)) == 0.) { err = -2; goto triangular_error; @@ -3113,48 +3272,53 @@ retval.xelem (i, j) = cwork[i]; } - // Calculation of 1-norm of inv(*this) - OCTAVE_LOCAL_BUFFER (double, work, nm); - for (octave_idx_type i = 0; i < nm; i++) - work[i] = 0.; - - for (octave_idx_type j = 0; j < nr; j++) - { - work[j] = 1.; - - for (octave_idx_type k = j; k < nc; k++) + if (calc_cond) + { + // Calculation of 1-norm of inv(*this) + OCTAVE_LOCAL_BUFFER (double, work, nm); + for (octave_idx_type i = 0; i < nm; i++) + work[i] = 0.; + + for (octave_idx_type j = 0; j < nr; j++) { - - if (work[k] != 0.) + work[j] = 1.; + + for (octave_idx_type k = j; k < nc; k++) { - double tmp = work[k] / data(cidx(k)); - work[k] = tmp; - for (octave_idx_type i = cidx(k)+1; i < cidx(k+1); i++) + + if (work[k] != 0.) { - octave_idx_type iidx = ridx(i); - work[iidx] = work[iidx] - tmp * data(i); + double tmp = work[k] / data(cidx(k)); + work[k] = tmp; + for (octave_idx_type i = cidx(k)+1; + i < cidx(k+1); i++) + { + octave_idx_type iidx = ridx(i); + work[iidx] = work[iidx] - tmp * data(i); + } } } - } - double atmp = 0; - for (octave_idx_type i = j; i < nc; i++) - { - atmp += fabs(work[i]); - work[i] = 0.; + double atmp = 0; + for (octave_idx_type i = j; i < nc; i++) + { + atmp += fabs(work[i]); + work[i] = 0.; + } + if (atmp > ainvnorm) + ainvnorm = atmp; } - if (atmp > ainvnorm) - ainvnorm = atmp; - } - - } - - rcond = 1. / ainvnorm / anorm; + rcond = 1. / ainvnorm / anorm; + } + } triangular_error: if (err != 0) { if (sing_handler) - sing_handler (rcond); + { + sing_handler (rcond); + mattype.mark_as_rectangular (); + } else (*current_liboctave_error_handler) ("SparseMatrix::solve matrix singular to machine precision, rcond = %g", @@ -3168,7 +3332,10 @@ err = -2; if (sing_handler) - sing_handler (rcond); + { + sing_handler (rcond); + mattype.mark_as_rectangular (); + } else (*current_liboctave_error_handler) ("matrix singular to machine precision, rcond = %g", @@ -3185,7 +3352,8 @@ SparseComplexMatrix SparseMatrix::ltsolve (SparseType &mattype, const SparseComplexMatrix& b, octave_idx_type& err, double& rcond, - solve_singularity_handler sing_handler) const + solve_singularity_handler sing_handler, + bool calc_cond) const { SparseComplexMatrix retval; @@ -3208,20 +3376,23 @@ { double anorm = 0.; double ainvnorm = 0.; - rcond = 0.; - - // Calculate the 1-norm of matrix for rcond calculation - for (octave_idx_type j = 0; j < nc; j++) - { - double atmp = 0.; - for (octave_idx_type i = cidx(j); i < cidx(j+1); i++) - atmp += fabs(data(i)); - if (atmp > anorm) - anorm = atmp; + rcond = 1.; + + if (calc_cond) + { + // Calculate the 1-norm of matrix for rcond calculation + for (octave_idx_type j = 0; j < nc; j++) + { + double atmp = 0.; + for (octave_idx_type i = cidx(j); i < cidx(j+1); i++) + atmp += fabs(data(i)); + if (atmp > anorm) + anorm = atmp; + } } octave_idx_type b_nc = b.cols (); - octave_idx_type b_nz = b.nzmax (); + octave_idx_type b_nz = b.nnz (); retval = SparseComplexMatrix (nc, b_nc, b_nz); retval.xcidx(0) = 0; octave_idx_type ii = 0; @@ -3253,7 +3424,7 @@ mini = i; } - if (minr != k) + if (minr != k || data(mini) == 0) { err = -2; goto triangular_error; @@ -3298,50 +3469,56 @@ retval.maybe_compress (); - // Calculation of 1-norm of inv(*this) - OCTAVE_LOCAL_BUFFER (double, work, nm); - for (octave_idx_type i = 0; i < nm; i++) - work[i] = 0.; - - for (octave_idx_type j = 0; j < nr; j++) - { - work[j] = 1.; - - for (octave_idx_type k = 0; k < nc; k++) + if (calc_cond) + { + // Calculation of 1-norm of inv(*this) + OCTAVE_LOCAL_BUFFER (double, work, nm); + for (octave_idx_type i = 0; i < nm; i++) + work[i] = 0.; + + for (octave_idx_type j = 0; j < nr; j++) { - if (work[k] != 0.) + work[j] = 1.; + + for (octave_idx_type k = 0; k < nc; k++) { - octave_idx_type minr = nr; - octave_idx_type mini = 0; - - for (octave_idx_type i = cidx(k); i < cidx(k+1); i++) - if (perm[ridx(i)] < minr) - { - minr = perm[ridx(i)]; - mini = i; - } - - double tmp = work[k] / data(mini); - work[k] = tmp; - for (octave_idx_type i = cidx(k); i < cidx(k+1); i++) + if (work[k] != 0.) { - if (i == mini) - continue; - - octave_idx_type iidx = perm[ridx(i)]; - work[iidx] = work[iidx] - tmp * data(i); + octave_idx_type minr = nr; + octave_idx_type mini = 0; + + for (octave_idx_type i = cidx(k); + i < cidx(k+1); i++) + if (perm[ridx(i)] < minr) + { + minr = perm[ridx(i)]; + mini = i; + } + + double tmp = work[k] / data(mini); + work[k] = tmp; + for (octave_idx_type i = cidx(k); + i < cidx(k+1); i++) + { + if (i == mini) + continue; + + octave_idx_type iidx = perm[ridx(i)]; + work[iidx] = work[iidx] - tmp * data(i); + } } } + + double atmp = 0; + for (octave_idx_type i = j; i < nc; i++) + { + atmp += fabs(work[i]); + work[i] = 0.; + } + if (atmp > ainvnorm) + ainvnorm = atmp; } - - double atmp = 0; - for (octave_idx_type i = j; i < nc; i++) - { - atmp += fabs(work[i]); - work[i] = 0.; - } - if (atmp > ainvnorm) - ainvnorm = atmp; + rcond = 1. / ainvnorm / anorm; } } else @@ -3359,7 +3536,8 @@ { if (cwork[k] != 0.) { - if (ridx(cidx(k)) != k) + if (ridx(cidx(k)) != k || + data(cidx(k)) == 0.) { err = -2; goto triangular_error; @@ -3401,48 +3579,53 @@ retval.maybe_compress (); - // Calculation of 1-norm of inv(*this) - OCTAVE_LOCAL_BUFFER (double, work, nm); - for (octave_idx_type i = 0; i < nm; i++) - work[i] = 0.; - - for (octave_idx_type j = 0; j < nr; j++) - { - work[j] = 1.; - - for (octave_idx_type k = j; k < nc; k++) + if (calc_cond) + { + // Calculation of 1-norm of inv(*this) + OCTAVE_LOCAL_BUFFER (double, work, nm); + for (octave_idx_type i = 0; i < nm; i++) + work[i] = 0.; + + for (octave_idx_type j = 0; j < nr; j++) { - - if (work[k] != 0.) + work[j] = 1.; + + for (octave_idx_type k = j; k < nc; k++) { - double tmp = work[k] / data(cidx(k)); - work[k] = tmp; - for (octave_idx_type i = cidx(k)+1; i < cidx(k+1); i++) + + if (work[k] != 0.) { - octave_idx_type iidx = ridx(i); - work[iidx] = work[iidx] - tmp * data(i); + double tmp = work[k] / data(cidx(k)); + work[k] = tmp; + for (octave_idx_type i = cidx(k)+1; + i < cidx(k+1); i++) + { + octave_idx_type iidx = ridx(i); + work[iidx] = work[iidx] - tmp * data(i); + } } } - } - double atmp = 0; - for (octave_idx_type i = j; i < nc; i++) - { - atmp += fabs(work[i]); - work[i] = 0.; + double atmp = 0; + for (octave_idx_type i = j; i < nc; i++) + { + atmp += fabs(work[i]); + work[i] = 0.; + } + if (atmp > ainvnorm) + ainvnorm = atmp; } - if (atmp > ainvnorm) - ainvnorm = atmp; - } - - } - - rcond = 1. / ainvnorm / anorm; + rcond = 1. / ainvnorm / anorm; + } + } triangular_error: if (err != 0) { if (sing_handler) - sing_handler (rcond); + { + sing_handler (rcond); + mattype.mark_as_rectangular (); + } else (*current_liboctave_error_handler) ("SparseMatrix::solve matrix singular to machine precision, rcond = %g", @@ -3456,7 +3639,10 @@ err = -2; if (sing_handler) - sing_handler (rcond); + { + sing_handler (rcond); + mattype.mark_as_rectangular (); + } else (*current_liboctave_error_handler) ("matrix singular to machine precision, rcond = %g", @@ -3471,9 +3657,10 @@ } Matrix -SparseMatrix::trisolve (SparseType &mattype, const Matrix& b, octave_idx_type& err, - double& rcond, - solve_singularity_handler sing_handler) const +SparseMatrix::trisolve (SparseType &mattype, const Matrix& b, + octave_idx_type& err, double& rcond, + solve_singularity_handler sing_handler, + bool calc_cond) const { Matrix retval; @@ -3484,6 +3671,9 @@ if (nr == 0 || nc == 0 || nr != nc || nr != b.rows ()) (*current_liboctave_error_handler) ("matrix dimension mismatch solution of linear equations"); + else if (calc_cond) + (*current_liboctave_error_handler) + ("calculation of condition number not implemented"); else { // Print spparms("spumoni") info if requested @@ -3602,7 +3792,10 @@ err = -2; if (sing_handler) - sing_handler (rcond); + { + sing_handler (rcond); + mattype.mark_as_rectangular (); + } else (*current_liboctave_error_handler) ("matrix singular to machine precision"); @@ -3619,8 +3812,10 @@ } SparseMatrix -SparseMatrix::trisolve (SparseType &mattype, const SparseMatrix& b, octave_idx_type& err, - double& rcond, solve_singularity_handler sing_handler) const +SparseMatrix::trisolve (SparseType &mattype, const SparseMatrix& b, + octave_idx_type& err, double& rcond, + solve_singularity_handler sing_handler, + bool calc_cond) const { SparseMatrix retval; @@ -3631,6 +3826,9 @@ if (nr == 0 || nc == 0 || nr != nc || nr != b.rows ()) (*current_liboctave_error_handler) ("matrix dimension mismatch solution of linear equations"); + else if (calc_cond) + (*current_liboctave_error_handler) + ("calculation of condition number not implemented"); else { // Print spparms("spumoni") info if requested @@ -3689,13 +3887,16 @@ ("unrecoverable error in dgttrf"); else { - rcond = 0.0; if (err != 0) { + rcond = 0.0; err = -2; if (sing_handler) - sing_handler (rcond); + { + sing_handler (rcond); + mattype.mark_as_rectangular (); + } else (*current_liboctave_error_handler) ("matrix singular to machine precision"); @@ -3703,8 +3904,9 @@ } else { + rcond = 1.0; char job = 'N'; - volatile octave_idx_type x_nz = b.nzmax (); + volatile octave_idx_type x_nz = b.nnz (); octave_idx_type b_nc = b.cols (); retval = SparseMatrix (nr, b_nc, x_nz); retval.xcidx(0) = 0; @@ -3768,8 +3970,10 @@ } ComplexMatrix -SparseMatrix::trisolve (SparseType &mattype, const ComplexMatrix& b, octave_idx_type& err, - double& rcond, solve_singularity_handler sing_handler) const +SparseMatrix::trisolve (SparseType &mattype, const ComplexMatrix& b, + octave_idx_type& err, double& rcond, + solve_singularity_handler sing_handler, + bool calc_cond) const { ComplexMatrix retval; @@ -3780,6 +3984,9 @@ if (nr == 0 || nc == 0 || nr != nc || nr != b.rows ()) (*current_liboctave_error_handler) ("matrix dimension mismatch solution of linear equations"); + else if (calc_cond) + (*current_liboctave_error_handler) + ("calculation of condition number not implemented"); else { // Print spparms("spumoni") info if requested @@ -3908,7 +4115,10 @@ err = -2; if (sing_handler) - sing_handler (rcond); + { + sing_handler (rcond); + mattype.mark_as_rectangular (); + } else (*current_liboctave_error_handler) ("matrix singular to machine precision"); @@ -3923,8 +4133,9 @@ SparseComplexMatrix SparseMatrix::trisolve (SparseType &mattype, const SparseComplexMatrix& b, - octave_idx_type& err, double& rcond, - solve_singularity_handler sing_handler) const + octave_idx_type& err, double& rcond, + solve_singularity_handler sing_handler, + bool calc_cond) const { SparseComplexMatrix retval; @@ -3935,6 +4146,9 @@ if (nr == 0 || nc == 0 || nr != nc || nr != b.rows ()) (*current_liboctave_error_handler) ("matrix dimension mismatch solution of linear equations"); + else if (calc_cond) + (*current_liboctave_error_handler) + ("calculation of condition number not implemented"); else { // Print spparms("spumoni") info if requested @@ -3993,13 +4207,16 @@ ("unrecoverable error in dgttrf"); else { - rcond = 0.0; if (err != 0) { + rcond = 0.0; err = -2; if (sing_handler) - sing_handler (rcond); + { + sing_handler (rcond); + mattype.mark_as_rectangular (); + } else (*current_liboctave_error_handler) ("matrix singular to machine precision"); @@ -4015,7 +4232,7 @@ // Take a first guess that the number of non-zero terms // will be as many as in b - volatile octave_idx_type x_nz = b.nzmax (); + volatile octave_idx_type x_nz = b.nnz (); volatile octave_idx_type ii = 0; retval = SparseComplexMatrix (b_nr, b_nc, x_nz); @@ -4112,9 +4329,10 @@ } Matrix -SparseMatrix::bsolve (SparseType &mattype, const Matrix& b, octave_idx_type& err, - double& rcond, - solve_singularity_handler sing_handler) const +SparseMatrix::bsolve (SparseType &mattype, const Matrix& b, + octave_idx_type& err, double& rcond, + solve_singularity_handler sing_handler, + bool calc_cond) const { Matrix retval; @@ -4156,7 +4374,9 @@ } // Calculate the norm of the matrix, for later use. - // double anorm = m_band.abs().sum().row(0).max(); + double anorm; + if (calc_cond) + anorm = m_band.abs().sum().row(0).max(); char job = 'L'; F77_XFCN (dpbtrf, DPBTRF, (F77_CONST_CHAR_ARG2 (&job, 1), @@ -4168,79 +4388,80 @@ ("unrecoverable error in dpbtrf"); else { - rcond = 0.0; if (err != 0) { // Matrix is not positive definite!! Fall through to // unsymmetric banded solver. mattype.mark_as_unsymmetric (); typ = SparseType::Banded; + rcond = 0.0; err = 0; } else { - // Unfortunately, the time to calculate the condition - // number is dominant for narrow banded matrices and - // so we rely on the "err" flag from xPBTRF to flag - // singularity. The commented code below is left here - // for reference - - //Array<double> z (3 * nr); - //double *pz = z.fortran_vec (); - //Array<int> iz (nr); - //int *piz = iz.fortran_vec (); - // - //F77_XFCN (dpbcon, DGBCON, - // (F77_CONST_CHAR_ARG2 (&job, 1), - // nr, n_lower, tmp_data, ldm, - // anorm, rcond, pz, piz, err - // F77_CHAR_ARG_LEN (1))); - // - // - //if (f77_exception_encountered) - // (*current_liboctave_error_handler) - // ("unrecoverable error in dpbcon"); - // - //if (err != 0) - // err = -2; - // - //volatile double rcond_plus_one = rcond + 1.0; - // - //if (rcond_plus_one == 1.0 || xisnan (rcond)) - // { - // err = -2; - // - // if (sing_handler) - // sing_handler (rcond); - // else - // (*current_liboctave_error_handler) - // ("matrix singular to machine precision, rcond = %g", - // rcond); - // } - //else - // REST OF CODE, EXCEPT rcond=1 - - rcond = 1.; - retval = b; - double *result = retval.fortran_vec (); - - octave_idx_type b_nc = b.cols (); - - F77_XFCN (dpbtrs, DPBTRS, - (F77_CONST_CHAR_ARG2 (&job, 1), - nr, n_lower, b_nc, tmp_data, - ldm, result, b.rows(), err - F77_CHAR_ARG_LEN (1))); + if (calc_cond) + { + Array<double> z (3 * nr); + double *pz = z.fortran_vec (); + Array<octave_idx_type> iz (nr); + int *piz = iz.fortran_vec (); + + F77_XFCN (dpbcon, DGBCON, + (F77_CONST_CHAR_ARG2 (&job, 1), + nr, n_lower, tmp_data, ldm, + anorm, rcond, pz, piz, err + F77_CHAR_ARG_LEN (1))); + + if (f77_exception_encountered) + (*current_liboctave_error_handler) + ("unrecoverable error in dpbcon"); + + if (err != 0) + err = -2; + + volatile double rcond_plus_one = rcond + 1.0; + + if (rcond_plus_one == 1.0 || xisnan (rcond)) + { + err = -2; + + if (sing_handler) + { + sing_handler (rcond); + mattype.mark_as_rectangular (); + } + else + (*current_liboctave_error_handler) + ("matrix singular to machine precision, rcond = %g", + rcond); + } + } + else + rcond = 1.; + + if (err == 0) + { + retval = b; + double *result = retval.fortran_vec (); + + octave_idx_type b_nc = b.cols (); + + F77_XFCN (dpbtrs, DPBTRS, + (F77_CONST_CHAR_ARG2 (&job, 1), + nr, n_lower, b_nc, tmp_data, + ldm, result, b.rows(), err + F77_CHAR_ARG_LEN (1))); - if (f77_exception_encountered) - (*current_liboctave_error_handler) - ("unrecoverable error in dpbtrs"); - - if (err != 0) - { - (*current_liboctave_error_handler) - ("SparseMatrix::solve solve failed"); - err = -1; + if (f77_exception_encountered) + (*current_liboctave_error_handler) + ("unrecoverable error in dpbtrs"); + + if (err != 0) + { + (*current_liboctave_error_handler) + ("SparseMatrix::solve solve failed"); + err = -1; + } } } } @@ -4269,6 +4490,20 @@ for (octave_idx_type i = cidx(j); i < cidx(j+1); i++) m_band(ridx(i) - j + n_lower + n_upper, j) = data(i); + // Calculate the norm of the matrix, for later use. + double anorm; + if (calc_cond) + { + for (octave_idx_type j = 0; j < nr; j++) + { + double atmp = 0.; + for (octave_idx_type i = cidx(j); i < cidx(j+1); i++) + atmp += fabs(data(i)); + if (atmp > anorm) + anorm = atmp; + } + } + Array<octave_idx_type> ipvt (nr); octave_idx_type *pipvt = ipvt.fortran_vec (); @@ -4282,13 +4517,16 @@ { // Throw-away extra info LAPACK gives so as to not // change output. - rcond = 0.0; if (err != 0) { err = -2; + rcond = 0.0; if (sing_handler) - sing_handler (rcond); + { + sing_handler (rcond); + mattype.mark_as_rectangular (); + } else (*current_liboctave_error_handler) ("matrix singular to machine precision"); @@ -4296,59 +4534,65 @@ } else { - char job = '1'; - - // Unfortunately, the time to calculate the condition - // number is dominant for narrow banded matrices and - // so we rely on the "err" flag from xPBTRF to flag - // singularity. The commented code below is left here - // for reference - - //F77_XFCN (dgbcon, DGBCON, - // (F77_CONST_CHAR_ARG2 (&job, 1), - // nc, n_lower, n_upper, tmp_data, ldm, pipvt, - // anorm, rcond, pz, piz, err - // F77_CHAR_ARG_LEN (1))); - // - //if (f77_exception_encountered) - // (*current_liboctave_error_handler) - // ("unrecoverable error in dgbcon"); - // - // if (err != 0) - // err = -2; - // - //volatile double rcond_plus_one = rcond + 1.0; - // - //if (rcond_plus_one == 1.0 || xisnan (rcond)) - // { - // err = -2; - // - // if (sing_handler) - // sing_handler (rcond); - // else - // (*current_liboctave_error_handler) - // ("matrix singular to machine precision, rcond = %g", - // rcond); - // } - //else - // REST OF CODE, EXCEPT rcond=1 - - rcond = 1.; - retval = b; - double *result = retval.fortran_vec (); - - octave_idx_type b_nc = b.cols (); - - job = 'N'; - F77_XFCN (dgbtrs, DGBTRS, - (F77_CONST_CHAR_ARG2 (&job, 1), - nr, n_lower, n_upper, b_nc, tmp_data, - ldm, pipvt, result, b.rows(), err - F77_CHAR_ARG_LEN (1))); + if (calc_cond) + { + char job = '1'; + Array<double> z (3 * nr); + double *pz = z.fortran_vec (); + Array<octave_idx_type> iz (nr); + int *piz = iz.fortran_vec (); + + F77_XFCN (dgbcon, DGBCON, + (F77_CONST_CHAR_ARG2 (&job, 1), + nc, n_lower, n_upper, tmp_data, ldm, pipvt, + anorm, rcond, pz, piz, err + F77_CHAR_ARG_LEN (1))); + + if (f77_exception_encountered) + (*current_liboctave_error_handler) + ("unrecoverable error in dgbcon"); + + if (err != 0) + err = -2; + + volatile double rcond_plus_one = rcond + 1.0; + + if (rcond_plus_one == 1.0 || xisnan (rcond)) + { + err = -2; + + if (sing_handler) + { + sing_handler (rcond); + mattype.mark_as_rectangular (); + } + else + (*current_liboctave_error_handler) + ("matrix singular to machine precision, rcond = %g", + rcond); + } + } + else + rcond = 1.; + + if (err == 0) + { + retval = b; + double *result = retval.fortran_vec (); + + octave_idx_type b_nc = b.cols (); + + char job = 'N'; + F77_XFCN (dgbtrs, DGBTRS, + (F77_CONST_CHAR_ARG2 (&job, 1), + nr, n_lower, n_upper, b_nc, tmp_data, + ldm, pipvt, result, b.rows(), err + F77_CHAR_ARG_LEN (1))); - if (f77_exception_encountered) - (*current_liboctave_error_handler) - ("unrecoverable error in dgbtrs"); + if (f77_exception_encountered) + (*current_liboctave_error_handler) + ("unrecoverable error in dgbtrs"); + } } } } @@ -4360,8 +4604,10 @@ } SparseMatrix -SparseMatrix::bsolve (SparseType &mattype, const SparseMatrix& b, octave_idx_type& err, - double& rcond, solve_singularity_handler sing_handler) const +SparseMatrix::bsolve (SparseType &mattype, const SparseMatrix& b, + octave_idx_type& err, double& rcond, + solve_singularity_handler sing_handler, + bool calc_cond) const { SparseMatrix retval; @@ -4403,6 +4649,11 @@ m_band(ri - j, j) = data(i); } + // Calculate the norm of the matrix, for later use. + double anorm; + if (calc_cond) + anorm = m_band.abs().sum().row(0).max(); + char job = 'L'; F77_XFCN (dpbtrf, DPBTRF, (F77_CONST_CHAR_ARG2 (&job, 1), nr, n_lower, tmp_data, ldm, err @@ -4413,75 +4664,118 @@ ("unrecoverable error in dpbtrf"); else { - rcond = 0.0; if (err != 0) { mattype.mark_as_unsymmetric (); typ = SparseType::Banded; + rcond = 0.0; err = 0; } else { - rcond = 1.; - octave_idx_type b_nr = b.rows (); - octave_idx_type b_nc = b.cols (); - OCTAVE_LOCAL_BUFFER (double, Bx, b_nr); - - // Take a first guess that the number of non-zero terms - // will be as many as in b - volatile octave_idx_type x_nz = b.nzmax (); - volatile octave_idx_type ii = 0; - retval = SparseMatrix (b_nr, b_nc, x_nz); - - retval.xcidx(0) = 0; - for (volatile octave_idx_type j = 0; j < b_nc; j++) + if (calc_cond) + { + Array<double> z (3 * nr); + double *pz = z.fortran_vec (); + Array<octave_idx_type> iz (nr); + int *piz = iz.fortran_vec (); + + F77_XFCN (dpbcon, DGBCON, + (F77_CONST_CHAR_ARG2 (&job, 1), + nr, n_lower, tmp_data, ldm, + anorm, rcond, pz, piz, err + F77_CHAR_ARG_LEN (1))); + + if (f77_exception_encountered) + (*current_liboctave_error_handler) + ("unrecoverable error in dpbcon"); + + if (err != 0) + err = -2; + + volatile double rcond_plus_one = rcond + 1.0; + + if (rcond_plus_one == 1.0 || xisnan (rcond)) + { + err = -2; + + if (sing_handler) + { + sing_handler (rcond); + mattype.mark_as_rectangular (); + } + else + (*current_liboctave_error_handler) + ("matrix singular to machine precision, rcond = %g", + rcond); + } + } + else + rcond = 1.; + + if (err == 0) { - for (octave_idx_type i = 0; i < b_nr; i++) - Bx[i] = b.elem (i, j); - - F77_XFCN (dpbtrs, DPBTRS, - (F77_CONST_CHAR_ARG2 (&job, 1), - nr, n_lower, 1, tmp_data, - ldm, Bx, b_nr, err - F77_CHAR_ARG_LEN (1))); + octave_idx_type b_nr = b.rows (); + octave_idx_type b_nc = b.cols (); + OCTAVE_LOCAL_BUFFER (double, Bx, b_nr); + + // Take a first guess that the number of non-zero terms + // will be as many as in b + volatile octave_idx_type x_nz = b.nnz (); + volatile octave_idx_type ii = 0; + retval = SparseMatrix (b_nr, b_nc, x_nz); + + retval.xcidx(0) = 0; + for (volatile octave_idx_type j = 0; j < b_nc; j++) + { + for (octave_idx_type i = 0; i < b_nr; i++) + Bx[i] = b.elem (i, j); + + F77_XFCN (dpbtrs, DPBTRS, + (F77_CONST_CHAR_ARG2 (&job, 1), + nr, n_lower, 1, tmp_data, + ldm, Bx, b_nr, err + F77_CHAR_ARG_LEN (1))); - if (f77_exception_encountered) - { - (*current_liboctave_error_handler) - ("unrecoverable error in dpbtrs"); - err = -1; - break; + if (f77_exception_encountered) + { + (*current_liboctave_error_handler) + ("unrecoverable error in dpbtrs"); + err = -1; + break; + } + + if (err != 0) + { + (*current_liboctave_error_handler) + ("SparseMatrix::solve solve failed"); + err = -1; + break; + } + + for (octave_idx_type i = 0; i < b_nr; i++) + { + double tmp = Bx[i]; + if (tmp != 0.0) + { + if (ii == x_nz) + { + // Resize the sparse matrix + octave_idx_type sz = x_nz * + (b_nc - j) / b_nc; + sz = (sz > 10 ? sz : 10) + x_nz; + retval.change_capacity (sz); + x_nz = sz; + } + retval.xdata(ii) = tmp; + retval.xridx(ii++) = i; + } + } + retval.xcidx(j+1) = ii; } - if (err != 0) - { - (*current_liboctave_error_handler) - ("SparseMatrix::solve solve failed"); - err = -1; - break; - } - - for (octave_idx_type i = 0; i < b_nr; i++) - { - double tmp = Bx[i]; - if (tmp != 0.0) - { - if (ii == x_nz) - { - // Resize the sparse matrix - octave_idx_type sz = x_nz * (b_nc - j) / b_nc; - sz = (sz > 10 ? sz : 10) + x_nz; - retval.change_capacity (sz); - x_nz = sz; - } - retval.xdata(ii) = tmp; - retval.xridx(ii++) = i; - } - } - retval.xcidx(j+1) = ii; + retval.maybe_compress (); } - - retval.maybe_compress (); } } } @@ -4509,6 +4803,20 @@ for (octave_idx_type i = cidx(j); i < cidx(j+1); i++) m_band(ridx(i) - j + n_lower + n_upper, j) = data(i); + // Calculate the norm of the matrix, for later use. + double anorm; + if (calc_cond) + { + for (octave_idx_type j = 0; j < nr; j++) + { + double atmp = 0.; + for (octave_idx_type i = cidx(j); i < cidx(j+1); i++) + atmp += fabs(data(i)); + if (atmp > anorm) + anorm = atmp; + } + } + Array<octave_idx_type> ipvt (nr); octave_idx_type *pipvt = ipvt.fortran_vec (); @@ -4520,13 +4828,16 @@ ("unrecoverable error in dgbtrf"); else { - rcond = 0.0; if (err != 0) { err = -2; + rcond = 0.0; if (sing_handler) - sing_handler (rcond); + { + sing_handler (rcond); + mattype.mark_as_rectangular (); + } else (*current_liboctave_error_handler) ("matrix singular to machine precision"); @@ -4534,60 +4845,105 @@ } else { - char job = 'N'; - volatile octave_idx_type x_nz = b.nzmax (); - octave_idx_type b_nc = b.cols (); - retval = SparseMatrix (nr, b_nc, x_nz); - retval.xcidx(0) = 0; - volatile octave_idx_type ii = 0; - - OCTAVE_LOCAL_BUFFER (double, work, nr); - - for (volatile octave_idx_type j = 0; j < b_nc; j++) + if (calc_cond) { - for (octave_idx_type i = 0; i < nr; i++) - work[i] = 0.; - for (octave_idx_type i = b.cidx(j); i < b.cidx(j+1); i++) - work[b.ridx(i)] = b.data(i); - - F77_XFCN (dgbtrs, DGBTRS, - (F77_CONST_CHAR_ARG2 (&job, 1), - nr, n_lower, n_upper, 1, tmp_data, - ldm, pipvt, work, b.rows (), err - F77_CHAR_ARG_LEN (1))); - + char job = '1'; + Array<double> z (3 * nr); + double *pz = z.fortran_vec (); + Array<octave_idx_type> iz (nr); + int *piz = iz.fortran_vec (); + + F77_XFCN (dgbcon, DGBCON, + (F77_CONST_CHAR_ARG2 (&job, 1), + nc, n_lower, n_upper, tmp_data, ldm, pipvt, + anorm, rcond, pz, piz, err + F77_CHAR_ARG_LEN (1))); + if (f77_exception_encountered) + (*current_liboctave_error_handler) + ("unrecoverable error in dgbcon"); + + if (err != 0) + err = -2; + + volatile double rcond_plus_one = rcond + 1.0; + + if (rcond_plus_one == 1.0 || xisnan (rcond)) + { + err = -2; + + if (sing_handler) + { + sing_handler (rcond); + mattype.mark_as_rectangular (); + } + else + (*current_liboctave_error_handler) + ("matrix singular to machine precision, rcond = %g", + rcond); + } + } + else + rcond = 1.; + + if (err == 0) + { + char job = 'N'; + volatile octave_idx_type x_nz = b.nnz (); + octave_idx_type b_nc = b.cols (); + retval = SparseMatrix (nr, b_nc, x_nz); + retval.xcidx(0) = 0; + volatile octave_idx_type ii = 0; + + OCTAVE_LOCAL_BUFFER (double, work, nr); + + for (volatile octave_idx_type j = 0; j < b_nc; j++) { - (*current_liboctave_error_handler) - ("unrecoverable error in dgbtrs"); - break; + for (octave_idx_type i = 0; i < nr; i++) + work[i] = 0.; + for (octave_idx_type i = b.cidx(j); + i < b.cidx(j+1); i++) + work[b.ridx(i)] = b.data(i); + + F77_XFCN (dgbtrs, DGBTRS, + (F77_CONST_CHAR_ARG2 (&job, 1), + nr, n_lower, n_upper, 1, tmp_data, + ldm, pipvt, work, b.rows (), err + F77_CHAR_ARG_LEN (1))); + + if (f77_exception_encountered) + { + (*current_liboctave_error_handler) + ("unrecoverable error in dgbtrs"); + break; + } + + // Count non-zeros in work vector and adjust + // space in retval if needed + octave_idx_type new_nnz = 0; + for (octave_idx_type i = 0; i < nr; i++) + if (work[i] != 0.) + new_nnz++; + + if (ii + new_nnz > x_nz) + { + // Resize the sparse matrix + octave_idx_type sz = new_nnz * (b_nc - j) + x_nz; + retval.change_capacity (sz); + x_nz = sz; + } + + for (octave_idx_type i = 0; i < nr; i++) + if (work[i] != 0.) + { + retval.xridx(ii) = i; + retval.xdata(ii++) = work[i]; + } + retval.xcidx(j+1) = ii; } - // Count non-zeros in work vector and adjust - // space in retval if needed - octave_idx_type new_nnz = 0; - for (octave_idx_type i = 0; i < nr; i++) - if (work[i] != 0.) - new_nnz++; - - if (ii + new_nnz > x_nz) - { - // Resize the sparse matrix - octave_idx_type sz = new_nnz * (b_nc - j) + x_nz; - retval.change_capacity (sz); - x_nz = sz; - } - - for (octave_idx_type i = 0; i < nr; i++) - if (work[i] != 0.) - { - retval.xridx(ii) = i; - retval.xdata(ii++) = work[i]; - } - retval.xcidx(j+1) = ii; + retval.maybe_compress (); } - - retval.maybe_compress (); } } } @@ -4599,8 +4955,10 @@ } ComplexMatrix -SparseMatrix::bsolve (SparseType &mattype, const ComplexMatrix& b, octave_idx_type& err, - double& rcond, solve_singularity_handler sing_handler) const +SparseMatrix::bsolve (SparseType &mattype, const ComplexMatrix& b, + octave_idx_type& err, double& rcond, + solve_singularity_handler sing_handler, + bool calc_cond) const { ComplexMatrix retval; @@ -4642,6 +5000,11 @@ m_band(ri - j, j) = data(i); } + // Calculate the norm of the matrix, for later use. + double anorm; + if (calc_cond) + anorm = m_band.abs().sum().row(0).max(); + char job = 'L'; F77_XFCN (dpbtrf, DPBTRF, (F77_CONST_CHAR_ARG2 (&job, 1), nr, n_lower, tmp_data, ldm, err @@ -4652,81 +5015,123 @@ ("unrecoverable error in dpbtrf"); else { - rcond = 0.0; if (err != 0) { // Matrix is not positive definite!! Fall through to // unsymmetric banded solver. mattype.mark_as_unsymmetric (); typ = SparseType::Banded; + rcond = 0.0; err = 0; } else { - rcond = 1.; - octave_idx_type b_nr = b.rows (); - octave_idx_type b_nc = b.cols (); - - OCTAVE_LOCAL_BUFFER (double, Bx, b_nr); - OCTAVE_LOCAL_BUFFER (double, Bz, b_nr); - - retval.resize (b_nr, b_nc); + if (calc_cond) + { + Array<double> z (3 * nr); + double *pz = z.fortran_vec (); + Array<octave_idx_type> iz (nr); + int *piz = iz.fortran_vec (); + + F77_XFCN (dpbcon, DGBCON, + (F77_CONST_CHAR_ARG2 (&job, 1), + nr, n_lower, tmp_data, ldm, + anorm, rcond, pz, piz, err + F77_CHAR_ARG_LEN (1))); + + if (f77_exception_encountered) + (*current_liboctave_error_handler) + ("unrecoverable error in dpbcon"); + + if (err != 0) + err = -2; + + volatile double rcond_plus_one = rcond + 1.0; + + if (rcond_plus_one == 1.0 || xisnan (rcond)) + { + err = -2; + + if (sing_handler) + { + sing_handler (rcond); + mattype.mark_as_rectangular (); + } + else + (*current_liboctave_error_handler) + ("matrix singular to machine precision, rcond = %g", + rcond); + } + } + else + rcond = 1.; + + if (err == 0) + { + octave_idx_type b_nr = b.rows (); + octave_idx_type b_nc = b.cols (); + + OCTAVE_LOCAL_BUFFER (double, Bx, b_nr); + OCTAVE_LOCAL_BUFFER (double, Bz, b_nr); + + retval.resize (b_nr, b_nc); - for (volatile octave_idx_type j = 0; j < b_nc; j++) - { - for (octave_idx_type i = 0; i < b_nr; i++) + for (volatile octave_idx_type j = 0; j < b_nc; j++) { - Complex c = b (i,j); - Bx[i] = std::real (c); - Bz[i] = std::imag (c); - } + for (octave_idx_type i = 0; i < b_nr; i++) + { + Complex c = b (i,j); + Bx[i] = std::real (c); + Bz[i] = std::imag (c); + } - F77_XFCN (dpbtrs, DPBTRS, - (F77_CONST_CHAR_ARG2 (&job, 1), - nr, n_lower, 1, tmp_data, - ldm, Bx, b_nr, err - F77_CHAR_ARG_LEN (1))); + F77_XFCN (dpbtrs, DPBTRS, + (F77_CONST_CHAR_ARG2 (&job, 1), + nr, n_lower, 1, tmp_data, + ldm, Bx, b_nr, err + F77_CHAR_ARG_LEN (1))); - if (f77_exception_encountered) - { - (*current_liboctave_error_handler) - ("unrecoverable error in dpbtrs"); - err = -1; - break; + if (f77_exception_encountered) + { + (*current_liboctave_error_handler) + ("unrecoverable error in dpbtrs"); + err = -1; + break; + } + + if (err != 0) + { + (*current_liboctave_error_handler) + ("SparseMatrix::solve solve failed"); + err = -1; + break; + } + + F77_XFCN (dpbtrs, DPBTRS, + (F77_CONST_CHAR_ARG2 (&job, 1), + nr, n_lower, 1, tmp_data, + ldm, Bz, b.rows(), err + F77_CHAR_ARG_LEN (1))); + + if (f77_exception_encountered) + { + (*current_liboctave_error_handler) + ("unrecoverable error in dpbtrs"); + err = -1; + break; + } + + if (err != 0) + { + (*current_liboctave_error_handler) + ("SparseMatrix::solve solve failed"); + err = -1; + break; + } + + for (octave_idx_type i = 0; i < b_nr; i++) + retval (i, j) = Complex (Bx[i], Bz[i]); } - - if (err != 0) - { - (*current_liboctave_error_handler) - ("SparseMatrix::solve solve failed"); - err = -1; - break; - } - - F77_XFCN (dpbtrs, DPBTRS, - (F77_CONST_CHAR_ARG2 (&job, 1), - nr, n_lower, 1, tmp_data, - ldm, Bz, b.rows(), err - F77_CHAR_ARG_LEN (1))); - - if (f77_exception_encountered) - { - (*current_liboctave_error_handler) - ("unrecoverable error in dpbtrs"); - err = -1; - break; - } - - if (err != 0) - { - (*current_liboctave_error_handler) - ("SparseMatrix::solve solve failed"); - err = -1; - break; - } - - for (octave_idx_type i = 0; i < b_nr; i++) - retval (i, j) = Complex (Bx[i], Bz[i]); } } } @@ -4755,6 +5160,20 @@ for (octave_idx_type i = cidx(j); i < cidx(j+1); i++) m_band(ridx(i) - j + n_lower + n_upper, j) = data(i); + // Calculate the norm of the matrix, for later use. + double anorm; + if (calc_cond) + { + for (octave_idx_type j = 0; j < nr; j++) + { + double atmp = 0.; + for (octave_idx_type i = cidx(j); i < cidx(j+1); i++) + atmp += fabs(data(i)); + if (atmp > anorm) + anorm = atmp; + } + } + Array<octave_idx_type> ipvt (nr); octave_idx_type *pipvt = ipvt.fortran_vec (); @@ -4766,13 +5185,16 @@ ("unrecoverable error in dgbtrf"); else { - rcond = 0.0; if (err != 0) { err = -2; + rcond = 0.0; if (sing_handler) + { sing_handler (rcond); + mattype.mark_as_rectangular (); + } else (*current_liboctave_error_handler) ("matrix singular to machine precision"); @@ -4780,50 +5202,94 @@ } else { - char job = 'N'; - octave_idx_type b_nc = b.cols (); - retval.resize (nr,b_nc); - - OCTAVE_LOCAL_BUFFER (double, Bz, nr); - OCTAVE_LOCAL_BUFFER (double, Bx, nr); - - for (volatile octave_idx_type j = 0; j < b_nc; j++) + if (calc_cond) { - for (octave_idx_type i = 0; i < nr; i++) + char job = '1'; + Array<double> z (3 * nr); + double *pz = z.fortran_vec (); + Array<octave_idx_type> iz (nr); + int *piz = iz.fortran_vec (); + + F77_XFCN (dpbcon, DGBCON, + (F77_CONST_CHAR_ARG2 (&job, 1), + nr, n_lower, tmp_data, ldm, + anorm, rcond, pz, piz, err + F77_CHAR_ARG_LEN (1))); + + if (f77_exception_encountered) + (*current_liboctave_error_handler) + ("unrecoverable error in dpbcon"); + + if (err != 0) + err = -2; + + volatile double rcond_plus_one = rcond + 1.0; + + if (rcond_plus_one == 1.0 || xisnan (rcond)) + { + err = -2; + + if (sing_handler) + { + sing_handler (rcond); + mattype.mark_as_rectangular (); + } + else + (*current_liboctave_error_handler) + ("matrix singular to machine precision, rcond = %g", + rcond); + } + } + else + rcond = 1.; + + if (err == 0) + { + char job = 'N'; + octave_idx_type b_nc = b.cols (); + retval.resize (nr,b_nc); + + OCTAVE_LOCAL_BUFFER (double, Bz, nr); + OCTAVE_LOCAL_BUFFER (double, Bx, nr); + + for (volatile octave_idx_type j = 0; j < b_nc; j++) { - Complex c = b (i, j); - Bx[i] = std::real (c); - Bz[i] = std::imag (c); - } - - F77_XFCN (dgbtrs, DGBTRS, - (F77_CONST_CHAR_ARG2 (&job, 1), - nr, n_lower, n_upper, 1, tmp_data, - ldm, pipvt, Bx, b.rows (), err - F77_CHAR_ARG_LEN (1))); + for (octave_idx_type i = 0; i < nr; i++) + { + Complex c = b (i, j); + Bx[i] = std::real (c); + Bz[i] = std::imag (c); + } + + F77_XFCN (dgbtrs, DGBTRS, + (F77_CONST_CHAR_ARG2 (&job, 1), + nr, n_lower, n_upper, 1, tmp_data, + ldm, pipvt, Bx, b.rows (), err + F77_CHAR_ARG_LEN (1))); - if (f77_exception_encountered) - { - (*current_liboctave_error_handler) - ("unrecoverable error in dgbtrs"); - break; + if (f77_exception_encountered) + { + (*current_liboctave_error_handler) + ("unrecoverable error in dgbtrs"); + break; + } + + F77_XFCN (dgbtrs, DGBTRS, + (F77_CONST_CHAR_ARG2 (&job, 1), + nr, n_lower, n_upper, 1, tmp_data, + ldm, pipvt, Bz, b.rows (), err + F77_CHAR_ARG_LEN (1))); + + if (f77_exception_encountered) + { + (*current_liboctave_error_handler) + ("unrecoverable error in dgbtrs"); + break; + } + + for (octave_idx_type i = 0; i < nr; i++) + retval (i, j) = Complex (Bx[i], Bz[i]); } - - F77_XFCN (dgbtrs, DGBTRS, - (F77_CONST_CHAR_ARG2 (&job, 1), - nr, n_lower, n_upper, 1, tmp_data, - ldm, pipvt, Bz, b.rows (), err - F77_CHAR_ARG_LEN (1))); - - if (f77_exception_encountered) - { - (*current_liboctave_error_handler) - ("unrecoverable error in dgbtrs"); - break; - } - - for (octave_idx_type i = 0; i < nr; i++) - retval (i, j) = Complex (Bx[i], Bz[i]); } } } @@ -4837,8 +5303,9 @@ SparseComplexMatrix SparseMatrix::bsolve (SparseType &mattype, const SparseComplexMatrix& b, - octave_idx_type& err, double& rcond, - solve_singularity_handler sing_handler) const + octave_idx_type& err, double& rcond, + solve_singularity_handler sing_handler, + bool calc_cond) const { SparseComplexMatrix retval; @@ -4880,6 +5347,11 @@ m_band(ri - j, j) = data(i); } + // Calculate the norm of the matrix, for later use. + double anorm; + if (calc_cond) + anorm = m_band.abs().sum().row(0).max(); + char job = 'L'; F77_XFCN (dpbtrf, DPBTRF, (F77_CONST_CHAR_ARG2 (&job, 1), nr, n_lower, tmp_data, ldm, err @@ -4890,7 +5362,6 @@ ("unrecoverable error in dpbtrf"); else { - rcond = 0.0; if (err != 0) { // Matrix is not positive definite!! Fall through to @@ -4898,105 +5369,148 @@ mattype.mark_as_unsymmetric (); typ = SparseType::Banded; + rcond = 0.0; err = 0; } else { - rcond = 1.; - octave_idx_type b_nr = b.rows (); - octave_idx_type b_nc = b.cols (); - OCTAVE_LOCAL_BUFFER (double, Bx, b_nr); - OCTAVE_LOCAL_BUFFER (double, Bz, b_nr); - - // Take a first guess that the number of non-zero terms - // will be as many as in b - volatile octave_idx_type x_nz = b.nzmax (); - volatile octave_idx_type ii = 0; - retval = SparseComplexMatrix (b_nr, b_nc, x_nz); - - retval.xcidx(0) = 0; - for (volatile octave_idx_type j = 0; j < b_nc; j++) + if (calc_cond) { - - for (octave_idx_type i = 0; i < b_nr; i++) + Array<double> z (3 * nr); + double *pz = z.fortran_vec (); + Array<octave_idx_type> iz (nr); + int *piz = iz.fortran_vec (); + + F77_XFCN (dpbcon, DGBCON, + (F77_CONST_CHAR_ARG2 (&job, 1), + nr, n_lower, tmp_data, ldm, + anorm, rcond, pz, piz, err + F77_CHAR_ARG_LEN (1))); + + if (f77_exception_encountered) + (*current_liboctave_error_handler) + ("unrecoverable error in dpbcon"); + + if (err != 0) + err = -2; + + volatile double rcond_plus_one = rcond + 1.0; + + if (rcond_plus_one == 1.0 || xisnan (rcond)) + { + err = -2; + + if (sing_handler) + { + sing_handler (rcond); + mattype.mark_as_rectangular (); + } + else + (*current_liboctave_error_handler) + ("matrix singular to machine precision, rcond = %g", + rcond); + } + } + else + rcond = 1.; + + if (err == 0) + { + octave_idx_type b_nr = b.rows (); + octave_idx_type b_nc = b.cols (); + OCTAVE_LOCAL_BUFFER (double, Bx, b_nr); + OCTAVE_LOCAL_BUFFER (double, Bz, b_nr); + + // Take a first guess that the number of non-zero terms + // will be as many as in b + volatile octave_idx_type x_nz = b.nnz (); + volatile octave_idx_type ii = 0; + retval = SparseComplexMatrix (b_nr, b_nc, x_nz); + + retval.xcidx(0) = 0; + for (volatile octave_idx_type j = 0; j < b_nc; j++) { - Complex c = b (i,j); - Bx[i] = std::real (c); - Bz[i] = std::imag (c); - } - - F77_XFCN (dpbtrs, DPBTRS, - (F77_CONST_CHAR_ARG2 (&job, 1), - nr, n_lower, 1, tmp_data, - ldm, Bx, b_nr, err - F77_CHAR_ARG_LEN (1))); + + for (octave_idx_type i = 0; i < b_nr; i++) + { + Complex c = b (i,j); + Bx[i] = std::real (c); + Bz[i] = std::imag (c); + } + + F77_XFCN (dpbtrs, DPBTRS, + (F77_CONST_CHAR_ARG2 (&job, 1), + nr, n_lower, 1, tmp_data, + ldm, Bx, b_nr, err + F77_CHAR_ARG_LEN (1))); + + if (f77_exception_encountered) + { + (*current_liboctave_error_handler) + ("unrecoverable error in dpbtrs"); + err = -1; + break; + } + + if (err != 0) + { + (*current_liboctave_error_handler) + ("SparseMatrix::solve solve failed"); + err = -1; + break; + } + + F77_XFCN (dpbtrs, DPBTRS, + (F77_CONST_CHAR_ARG2 (&job, 1), + nr, n_lower, 1, tmp_data, + ldm, Bz, b_nr, err + F77_CHAR_ARG_LEN (1))); - if (f77_exception_encountered) - { - (*current_liboctave_error_handler) - ("unrecoverable error in dpbtrs"); - err = -1; - break; - } - - if (err != 0) - { - (*current_liboctave_error_handler) - ("SparseMatrix::solve solve failed"); - err = -1; - break; + if (f77_exception_encountered) + { + (*current_liboctave_error_handler) + ("unrecoverable error in dpbtrs"); + err = -1; + break; + } + + if (err != 0) + { + (*current_liboctave_error_handler) + ("SparseMatrix::solve solve failed"); + + err = -1; + break; + } + + // Count non-zeros in work vector and adjust + // space in retval if needed + octave_idx_type new_nnz = 0; + for (octave_idx_type i = 0; i < nr; i++) + if (Bx[i] != 0. || Bz[i] != 0.) + new_nnz++; + + if (ii + new_nnz > x_nz) + { + // Resize the sparse matrix + octave_idx_type sz = new_nnz * (b_nc - j) + x_nz; + retval.change_capacity (sz); + x_nz = sz; + } + + for (octave_idx_type i = 0; i < nr; i++) + if (Bx[i] != 0. || Bz[i] != 0.) + { + retval.xridx(ii) = i; + retval.xdata(ii++) = + Complex (Bx[i], Bz[i]); + } + + retval.xcidx(j+1) = ii; } - F77_XFCN (dpbtrs, DPBTRS, - (F77_CONST_CHAR_ARG2 (&job, 1), - nr, n_lower, 1, tmp_data, - ldm, Bz, b_nr, err - F77_CHAR_ARG_LEN (1))); - - if (f77_exception_encountered) - { - (*current_liboctave_error_handler) - ("unrecoverable error in dpbtrs"); - err = -1; - break; - } - - if (err != 0) - { - (*current_liboctave_error_handler) - ("SparseMatrix::solve solve failed"); - - err = -1; - break; - } - - // Count non-zeros in work vector and adjust - // space in retval if needed - octave_idx_type new_nnz = 0; - for (octave_idx_type i = 0; i < nr; i++) - if (Bx[i] != 0. || Bz[i] != 0.) - new_nnz++; - - if (ii + new_nnz > x_nz) - { - // Resize the sparse matrix - octave_idx_type sz = new_nnz * (b_nc - j) + x_nz; - retval.change_capacity (sz); - x_nz = sz; - } - - for (octave_idx_type i = 0; i < nr; i++) - if (Bx[i] != 0. || Bz[i] != 0.) - { - retval.xridx(ii) = i; - retval.xdata(ii++) = - Complex (Bx[i], Bz[i]); - } - - retval.xcidx(j+1) = ii; + retval.maybe_compress (); } - - retval.maybe_compress (); } } } @@ -5024,6 +5538,20 @@ for (octave_idx_type i = cidx(j); i < cidx(j+1); i++) m_band(ridx(i) - j + n_lower + n_upper, j) = data(i); + // Calculate the norm of the matrix, for later use. + double anorm; + if (calc_cond) + { + for (octave_idx_type j = 0; j < nr; j++) + { + double atmp = 0.; + for (octave_idx_type i = cidx(j); i < cidx(j+1); i++) + atmp += fabs(data(i)); + if (atmp > anorm) + anorm = atmp; + } + } + Array<octave_idx_type> ipvt (nr); octave_idx_type *pipvt = ipvt.fortran_vec (); @@ -5035,13 +5563,16 @@ ("unrecoverable error in dgbtrf"); else { - rcond = 0.0; if (err != 0) { err = -2; + rcond = 0.0; if (sing_handler) - sing_handler (rcond); + { + sing_handler (rcond); + mattype.mark_as_rectangular (); + } else (*current_liboctave_error_handler) ("matrix singular to machine precision"); @@ -5049,82 +5580,127 @@ } else { - char job = 'N'; - volatile octave_idx_type x_nz = b.nzmax (); - octave_idx_type b_nc = b.cols (); - retval = SparseComplexMatrix (nr, b_nc, x_nz); - retval.xcidx(0) = 0; - volatile octave_idx_type ii = 0; - - OCTAVE_LOCAL_BUFFER (double, Bx, nr); - OCTAVE_LOCAL_BUFFER (double, Bz, nr); - - for (volatile octave_idx_type j = 0; j < b_nc; j++) + if (calc_cond) { - for (octave_idx_type i = 0; i < nr; i++) + char job = '1'; + Array<double> z (3 * nr); + double *pz = z.fortran_vec (); + Array<octave_idx_type> iz (nr); + int *piz = iz.fortran_vec (); + + F77_XFCN (dgbcon, DGBCON, + (F77_CONST_CHAR_ARG2 (&job, 1), + nc, n_lower, n_upper, tmp_data, ldm, pipvt, + anorm, rcond, pz, piz, err + F77_CHAR_ARG_LEN (1))); + + if (f77_exception_encountered) + (*current_liboctave_error_handler) + ("unrecoverable error in dgbcon"); + + if (err != 0) + err = -2; + + volatile double rcond_plus_one = rcond + 1.0; + + if (rcond_plus_one == 1.0 || xisnan (rcond)) + { + err = -2; + + if (sing_handler) + { + sing_handler (rcond); + mattype.mark_as_rectangular (); + } + else + (*current_liboctave_error_handler) + ("matrix singular to machine precision, rcond = %g", + rcond); + } + } + else + rcond = 1.; + + if (err == 0) + { + char job = 'N'; + volatile octave_idx_type x_nz = b.nnz (); + octave_idx_type b_nc = b.cols (); + retval = SparseComplexMatrix (nr, b_nc, x_nz); + retval.xcidx(0) = 0; + volatile octave_idx_type ii = 0; + + OCTAVE_LOCAL_BUFFER (double, Bx, nr); + OCTAVE_LOCAL_BUFFER (double, Bz, nr); + + for (volatile octave_idx_type j = 0; j < b_nc; j++) { - Bx[i] = 0.; - Bz[i] = 0.; - } - for (octave_idx_type i = b.cidx(j); i < b.cidx(j+1); i++) - { - Complex c = b.data(i); - Bx[b.ridx(i)] = std::real (c); - Bz[b.ridx(i)] = std::imag (c); - } - - F77_XFCN (dgbtrs, DGBTRS, - (F77_CONST_CHAR_ARG2 (&job, 1), - nr, n_lower, n_upper, 1, tmp_data, - ldm, pipvt, Bx, b.rows (), err - F77_CHAR_ARG_LEN (1))); + for (octave_idx_type i = 0; i < nr; i++) + { + Bx[i] = 0.; + Bz[i] = 0.; + } + for (octave_idx_type i = b.cidx(j); + i < b.cidx(j+1); i++) + { + Complex c = b.data(i); + Bx[b.ridx(i)] = std::real (c); + Bz[b.ridx(i)] = std::imag (c); + } + + F77_XFCN (dgbtrs, DGBTRS, + (F77_CONST_CHAR_ARG2 (&job, 1), + nr, n_lower, n_upper, 1, tmp_data, + ldm, pipvt, Bx, b.rows (), err + F77_CHAR_ARG_LEN (1))); - if (f77_exception_encountered) - { - (*current_liboctave_error_handler) - ("unrecoverable error in dgbtrs"); - break; + if (f77_exception_encountered) + { + (*current_liboctave_error_handler) + ("unrecoverable error in dgbtrs"); + break; + } + + F77_XFCN (dgbtrs, DGBTRS, + (F77_CONST_CHAR_ARG2 (&job, 1), + nr, n_lower, n_upper, 1, tmp_data, + ldm, pipvt, Bz, b.rows (), err + F77_CHAR_ARG_LEN (1))); + + if (f77_exception_encountered) + { + (*current_liboctave_error_handler) + ("unrecoverable error in dgbtrs"); + break; + } + + // Count non-zeros in work vector and adjust + // space in retval if needed + octave_idx_type new_nnz = 0; + for (octave_idx_type i = 0; i < nr; i++) + if (Bx[i] != 0. || Bz[i] != 0.) + new_nnz++; + + if (ii + new_nnz > x_nz) + { + // Resize the sparse matrix + octave_idx_type sz = new_nnz * (b_nc - j) + x_nz; + retval.change_capacity (sz); + x_nz = sz; + } + + for (octave_idx_type i = 0; i < nr; i++) + if (Bx[i] != 0. || Bz[i] != 0.) + { + retval.xridx(ii) = i; + retval.xdata(ii++) = + Complex (Bx[i], Bz[i]); + } + retval.xcidx(j+1) = ii; } - F77_XFCN (dgbtrs, DGBTRS, - (F77_CONST_CHAR_ARG2 (&job, 1), - nr, n_lower, n_upper, 1, tmp_data, - ldm, pipvt, Bz, b.rows (), err - F77_CHAR_ARG_LEN (1))); - - if (f77_exception_encountered) - { - (*current_liboctave_error_handler) - ("unrecoverable error in dgbtrs"); - break; - } - - // Count non-zeros in work vector and adjust - // space in retval if needed - octave_idx_type new_nnz = 0; - for (octave_idx_type i = 0; i < nr; i++) - if (Bx[i] != 0. || Bz[i] != 0.) - new_nnz++; - - if (ii + new_nnz > x_nz) - { - // Resize the sparse matrix - octave_idx_type sz = new_nnz * (b_nc - j) + x_nz; - retval.change_capacity (sz); - x_nz = sz; - } - - for (octave_idx_type i = 0; i < nr; i++) - if (Bx[i] != 0. || Bz[i] != 0.) - { - retval.xridx(ii) = i; - retval.xdata(ii++) = - Complex (Bx[i], Bz[i]); - } - retval.xcidx(j+1) = ii; + retval.maybe_compress (); } - - retval.maybe_compress (); } } } @@ -5136,8 +5712,9 @@ } void * -SparseMatrix::factorize (octave_idx_type& err, double &rcond, Matrix &Control, Matrix &Info, - solve_singularity_handler sing_handler) const +SparseMatrix::factorize (octave_idx_type& err, double &rcond, Matrix &Control, + Matrix &Info, solve_singularity_handler sing_handler, + bool calc_cond) const { // The return values void *Numeric = 0; @@ -5199,7 +5776,10 @@ &Numeric, control, info) ; UMFPACK_DNAME (free_symbolic) (&Symbolic) ; - rcond = Info (UMFPACK_RCOND); + if (calc_cond) + rcond = Info (UMFPACK_RCOND); + else + rcond = 1.; volatile double rcond_plus_one = rcond + 1.0; if (status == UMFPACK_WARNING_singular_matrix || @@ -5244,9 +5824,10 @@ } Matrix -SparseMatrix::fsolve (SparseType &mattype, const Matrix& b, octave_idx_type& err, - double& rcond, - solve_singularity_handler sing_handler) const +SparseMatrix::fsolve (SparseType &mattype, const Matrix& b, + octave_idx_type& err, double& rcond, + solve_singularity_handler sing_handler, + bool calc_cond) const { Matrix retval; @@ -5355,7 +5936,11 @@ BEGIN_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE; L = CHOLMOD_NAME(analyze) (A, cm); CHOLMOD_NAME(factorize) (A, L, cm); - rcond = CHOLMOD_NAME(rcond)(L, cm); + if (calc_cond) + rcond = CHOLMOD_NAME(rcond)(L, cm); + else + rcond = 1.0; + END_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE; if (rcond == 0.0) @@ -5373,7 +5958,10 @@ err = -2; if (sing_handler) - sing_handler (rcond); + { + sing_handler (rcond); + mattype.mark_as_rectangular (); + } else (*current_liboctave_error_handler) ("SparseMatrix::solve matrix singular to machine precision, rcond = %g", @@ -5416,7 +6004,7 @@ #ifdef HAVE_UMFPACK Matrix Control, Info; void *Numeric = - factorize (err, rcond, Control, Info, sing_handler); + factorize (err, rcond, Control, Info, sing_handler, calc_cond); if (err == 0) { @@ -5454,6 +6042,9 @@ UMFPACK_DNAME (free_numeric) (&Numeric); } + else + mattype.mark_as_rectangular (); + #else (*current_liboctave_error_handler) ("UMFPACK not installed"); #endif @@ -5466,8 +6057,10 @@ } SparseMatrix -SparseMatrix::fsolve (SparseType &mattype, const SparseMatrix& b, octave_idx_type& err, double& rcond, - solve_singularity_handler sing_handler) const +SparseMatrix::fsolve (SparseType &mattype, const SparseMatrix& b, + octave_idx_type& err, double& rcond, + solve_singularity_handler sing_handler, + bool calc_cond) const { SparseMatrix retval; @@ -5586,7 +6179,10 @@ BEGIN_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE; L = CHOLMOD_NAME(analyze) (A, cm); CHOLMOD_NAME(factorize) (A, L, cm); - rcond = CHOLMOD_NAME(rcond)(L, cm); + if (calc_cond) + rcond = CHOLMOD_NAME(rcond)(L, cm); + else + rcond = 1.; END_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE; if (rcond == 0.0) @@ -5604,7 +6200,10 @@ err = -2; if (sing_handler) - sing_handler (rcond); + { + sing_handler (rcond); + mattype.mark_as_rectangular (); + } else (*current_liboctave_error_handler) ("SparseMatrix::solve matrix singular to machine precision, rcond = %g", @@ -5652,7 +6251,7 @@ #ifdef HAVE_UMFPACK Matrix Control, Info; void *Numeric = factorize (err, rcond, Control, Info, - sing_handler); + sing_handler, calc_cond); if (err == 0) { @@ -5670,7 +6269,7 @@ // Take a first guess that the number of non-zero terms // will be as many as in b - octave_idx_type x_nz = b.nzmax (); + octave_idx_type x_nz = b.nnz (); octave_idx_type ii = 0; retval = SparseMatrix (b_nr, b_nc, x_nz); @@ -5722,6 +6321,9 @@ UMFPACK_DNAME (free_numeric) (&Numeric); } + else + mattype.mark_as_rectangular (); + #else (*current_liboctave_error_handler) ("UMFPACK not installed"); #endif @@ -5734,8 +6336,10 @@ } ComplexMatrix -SparseMatrix::fsolve (SparseType &mattype, const ComplexMatrix& b, octave_idx_type& err, double& rcond, - solve_singularity_handler sing_handler) const +SparseMatrix::fsolve (SparseType &mattype, const ComplexMatrix& b, + octave_idx_type& err, double& rcond, + solve_singularity_handler sing_handler, + bool calc_cond) const { ComplexMatrix retval; @@ -5844,7 +6448,10 @@ BEGIN_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE; L = CHOLMOD_NAME(analyze) (A, cm); CHOLMOD_NAME(factorize) (A, L, cm); - rcond = CHOLMOD_NAME(rcond)(L, cm); + if (calc_cond) + rcond = CHOLMOD_NAME(rcond)(L, cm); + else + rcond = 1.0; END_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE; if (rcond == 0.0) @@ -5862,7 +6469,10 @@ err = -2; if (sing_handler) - sing_handler (rcond); + { + sing_handler (rcond); + mattype.mark_as_rectangular (); + } else (*current_liboctave_error_handler) ("SparseMatrix::solve matrix singular to machine precision, rcond = %g", @@ -5905,7 +6515,7 @@ #ifdef HAVE_UMFPACK Matrix Control, Info; void *Numeric = factorize (err, rcond, Control, Info, - sing_handler); + sing_handler, calc_cond); if (err == 0) { @@ -5962,6 +6572,9 @@ UMFPACK_DNAME (free_numeric) (&Numeric); } + else + mattype.mark_as_rectangular (); + #else (*current_liboctave_error_handler) ("UMFPACK not installed"); #endif @@ -5976,7 +6589,8 @@ SparseComplexMatrix SparseMatrix::fsolve (SparseType &mattype, const SparseComplexMatrix& b, octave_idx_type& err, double& rcond, - solve_singularity_handler sing_handler) const + solve_singularity_handler sing_handler, + bool calc_cond) const { SparseComplexMatrix retval; @@ -6095,7 +6709,10 @@ BEGIN_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE; L = CHOLMOD_NAME(analyze) (A, cm); CHOLMOD_NAME(factorize) (A, L, cm); - rcond = CHOLMOD_NAME(rcond)(L, cm); + if (calc_cond) + rcond = CHOLMOD_NAME(rcond)(L, cm); + else + rcond = 1.0; END_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE; if (rcond == 0.0) @@ -6113,7 +6730,10 @@ err = -2; if (sing_handler) - sing_handler (rcond); + { + sing_handler (rcond); + mattype.mark_as_rectangular (); + } else (*current_liboctave_error_handler) ("SparseMatrix::solve matrix singular to machine precision, rcond = %g", @@ -6162,7 +6782,7 @@ #ifdef HAVE_UMFPACK Matrix Control, Info; void *Numeric = factorize (err, rcond, Control, Info, - sing_handler); + sing_handler, calc_cond); if (err == 0) { @@ -6180,7 +6800,7 @@ // Take a first guess that the number of non-zero terms // will be as many as in b - octave_idx_type x_nz = b.nzmax (); + octave_idx_type x_nz = b.nnz (); octave_idx_type ii = 0; retval = SparseComplexMatrix (b_nr, b_nc, x_nz); @@ -6242,6 +6862,8 @@ UMFPACK_DNAME (free_numeric) (&Numeric); } + else + mattype.mark_as_rectangular (); #else (*current_liboctave_error_handler) ("UMFPACK not installed"); #endif @@ -6280,30 +6902,44 @@ double& rcond, solve_singularity_handler sing_handler) const { + Matrix retval; int typ = mattype.type (false); if (typ == SparseType::Unknown) typ = mattype.type (*this); + // Only calculate the condition number for CHOLMOD/UMFPACK if (typ == SparseType::Diagonal || typ == SparseType::Permuted_Diagonal) - return dsolve (mattype, b, err, rcond, sing_handler); + retval = dsolve (mattype, b, err, rcond, sing_handler, false); else if (typ == SparseType::Upper || typ == SparseType::Permuted_Upper) - return utsolve (mattype, b, err, rcond, sing_handler); + retval = utsolve (mattype, b, err, rcond, sing_handler, false); else if (typ == SparseType::Lower || typ == SparseType::Permuted_Lower) - return ltsolve (mattype, b, err, rcond, sing_handler); + retval = ltsolve (mattype, b, err, rcond, sing_handler, false); else if (typ == SparseType::Banded || typ == SparseType::Banded_Hermitian) - return bsolve (mattype, b, err, rcond, sing_handler); + retval = bsolve (mattype, b, err, rcond, sing_handler, false); else if (typ == SparseType::Tridiagonal || typ == SparseType::Tridiagonal_Hermitian) - return trisolve (mattype, b, err, rcond, sing_handler); + retval = trisolve (mattype, b, err, rcond, sing_handler, false); else if (typ == SparseType::Full || typ == SparseType::Hermitian) - return fsolve (mattype, b, err, rcond, sing_handler); - else + retval = fsolve (mattype, b, err, rcond, sing_handler, true); + else if (typ != SparseType::Rectangular) { - (*current_liboctave_error_handler) - ("matrix dimension mismatch solution of linear equations"); + (*current_liboctave_error_handler) ("unknown matrix type"); return Matrix (); } + + // Rectangular or one of the above solvers flags a singular matrix + if (mattype.type (false) == SparseType::Rectangular) + { + rcond = 1.; +#ifdef USE_QRSOLVE + retval = qrsolve (*this, b, err); +#else + retval = dmsolve<Matrix, SparseMatrix, Matrix> (*this, b, err); +#endif + } + + return retval; } SparseMatrix @@ -6334,30 +6970,43 @@ octave_idx_type& err, double& rcond, solve_singularity_handler sing_handler) const { + SparseMatrix retval; int typ = mattype.type (false); if (typ == SparseType::Unknown) typ = mattype.type (*this); if (typ == SparseType::Diagonal || typ == SparseType::Permuted_Diagonal) - return dsolve (mattype, b, err, rcond, sing_handler); + retval = dsolve (mattype, b, err, rcond, sing_handler, false); else if (typ == SparseType::Upper || typ == SparseType::Permuted_Upper) - return utsolve (mattype, b, err, rcond, sing_handler); + retval = utsolve (mattype, b, err, rcond, sing_handler, false); else if (typ == SparseType::Lower || typ == SparseType::Permuted_Lower) - return ltsolve (mattype, b, err, rcond, sing_handler); + retval = ltsolve (mattype, b, err, rcond, sing_handler, false); else if (typ == SparseType::Banded || typ == SparseType::Banded_Hermitian) - return bsolve (mattype, b, err, rcond, sing_handler); + retval = bsolve (mattype, b, err, rcond, sing_handler, false); else if (typ == SparseType::Tridiagonal || typ == SparseType::Tridiagonal_Hermitian) - return trisolve (mattype, b, err, rcond, sing_handler); + retval = trisolve (mattype, b, err, rcond, sing_handler, false); else if (typ == SparseType::Full || typ == SparseType::Hermitian) - return fsolve (mattype, b, err, rcond, sing_handler); - else + retval = fsolve (mattype, b, err, rcond, sing_handler, true); + else if (typ != SparseType::Rectangular) { - (*current_liboctave_error_handler) - ("matrix dimension mismatch solution of linear equations"); + (*current_liboctave_error_handler) ("unknown matrix type"); return SparseMatrix (); } + + if (mattype.type (false) == SparseType::Rectangular) + { + rcond = 1.; +#ifdef USE_QRSOLVE + retval = qrsolve (*this, b, err); +#else + retval = dmsolve<SparseMatrix, SparseMatrix, + SparseMatrix> (*this, b, err); +#endif + } + + return retval; } ComplexMatrix @@ -6388,30 +7037,43 @@ octave_idx_type& err, double& rcond, solve_singularity_handler sing_handler) const { + ComplexMatrix retval; int typ = mattype.type (false); if (typ == SparseType::Unknown) typ = mattype.type (*this); if (typ == SparseType::Diagonal || typ == SparseType::Permuted_Diagonal) - return dsolve (mattype, b, err, rcond, sing_handler); + retval = dsolve (mattype, b, err, rcond, sing_handler, false); else if (typ == SparseType::Upper || typ == SparseType::Permuted_Upper) - return utsolve (mattype, b, err, rcond, sing_handler); + retval = utsolve (mattype, b, err, rcond, sing_handler, false); else if (typ == SparseType::Lower || typ == SparseType::Permuted_Lower) - return ltsolve (mattype, b, err, rcond, sing_handler); + retval = ltsolve (mattype, b, err, rcond, sing_handler, false); else if (typ == SparseType::Banded || typ == SparseType::Banded_Hermitian) - return bsolve (mattype, b, err, rcond, sing_handler); + retval = bsolve (mattype, b, err, rcond, sing_handler, false); else if (typ == SparseType::Tridiagonal || typ == SparseType::Tridiagonal_Hermitian) - return trisolve (mattype, b, err, rcond, sing_handler); + retval = trisolve (mattype, b, err, rcond, sing_handler, false); else if (typ == SparseType::Full || typ == SparseType::Hermitian) - return fsolve (mattype, b, err, rcond, sing_handler); - else + retval = fsolve (mattype, b, err, rcond, sing_handler, true); + else if (typ != SparseType::Rectangular) { - (*current_liboctave_error_handler) - ("matrix dimension mismatch solution of linear equations"); + (*current_liboctave_error_handler) ("unknown matrix type"); return ComplexMatrix (); } + + if (mattype.type(false) == SparseType::Rectangular) + { + rcond = 1.; +#ifdef USE_QRSOLVE + retval = qrsolve (*this, b, err); +#else + retval = dmsolve<ComplexMatrix, SparseMatrix, + ComplexMatrix> (*this, b, err); +#endif + } + + return retval; } SparseComplexMatrix @@ -6442,30 +7104,43 @@ octave_idx_type& err, double& rcond, solve_singularity_handler sing_handler) const { + SparseComplexMatrix retval; int typ = mattype.type (false); if (typ == SparseType::Unknown) typ = mattype.type (*this); if (typ == SparseType::Diagonal || typ == SparseType::Permuted_Diagonal) - return dsolve (mattype, b, err, rcond, sing_handler); + retval = dsolve (mattype, b, err, rcond, sing_handler, false); else if (typ == SparseType::Upper || typ == SparseType::Permuted_Upper) - return utsolve (mattype, b, err, rcond, sing_handler); + retval = utsolve (mattype, b, err, rcond, sing_handler, false); else if (typ == SparseType::Lower || typ == SparseType::Permuted_Lower) - return ltsolve (mattype, b, err, rcond, sing_handler); + retval = ltsolve (mattype, b, err, rcond, sing_handler, false); else if (typ == SparseType::Banded || typ == SparseType::Banded_Hermitian) - return bsolve (mattype, b, err, rcond, sing_handler); + retval = bsolve (mattype, b, err, rcond, sing_handler, false); else if (typ == SparseType::Tridiagonal || typ == SparseType::Tridiagonal_Hermitian) - return trisolve (mattype, b, err, rcond, sing_handler); + retval = trisolve (mattype, b, err, rcond, sing_handler, false); else if (typ == SparseType::Full || typ == SparseType::Hermitian) - return fsolve (mattype, b, err, rcond, sing_handler); - else + retval = fsolve (mattype, b, err, rcond, sing_handler, true); + else if (typ != SparseType::Rectangular) { - (*current_liboctave_error_handler) - ("matrix dimension mismatch solution of linear equations"); + (*current_liboctave_error_handler) ("unknown matrix type"); return SparseComplexMatrix (); } + + if (mattype.type(false) == SparseType::Rectangular) + { + rcond = 1.; +#ifdef USE_QRSOLVE + retval = qrsolve (*this, b, err); +#else + retval = dmsolve<SparseComplexMatrix, SparseMatrix, + SparseComplexMatrix> (*this, b, err); +#endif + } + + return retval; } ColumnVector @@ -6703,136 +7378,6 @@ return solve (tmp, info, rcond, sing_handler).column (static_cast<octave_idx_type> (0)); } -Matrix -SparseMatrix::lssolve (const Matrix& b) const -{ - octave_idx_type info; - octave_idx_type rank; - return lssolve (b, info, rank); -} - -Matrix -SparseMatrix::lssolve (const Matrix& b, octave_idx_type& info) const -{ - octave_idx_type rank; - return lssolve (b, info, rank); -} - -Matrix -SparseMatrix::lssolve (const Matrix& b, octave_idx_type& info, octave_idx_type&) const -{ - return qrsolve (*this, b, info); -} - -SparseMatrix -SparseMatrix::lssolve (const SparseMatrix& b) const -{ - octave_idx_type info; - octave_idx_type rank; - return lssolve (b, info, rank); -} - -SparseMatrix -SparseMatrix::lssolve (const SparseMatrix& b, octave_idx_type& info) const -{ - octave_idx_type rank; - return lssolve (b, info, rank); -} - -SparseMatrix -SparseMatrix::lssolve (const SparseMatrix& b, octave_idx_type& info, octave_idx_type&) const -{ - return qrsolve (*this, b, info); -} - -ComplexMatrix -SparseMatrix::lssolve (const ComplexMatrix& b) const -{ - octave_idx_type info; - octave_idx_type rank; - return lssolve (b, info, rank); -} - -ComplexMatrix -SparseMatrix::lssolve (const ComplexMatrix& b, octave_idx_type& info) const -{ - octave_idx_type rank; - return lssolve (b, info, rank); -} - -ComplexMatrix -SparseMatrix::lssolve (const ComplexMatrix& b, octave_idx_type& info, octave_idx_type&) const -{ - return qrsolve (*this, b, info); -} - -SparseComplexMatrix -SparseMatrix::lssolve (const SparseComplexMatrix& b) const -{ - octave_idx_type info; - octave_idx_type rank; - return lssolve (b, info, rank); -} - -SparseComplexMatrix -SparseMatrix::lssolve (const SparseComplexMatrix& b, octave_idx_type& info) const -{ - octave_idx_type rank; - return lssolve (b, info, rank); -} - -SparseComplexMatrix -SparseMatrix::lssolve (const SparseComplexMatrix& b, octave_idx_type& info, - octave_idx_type&) const -{ - return qrsolve (*this, b, info); -} - -ColumnVector -SparseMatrix::lssolve (const ColumnVector& b) const -{ - octave_idx_type info; - octave_idx_type rank; - return lssolve (b, info, rank); -} - -ColumnVector -SparseMatrix::lssolve (const ColumnVector& b, octave_idx_type& info) const -{ - octave_idx_type rank; - return lssolve (b, info, rank); -} - -ColumnVector -SparseMatrix::lssolve (const ColumnVector& b, octave_idx_type& info, octave_idx_type& rank) const -{ - Matrix tmp (b); - return lssolve (tmp, info, rank).column (static_cast<octave_idx_type> (0)); -} - -ComplexColumnVector -SparseMatrix::lssolve (const ComplexColumnVector& b) const -{ - octave_idx_type info; - octave_idx_type rank; - return lssolve (b, info, rank); -} - -ComplexColumnVector -SparseMatrix::lssolve (const ComplexColumnVector& b, octave_idx_type& info) const -{ - octave_idx_type rank; - return lssolve (b, info, rank); -} - -ComplexColumnVector -SparseMatrix::lssolve (const ComplexColumnVector& b, octave_idx_type& info, - octave_idx_type& rank) const -{ - ComplexMatrix tmp (b); - return lssolve (tmp, info, rank).column (static_cast<octave_idx_type> (0)); -} - // other operations. SparseMatrix @@ -6840,7 +7385,7 @@ { octave_idx_type nr = rows (); octave_idx_type nc = cols (); - octave_idx_type nz = nzmax (); + octave_idx_type nz = nnz (); bool f_zero = (f(0.0) == 0.0); // Count number of non-zero elements @@ -6890,7 +7435,7 @@ { octave_idx_type nr = rows (); octave_idx_type nc = cols (); - octave_idx_type nz = nzmax (); + octave_idx_type nz = nnz (); bool f_zero = f(0.0); // Count number of non-zero elements @@ -6945,7 +7490,7 @@ bool SparseMatrix::any_element_is_negative (bool neg_zero) const { - octave_idx_type nel = nzmax (); + octave_idx_type nel = nnz (); if (neg_zero) { @@ -6966,7 +7511,7 @@ bool SparseMatrix::any_element_is_inf_or_nan (void) const { - octave_idx_type nel = nzmax (); + octave_idx_type nel = nnz (); for (octave_idx_type i = 0; i < nel; i++) { @@ -6981,7 +7526,7 @@ bool SparseMatrix::all_elements_are_int_or_inf_or_nan (void) const { - octave_idx_type nel = nzmax (); + octave_idx_type nel = nnz (); for (octave_idx_type i = 0; i < nel; i++) { @@ -7001,7 +7546,7 @@ bool SparseMatrix::all_integers (double& max_val, double& min_val) const { - octave_idx_type nel = nzmax (); + octave_idx_type nel = nnz (); if (nel == 0) return false; @@ -7029,7 +7574,7 @@ bool SparseMatrix::too_large_for_float (void) const { - octave_idx_type nel = nzmax (); + octave_idx_type nel = nnz (); for (octave_idx_type i = 0; i < nel; i++) { @@ -7047,7 +7592,7 @@ { octave_idx_type nr = rows (); octave_idx_type nc = cols (); - octave_idx_type nz1 = nzmax (); + octave_idx_type nz1 = nnz (); octave_idx_type nz2 = nr*nc - nz1; SparseBoolMatrix r (nr, nc, nz2); @@ -7133,7 +7678,7 @@ SparseMatrix SparseMatrix::abs (void) const { - octave_idx_type nz = nzmax (); + octave_idx_type nz = nnz (); SparseMatrix retval (*this); @@ -7359,32 +7904,19 @@ SparseMatrix operator * (const SparseMatrix& m, const SparseMatrix& a) { -#ifdef HAVE_SPARSE_BLAS - // XXX FIXME XXX Isn't there a sparse BLAS ?? Is it faster?? -#else - // Use Andy's sparse matrix multiply function - SPARSE_SPARSE_MUL (SparseMatrix, double); -#endif + SPARSE_SPARSE_MUL (SparseMatrix, double, double); } Matrix operator * (const Matrix& m, const SparseMatrix& a) { -#ifdef HAVE_SPARSE_BLAS - // XXX FIXME XXX Isn't there a sparse BLAS ?? Is it faster?? -#else - FULL_SPARSE_MUL (Matrix, double); -#endif + FULL_SPARSE_MUL (Matrix, double, 0.); } Matrix operator * (const SparseMatrix& m, const Matrix& a) { -#ifdef HAVE_SPARSE_BLAS - // XXX FIXME XXX Isn't there a sparse BLAS ?? Is it faster?? -#else - SPARSE_FULL_MUL (Matrix, double); -#endif + SPARSE_FULL_MUL (Matrix, double, 0.); } // XXX FIXME XXX -- it would be nice to share code among the min/max @@ -7474,7 +8006,7 @@ gripe_nonconformant ("min", a_nr, a_nc, b_nr, b_nc); else { - r = SparseMatrix (a_nr, a_nc, (a.nzmax () + b.nzmax ())); + r = SparseMatrix (a_nr, a_nc, (a.nnz () + b.nnz ())); octave_idx_type jx = 0; r.cidx (0) = 0; @@ -7624,7 +8156,7 @@ gripe_nonconformant ("min", a_nr, a_nc, b_nr, b_nc); else { - r = SparseMatrix (a_nr, a_nc, (a.nzmax () + b.nzmax ())); + r = SparseMatrix (a_nr, a_nc, (a.nnz () + b.nnz ())); octave_idx_type jx = 0; r.cidx (0) = 0;
--- a/liboctave/dSparse.h +++ b/liboctave/dSparse.h @@ -136,91 +136,128 @@ private: // Diagonal matrix solvers - Matrix dsolve (SparseType &typ, const Matrix& b, octave_idx_type& info, double& rcond, - solve_singularity_handler sing_handler) const; + Matrix dsolve (SparseType &typ, const Matrix& b, octave_idx_type& info, + double& rcond, solve_singularity_handler sing_handler, + bool calc_cond = false) const; - ComplexMatrix dsolve (SparseType &typ, const ComplexMatrix& b, octave_idx_type& info, - double& rcond, solve_singularity_handler sing_handler) const; + ComplexMatrix dsolve (SparseType &typ, const ComplexMatrix& b, + octave_idx_type& info, double& rcond, + solve_singularity_handler sing_handler, + bool calc_cond = false) const; - SparseMatrix dsolve (SparseType &typ, const SparseMatrix& b, octave_idx_type& info, - double& rcond, solve_singularity_handler sing_handler) const; + SparseMatrix dsolve (SparseType &typ, const SparseMatrix& b, + octave_idx_type& info, double& rcond, + solve_singularity_handler sing_handler, + bool calc_cond = false) const; SparseComplexMatrix dsolve (SparseType &typ, const SparseComplexMatrix& b, octave_idx_type& info, double& rcond, - solve_singularity_handler sing_handler) const; + solve_singularity_handler sing_handler, + bool calc_cond = false) const; // Upper triangular matrix solvers - Matrix utsolve (SparseType &typ, const Matrix& b, octave_idx_type& info, double& rcond, - solve_singularity_handler sing_handler) const; + Matrix utsolve (SparseType &typ, const Matrix& b, octave_idx_type& info, + double& rcond, solve_singularity_handler sing_handler, + bool calc_cond = false) const; - ComplexMatrix utsolve (SparseType &typ, const ComplexMatrix& b, octave_idx_type& info, - double& rcond, solve_singularity_handler sing_handler) const; + ComplexMatrix utsolve (SparseType &typ, const ComplexMatrix& b, + octave_idx_type& info, double& rcond, + solve_singularity_handler sing_handler, + bool calc_cond = false) const; - SparseMatrix utsolve (SparseType &typ, const SparseMatrix& b, octave_idx_type& info, - double& rcond, solve_singularity_handler sing_handler) const; + SparseMatrix utsolve (SparseType &typ, const SparseMatrix& b, + octave_idx_type& info, double& rcond, + solve_singularity_handler sing_handler, + bool calc_cond = false) const; SparseComplexMatrix utsolve (SparseType &typ, const SparseComplexMatrix& b, octave_idx_type& info, double& rcond, - solve_singularity_handler sing_handler) const; + solve_singularity_handler sing_handler, + bool calc_cond = false) const; // Lower triangular matrix solvers - Matrix ltsolve (SparseType &typ, const Matrix& b, octave_idx_type& info, double& rcond, - solve_singularity_handler sing_handler) const; + Matrix ltsolve (SparseType &typ, const Matrix& b, octave_idx_type& info, + double& rcond, solve_singularity_handler sing_handler, + bool calc_cond = false) const; - ComplexMatrix ltsolve (SparseType &typ, const ComplexMatrix& b, octave_idx_type& info, - double& rcond, solve_singularity_handler sing_handler) const; + ComplexMatrix ltsolve (SparseType &typ, const ComplexMatrix& b, + octave_idx_type& info, double& rcond, + solve_singularity_handler sing_handler, + bool calc_cond = false) const; - SparseMatrix ltsolve (SparseType &typ, const SparseMatrix& b, octave_idx_type& info, - double& rcond, solve_singularity_handler sing_handler) const; + SparseMatrix ltsolve (SparseType &typ, const SparseMatrix& b, + octave_idx_type& info, double& rcond, + solve_singularity_handler sing_handler, + bool calc_cond = false) const; SparseComplexMatrix ltsolve (SparseType &typ, const SparseComplexMatrix& b, octave_idx_type& info, double& rcond, - solve_singularity_handler sing_handler) const; + solve_singularity_handler sing_handler, + bool calc_cond = false) const; // Tridiagonal matrix solvers - Matrix trisolve (SparseType &typ, const Matrix& b, octave_idx_type& info, double& rcond, - solve_singularity_handler sing_handler) const; + Matrix trisolve (SparseType &typ, const Matrix& b, octave_idx_type& info, + double& rcond, solve_singularity_handler sing_handler, + bool calc_cond = false) const; - ComplexMatrix trisolve (SparseType &typ, const ComplexMatrix& b, octave_idx_type& info, - double& rcond, solve_singularity_handler sing_handler) const; + ComplexMatrix trisolve (SparseType &typ, const ComplexMatrix& b, + octave_idx_type& info, double& rcond, + solve_singularity_handler sing_handler, + bool calc_cond = false) const; - SparseMatrix trisolve (SparseType &typ, const SparseMatrix& b, octave_idx_type& info, - double& rcond, solve_singularity_handler sing_handler) const; + SparseMatrix trisolve (SparseType &typ, const SparseMatrix& b, + octave_idx_type& info, double& rcond, + solve_singularity_handler sing_handler, + bool calc_cond = false) const; SparseComplexMatrix trisolve (SparseType &typ, const SparseComplexMatrix& b, octave_idx_type& info, double& rcond, - solve_singularity_handler sing_handler) const; + solve_singularity_handler sing_handler, + bool calc_cond = false) const; // Banded matrix solvers (umfpack/cholesky) - Matrix bsolve (SparseType &typ, const Matrix& b, octave_idx_type& info, double& rcond, - solve_singularity_handler sing_handler) const; + Matrix bsolve (SparseType &typ, const Matrix& b, octave_idx_type& info, + double& rcond, solve_singularity_handler sing_handler, + bool calc_cond = false) const; - ComplexMatrix bsolve (SparseType &typ, const ComplexMatrix& b, octave_idx_type& info, - double& rcond, solve_singularity_handler sing_handler) const; + ComplexMatrix bsolve (SparseType &typ, const ComplexMatrix& b, + octave_idx_type& info, double& rcond, + solve_singularity_handler sing_handler, + bool calc_cond = false) const; - SparseMatrix bsolve (SparseType &typ, const SparseMatrix& b, octave_idx_type& info, - double& rcond, solve_singularity_handler sing_handler) const; + SparseMatrix bsolve (SparseType &typ, const SparseMatrix& b, + octave_idx_type& info, double& rcond, + solve_singularity_handler sing_handler, + bool calc_cond = false) const; SparseComplexMatrix bsolve (SparseType &typ, const SparseComplexMatrix& b, octave_idx_type& info, double& rcond, - solve_singularity_handler sing_handler) const; + solve_singularity_handler sing_handler, + bool calc_cond = false) const; // Full matrix solvers (umfpack/cholesky) - void * factorize (octave_idx_type& err, double &rcond, Matrix &Control, Matrix &Info, - solve_singularity_handler sing_handler) const; + void * factorize (octave_idx_type& err, double &rcond, Matrix &Control, + Matrix &Info, solve_singularity_handler sing_handler, + bool calc_cond = false) const; - Matrix fsolve (SparseType &typ, const Matrix& b, octave_idx_type& info, double& rcond, - solve_singularity_handler sing_handler) const; + Matrix fsolve (SparseType &typ, const Matrix& b, octave_idx_type& info, + double& rcond, solve_singularity_handler sing_handler, + bool calc_cond = false) const; - ComplexMatrix fsolve (SparseType &typ, const ComplexMatrix& b, octave_idx_type& info, - double& rcond, solve_singularity_handler sing_handler) const; + ComplexMatrix fsolve (SparseType &typ, const ComplexMatrix& b, + octave_idx_type& info, double& rcond, + solve_singularity_handler sing_handler, + bool calc_cond = false) const; - SparseMatrix fsolve (SparseType &typ, const SparseMatrix& b, octave_idx_type& info, - double& rcond, solve_singularity_handler sing_handler) const; + SparseMatrix fsolve (SparseType &typ, const SparseMatrix& b, + octave_idx_type& info, double& rcond, + solve_singularity_handler sing_handler, + bool calc_cond = false) const; SparseComplexMatrix fsolve (SparseType &typ, const SparseComplexMatrix& b, - octave_idx_type& info, double& rcond, - solve_singularity_handler sing_handler) const; + octave_idx_type& info, double& rcond, + solve_singularity_handler sing_handler, + bool calc_cond = false) const; public: // Generic interface to solver with no probing of type @@ -317,35 +354,6 @@ double& rcond, solve_singularity_handler sing_handler) const; - // Minimum-norm solvers - Matrix lssolve (const Matrix& b) const; - Matrix lssolve (const Matrix& b, octave_idx_type& info) const; - Matrix lssolve (const Matrix& b, octave_idx_type& info, octave_idx_type& rank) const; - - ComplexMatrix lssolve (const ComplexMatrix& b) const; - ComplexMatrix lssolve (const ComplexMatrix& b, octave_idx_type& info) const; - ComplexMatrix lssolve (const ComplexMatrix& b, octave_idx_type& info, - octave_idx_type& rank) const; - - SparseMatrix lssolve (const SparseMatrix& b) const; - SparseMatrix lssolve (const SparseMatrix& b, octave_idx_type& info) const; - SparseMatrix lssolve (const SparseMatrix& b, octave_idx_type& info, octave_idx_type& rank) const; - - SparseComplexMatrix lssolve (const SparseComplexMatrix& b) const; - SparseComplexMatrix lssolve (const SparseComplexMatrix& b, - octave_idx_type& info) const; - SparseComplexMatrix lssolve (const SparseComplexMatrix& b, octave_idx_type& info, - octave_idx_type& rank) const; - - ColumnVector lssolve (const ColumnVector& b) const; - ColumnVector lssolve (const ColumnVector& b, octave_idx_type& info) const; - ColumnVector lssolve (const ColumnVector& b, octave_idx_type& info, octave_idx_type& rank) const; - - ComplexColumnVector lssolve (const ComplexColumnVector& b) const; - ComplexColumnVector lssolve (const ComplexColumnVector& b, octave_idx_type& info) const; - ComplexColumnVector lssolve (const ComplexColumnVector& b, octave_idx_type& info, - octave_idx_type& rank) const; - // other operations SparseMatrix map (d_d_Mapper f) const; SparseBoolMatrix map (b_d_Mapper f) const;
--- a/scripts/ChangeLog +++ b/scripts/ChangeLog @@ -1,3 +1,11 @@ +2006-03-16 David Bateman <dbateman@free.fr> + + * testfun/test.m: Clear last warning before warning test to avoid + issues with previously set warnings. + * build_sparse_test.sh: Tests for multiple RHS for rectanguar + sparse matrices. Force matrix type from spqr solution to be + singular to force QR solvers to be used for assert. + 2006-03-16 William Poetra Yoga Hadisoeseno <williampoetra@gmail.com> * strings/strfind.m: New file.
--- a/scripts/testfun/test.m +++ b/scripts/testfun/test.m @@ -607,6 +607,9 @@ %!error test("test", 'bogus'); # test without pattern +%!test +%! lastwarn(); # clear last warning just in case + %!warning <warning message> warning('warning message') %!## test of shared variables
--- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,18 @@ +2006-03-16 David Bateman <dbateman@free.fr> + + * sparse-xdiv.cc (result_ok): delete. + (xdiv, xleftdiv): Simplify to use version of SpareMatrix::solve + and SparseComplexMatrix::solve which internally treats rectangular + and singular matrices. + * DLD-FUNCTIONS/luinc.cc: Remove error test for singular matrix as + QR solver now implemented. + * DLD-FUNCTIONS/matrix_type.cc (Fmatrix_type): Paranoid check on + error_state. Disable tests for the detection of underdetermined + lower and over-determined upper matrix due to problems with + non minimum norm solutions. + * DLD-FUNCTIONS/spqr.cc: Warning for issue of use of Fspqr for + under-determined problems. + 2006-03-16 John W. Eaton <jwe@octave.org> * __gnuplot_raw__.l: Move here from DLD-FUNCTIONS/__gnuplot_raw__.l.
--- a/src/DLD-FUNCTIONS/luinc.cc +++ b/src/DLD-FUNCTIONS/luinc.cc @@ -296,8 +296,6 @@ %! [l,u]=luinc(a,opts); %! assert(l*u, sparse([1i,2,0,0;0,1,2,0;0,0,3,0;0,0,0,1]),1e-10); -%!error splu(sparse([1i,2,0,0;0,1,2,0;1e-14,0,3,0;0,0,0,1])); - */ /*
--- a/src/DLD-FUNCTIONS/matrix_type.cc +++ b/src/DLD-FUNCTIONS/matrix_type.cc @@ -118,8 +118,13 @@ if (mattyp.is_unknown ()) { - mattyp = SparseType (args(0).sparse_complex_matrix_value ()); - ((octave_sparse_complex_matrix &)rep).sparse_type (mattyp); + SparseComplexMatrix m = + args(0).sparse_complex_matrix_value (); + if (!error_state) + { + mattyp = SparseType (m); + ((octave_sparse_complex_matrix &)rep).sparse_type (mattyp); + } } } else @@ -128,8 +133,12 @@ if (mattyp.is_unknown ()) { - mattyp = SparseType (args(0).sparse_matrix_value ()); - ((octave_sparse_matrix &)rep).sparse_type (mattyp); + SparseMatrix m = args(0).sparse_matrix_value (); + if (!error_state) + { + mattyp = SparseType (m); + ((octave_sparse_matrix &)rep).sparse_type (mattyp); + } } } @@ -291,6 +300,11 @@ } /* + +## XXX FIXME XXX +## Disable tests for lower under-determined and upper over-determined +## matrices and this detection is disabled in SparseType due to issues +## of non minimum norm solution being found. %!assert(matrix_type(speye(10,10)),"Diagonal"); %!assert(matrix_type(speye(10,10)([2:10,1],:)),"Permuted Diagonal"); @@ -320,12 +334,12 @@ %!assert(matrix_type(speye(10,11)([2:10,1],:)),"Permuted Diagonal"); %!assert(matrix_type(speye(11,10)),"Diagonal"); %!assert(matrix_type(speye(11,10)([2:11,1],:)),"Permuted Diagonal"); -%!assert(matrix_type([[speye(10,10);sparse(1,10)],[[1,1];sparse(9,2);[1,1]]]),"Upper"); -%!assert(matrix_type([[speye(10,10);sparse(1,10)],[[1,1];sparse(9,2);[1,1]]](:,[2,1,3:12])),"Permuted Upper"); +%#!assert(matrix_type([[speye(10,10);sparse(1,10)],[[1,1];sparse(9,2);[1,1]]]),"Upper"); +%#!assert(matrix_type([[speye(10,10);sparse(1,10)],[[1,1];sparse(9,2);[1,1]]](:,[2,1,3:12])),"Permuted Upper"); %!assert(matrix_type([speye(11,9),[1;sparse(8,1);1;0]]),"Upper"); %!assert(matrix_type([speye(11,9),[1;sparse(8,1);1;0]](:,[2,1,3:10])),"Permuted Upper"); -%!assert(matrix_type([speye(10,10),sparse(10,1);[1;1],sparse(2,9),[1;1]]),"Lower"); -%!assert(matrix_type([speye(10,10),sparse(10,1);[1;1],sparse(2,9),[1;1]]([2,1,3:12],:)),"Permuted Lower"); +%#!assert(matrix_type([speye(10,10),sparse(10,1);[1;1],sparse(2,9),[1;1]]),"Lower"); +%#!assert(matrix_type([speye(10,10),sparse(10,1);[1;1],sparse(2,9),[1;1]]([2,1,3:12],:)),"Permuted Lower"); %!assert(matrix_type([speye(9,11);[1,sparse(1,8),1,0]]),"Lower"); %!assert(matrix_type([speye(9,11);[1,sparse(1,8),1,0]]([2,1,3:10],:)),"Permuted Lower"); %!assert(matrix_type(spdiags(randn(10,4),[-2:1],10,9)),"Rectangular") @@ -358,12 +372,12 @@ %!assert(matrix_type(1i*speye(10,11)([2:10,1],:)),"Permuted Diagonal"); %!assert(matrix_type(1i*speye(11,10)),"Diagonal"); %!assert(matrix_type(1i*speye(11,10)([2:11,1],:)),"Permuted Diagonal"); -%!assert(matrix_type([[speye(10,10);sparse(1,10)],[[1i,1i];sparse(9,2);[1i,1i]]]),"Upper"); -%!assert(matrix_type([[speye(10,10);sparse(1,10)],[[1i,1i];sparse(9,2);[1i,1i]]](:,[2,1,3:12])),"Permuted Upper"); +%#!assert(matrix_type([[speye(10,10);sparse(1,10)],[[1i,1i];sparse(9,2);[1i,1i]]]),"Upper"); +%#!assert(matrix_type([[speye(10,10);sparse(1,10)],[[1i,1i];sparse(9,2);[1i,1i]]](:,[2,1,3:12])),"Permuted Upper"); %!assert(matrix_type([speye(11,9),[1i;sparse(8,1);1i;0]]),"Upper"); %!assert(matrix_type([speye(11,9),[1i;sparse(8,1);1i;0]](:,[2,1,3:10])),"Permuted Upper"); -%!assert(matrix_type([speye(10,10),sparse(10,1);[1i;1i],sparse(2,9),[1i;1i]]),"Lower"); -%!assert(matrix_type([speye(10,10),sparse(10,1);[1i;1i],sparse(2,9),[1i;1i]]([2,1,3:12],:)),"Permuted Lower"); +%#!assert(matrix_type([speye(10,10),sparse(10,1);[1i;1i],sparse(2,9),[1i;1i]]),"Lower"); +%#!assert(matrix_type([speye(10,10),sparse(10,1);[1i;1i],sparse(2,9),[1i;1i]]([2,1,3:12],:)),"Permuted Lower"); %!assert(matrix_type([speye(9,11);[1i,sparse(1,8),1i,0]]),"Lower"); %!assert(matrix_type([speye(9,11);[1i,sparse(1,8),1i,0]]([2,1,3:10],:)),"Permuted Lower"); %!assert(matrix_type(1i*spdiags(randn(10,4),[-2:1],10,9)),"Rectangular")
--- a/src/DLD-FUNCTIONS/spqr.cc +++ b/src/DLD-FUNCTIONS/spqr.cc @@ -114,6 +114,8 @@ { retval(1) = q.R (economy); retval(0) = q.C (args(1).complex_matrix_value ()); + if (args(0).rows() < args(0).columns()) + warning ("spqr: non minimum norm solution for under-determined problem"); } else retval(0) = q.R (economy); @@ -128,6 +130,8 @@ { retval(1) = q.R (economy); retval(0) = q.C (args(1).matrix_value ()); + if (args(0).rows() < args(0).columns()) + warning ("spqr: non minimum norm solution for under-determined problem"); } else retval(0) = q.R (economy);
--- a/src/sparse-xdiv.cc +++ b/src/sparse-xdiv.cc @@ -36,12 +36,6 @@ #include "oct-spparms.h" #include "sparse-xdiv.h" -static inline bool -result_ok (octave_idx_type info) -{ - return (info != -2 && info != -1); -} - static void solve_singularity_warning (double rcond) { @@ -132,24 +126,11 @@ SparseType btyp = typ.transpose (); octave_idx_type info; - if (btmp.rows () == btmp.columns ()) - { - double rcond = 0.0; - - Matrix result = btmp.solve (btyp, atmp, info, rcond, - solve_singularity_warning); + double rcond = 0.0; + Matrix result = btmp.solve (btyp, atmp, info, rcond, + solve_singularity_warning); - if (result_ok (info)) - { - typ = btyp.transpose (); - return Matrix (result.transpose ()); - } - } - - octave_idx_type rank; - Matrix result = btmp.lssolve (atmp, info, rank); typ = btyp.transpose (); - return result.transpose (); } @@ -165,24 +146,11 @@ SparseType btyp = typ.transpose (); octave_idx_type info; - if (btmp.rows () == btmp.columns ()) - { - double rcond = 0.0; - - ComplexMatrix result - = btmp.solve (btyp, atmp, info, rcond, solve_singularity_warning); + double rcond = 0.0; + ComplexMatrix result + = btmp.solve (btyp, atmp, info, rcond, solve_singularity_warning); - if (result_ok (info)) - { - typ = btyp.transpose (); - return result.hermitian (); - } - } - - octave_idx_type rank; - ComplexMatrix result = btmp.lssolve (atmp, info, rank); typ = btyp.transpose (); - return result.hermitian (); } @@ -198,24 +166,11 @@ SparseType btyp = typ.transpose (); octave_idx_type info; - if (btmp.rows () == btmp.columns ()) - { - double rcond = 0.0; - - ComplexMatrix result - = btmp.solve (btyp, atmp, info, rcond, solve_singularity_warning); + double rcond = 0.0; + ComplexMatrix result + = btmp.solve (btyp, atmp, info, rcond, solve_singularity_warning); - if (result_ok (info)) - { - typ = btyp.transpose (); - return result.hermitian (); - } - } - - octave_idx_type rank; - ComplexMatrix result = btmp.lssolve (atmp, info, rank); typ = btyp.transpose (); - return result.hermitian (); } @@ -231,24 +186,11 @@ SparseType btyp = typ.transpose (); octave_idx_type info; - if (btmp.rows () == btmp.columns ()) - { - double rcond = 0.0; - - ComplexMatrix result - = btmp.solve (btyp, atmp, info, rcond, solve_singularity_warning); + double rcond = 0.0; + ComplexMatrix result + = btmp.solve (btyp, atmp, info, rcond, solve_singularity_warning); - if (result_ok (info)) - { - typ = btyp.transpose (); - return result.hermitian (); - } - } - - octave_idx_type rank; - ComplexMatrix result = btmp.lssolve (atmp, info, rank); typ = btyp.transpose (); - return result.hermitian (); } @@ -264,24 +206,11 @@ SparseType btyp = typ.transpose (); octave_idx_type info; - if (btmp.rows () == btmp.columns ()) - { - double rcond = 0.0; - - SparseMatrix result = btmp.solve (btyp, atmp, info, rcond, - solve_singularity_warning); + double rcond = 0.0; + SparseMatrix result = btmp.solve (btyp, atmp, info, rcond, + solve_singularity_warning); - if (result_ok (info)) - { - typ = btyp.transpose (); - return SparseMatrix (result.transpose ()); - } - } - - octave_idx_type rank; - SparseMatrix result = btmp.lssolve (atmp, info, rank); typ = btyp.transpose (); - return result.transpose (); } @@ -297,24 +226,11 @@ SparseType btyp = typ.transpose (); octave_idx_type info; - if (btmp.rows () == btmp.columns ()) - { - double rcond = 0.0; - - SparseComplexMatrix result - = btmp.solve (btyp, atmp, info, rcond, solve_singularity_warning); + double rcond = 0.0; + SparseComplexMatrix result + = btmp.solve (btyp, atmp, info, rcond, solve_singularity_warning); - if (result_ok (info)) - { - typ = btyp.transpose (); - return result.hermitian (); - } - } - - octave_idx_type rank; - SparseComplexMatrix result = btmp.lssolve (atmp, info, rank); typ = btyp.transpose (); - return result.hermitian (); } @@ -330,24 +246,11 @@ SparseType btyp = typ.transpose (); octave_idx_type info; - if (btmp.rows () == btmp.columns ()) - { - double rcond = 0.0; - - SparseComplexMatrix result - = btmp.solve (btyp, atmp, info, rcond, solve_singularity_warning); + double rcond = 0.0; + SparseComplexMatrix result + = btmp.solve (btyp, atmp, info, rcond, solve_singularity_warning); - if (result_ok (info)) - { - typ = btyp.transpose (); - return result.hermitian (); - } - } - - octave_idx_type rank; - SparseComplexMatrix result = btmp.lssolve (atmp, info, rank); typ = btyp.transpose (); - return result.hermitian (); } @@ -363,24 +266,11 @@ SparseType btyp = typ.transpose (); octave_idx_type info; - if (btmp.rows () == btmp.columns ()) - { - double rcond = 0.0; - - SparseComplexMatrix result - = btmp.solve (btyp, atmp, info, rcond, solve_singularity_warning); + double rcond = 0.0; + SparseComplexMatrix result + = btmp.solve (btyp, atmp, info, rcond, solve_singularity_warning); - if (result_ok (info)) - { - typ = btyp.transpose (); - return result.hermitian (); - } - } - - octave_idx_type rank; - SparseComplexMatrix result = btmp.lssolve (atmp, info, rank); typ = btyp.transpose (); - return result.hermitian (); } @@ -493,19 +383,8 @@ return Matrix (); octave_idx_type info; - if (a.rows () == a.columns ()) - { - double rcond = 0.0; - - Matrix result - = a.solve (typ, b, info, rcond, solve_singularity_warning); - - if (result_ok (info)) - return result; - } - - octave_idx_type rank; - return a.lssolve (b, info, rank); + double rcond = 0.0; + return a.solve (typ, b, info, rcond, solve_singularity_warning); } // -*- 2 -*- @@ -516,19 +395,8 @@ return ComplexMatrix (); octave_idx_type info; - if (a.rows () == a.columns ()) - { - double rcond = 0.0; - - ComplexMatrix result - = a.solve (typ, b, info, rcond, solve_singularity_warning); - - if (result_ok (info)) - return result; - } - - octave_idx_type rank; - return a.lssolve (b, info, rank); + double rcond = 0.0; + return a.solve (typ, b, info, rcond, solve_singularity_warning); } // -*- 3 -*- @@ -539,19 +407,8 @@ return SparseMatrix (); octave_idx_type info; - if (a.rows () == a.columns ()) - { - double rcond = 0.0; - - SparseMatrix result - = a.solve (typ, b, info, rcond, solve_singularity_warning); - - if (result_ok (info)) - return result; - } - - octave_idx_type rank; - return a.lssolve (b, info, rank); + double rcond = 0.0; + return a.solve (typ, b, info, rcond, solve_singularity_warning); } // -*- 4 -*- @@ -562,19 +419,8 @@ return SparseComplexMatrix (); octave_idx_type info; - if (a.rows () == a.columns ()) - { - double rcond = 0.0; - - SparseComplexMatrix result - = a.solve (typ, b, info, rcond, solve_singularity_warning); - - if (result_ok (info)) - return result; - } - - octave_idx_type rank; - return a.lssolve (b, info, rank); + double rcond = 0.0; + return a.solve (typ, b, info, rcond, solve_singularity_warning); } // -*- 5 -*- @@ -585,19 +431,8 @@ return ComplexMatrix (); octave_idx_type info; - if (a.rows () == a.columns ()) - { - double rcond = 0.0; - - ComplexMatrix result - = a.solve (typ, b, info, rcond, solve_singularity_warning); - - if (result_ok (info)) - return result; - } - - octave_idx_type rank; - return a.lssolve (b, info, rank); + double rcond = 0.0; + return a.solve (typ, b, info, rcond, solve_singularity_warning); } // -*- 6 -*- @@ -608,19 +443,8 @@ return ComplexMatrix (); octave_idx_type info; - if (a.rows () == a.columns ()) - { - double rcond = 0.0; - - ComplexMatrix result - = a.solve (typ, b, info, rcond, solve_singularity_warning); - - if (result_ok (info)) - return result; - } - - octave_idx_type rank; - return a.lssolve (b, info, rank); + double rcond = 0.0; + return a.solve (typ, b, info, rcond, solve_singularity_warning); } // -*- 7 -*- @@ -631,19 +455,8 @@ return SparseComplexMatrix (); octave_idx_type info; - if (a.rows () == a.columns ()) - { - double rcond = 0.0; - - SparseComplexMatrix result - = a.solve (typ, b, info, rcond, solve_singularity_warning); - - if (result_ok (info)) - return result; - } - - octave_idx_type rank; - return a.lssolve (b, info, rank); + double rcond = 0.0; + return a.solve (typ, b, info, rcond, solve_singularity_warning); } // -*- 8 -*- @@ -655,19 +468,8 @@ return SparseComplexMatrix (); octave_idx_type info; - if (a.rows () == a.columns ()) - { - double rcond = 0.0; - - SparseComplexMatrix result - = a.solve (typ, b, info, rcond, solve_singularity_warning); - - if (result_ok (info)) - return result; - } - - octave_idx_type rank; - return a.lssolve (b, info, rank); + double rcond = 0.0; + return a.solve (typ, b, info, rcond, solve_singularity_warning); } /*
--- a/test/build_sparse_tests.sh +++ b/test/build_sparse_tests.sh @@ -935,7 +935,7 @@ %!test %! ds = alpha * spdiags([1:11]',0,10,11); %! df = full(ds); -%! xf = beta * ones(10,1); +%! xf = beta * ones(10,2); %! xs = speye(10,10); %!assert(ds\xf,df\xf,100*eps) %!assert(ds\xs,sparse(df\xs,true),100*eps) @@ -947,7 +947,7 @@ %!test %! ds = alpha * spdiags([1:11]',0,11,10); %! df = full(ds); -%! xf = beta * ones(11,1); +%! xf = beta * ones(11,2); %! xs = speye(11,11); %!assert(ds\xf,df\xf,100*eps) %!assert(ds\xs,sparse(df\xs,true),100*eps) @@ -971,18 +971,21 @@ %! assert(us\xf,r\c,100*eps) %!test %! [c,r] = spqr (us, xs); +%! r = matrix_type(r,"Singular"); ## Force Matrix Type %! assert(us\xs,r\c,100*eps) %!test %! pus = us(:,[1:8,10,9]); %!test %! [c,r] = spqr (pus, xf); +%! r = matrix_type(r,"Singular"); ## Force Matrix Type %! assert(pus\xf,r\c,100*eps) %!test %! [c,r] = spqr (pus, xs); +%! r = matrix_type(r,"Singular"); ## Force Matrix Type %! assert(pus\xs,r\c,100*eps) %!test %! ls = alpha*[speye(9,11);[1,sparse(1,8),1,0]]; -%! xf = beta * ones(10,1); +%! xf = beta * ones(10,2); %! xs = speye(10,10); %!assert(ls*(ls\xf),xf,100*eps) %!assert(ls*(ls\xs),xs,100*eps) @@ -992,21 +995,24 @@ %!assert(pls*(pls\xs),xs,100*eps) %!test %! ls = alpha*[speye(10,10),sparse(10,1);[1;1],sparse(2,9),[1;1]]; -%! xf = beta * ones(12,1); +%! xf = beta * ones(12,2); %! xs = speye(12,12); %!test %! [c,r] = spqr (ls, xf); %! assert(ls\xf,r\c,100*eps) %!test %! [c,r] = spqr (ls, xs); +%! r = matrix_type(r,"Singular"); ## Force Matrix Type %! assert(ls\xs,r\c,100*eps) %!test %! pls = ls(:,[1:8,10,9]); %!test %! [c,r] = spqr (pls, xf); +%! r = matrix_type(r,"Singular"); ## Force Matrix Type %! assert(pls\xf,r\c,100*eps) %!test %! [c,r] = spqr (pls, xs); +%! r = matrix_type(r,"Singular"); ## Force Matrix Type %! assert(pls\xs,r\c,100*eps) EOF