diff liboctave/CSparse.cc @ 5681:233d98d95659

[project @ 2006-03-16 17:48:55 by dbateman]
author dbateman
date Thu, 16 Mar 2006 17:48:56 +0000
parents 69a4f320d95a
children 2fe20065a545
line wrap: on
line diff
--- 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;