comparison 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
comparison
equal deleted inserted replaced
5680:cc6a965ae4ca 5681:233d98d95659
45 #include "SparseCmplxCHOL.h" 45 #include "SparseCmplxCHOL.h"
46 #include "SparseCmplxQR.h" 46 #include "SparseCmplxQR.h"
47 47
48 #include "oct-sort.h" 48 #include "oct-sort.h"
49 49
50 // Define whether to use a basic QR solver or one that uses a Dulmange
51 // Mendelsohn factorization to seperate the problem into under-determined,
52 // well-determined and over-determined parts and solves them seperately
53 #ifndef USE_QRSOLVE
54 #include "sparse-dmsolve.cc"
55 #endif
56
50 // Fortran functions we call. 57 // Fortran functions we call.
51 extern "C" 58 extern "C"
52 { 59 {
53 F77_RET_T 60 F77_RET_T
54 F77_FUNC (zgbtrf, ZGBTRF) (const octave_idx_type&, const octave_idx_type&, const octave_idx_type&, 61 F77_FUNC (zgbtrf, ZGBTRF) (const octave_idx_type&, const octave_idx_type&, const octave_idx_type&,
80 F77_CHAR_ARG_LEN_DECL); 87 F77_CHAR_ARG_LEN_DECL);
81 88
82 F77_RET_T 89 F77_RET_T
83 F77_FUNC (zpbcon, ZPBCON) (F77_CONST_CHAR_ARG_DECL, const octave_idx_type&, 90 F77_FUNC (zpbcon, ZPBCON) (F77_CONST_CHAR_ARG_DECL, const octave_idx_type&,
84 const octave_idx_type&, Complex*, const octave_idx_type&, 91 const octave_idx_type&, Complex*, const octave_idx_type&,
85 const double&, double&, Complex*, octave_idx_type*, octave_idx_type& 92 const double&, double&, Complex*, double*, octave_idx_type&
86 F77_CHAR_ARG_LEN_DECL); 93 F77_CHAR_ARG_LEN_DECL);
87 94
88 F77_RET_T 95 F77_RET_T
89 F77_FUNC (zgttrf, ZGTTRF) (const octave_idx_type&, Complex*, Complex*, Complex*, 96 F77_FUNC (zgttrf, ZGTTRF) (const octave_idx_type&, Complex*, Complex*, Complex*,
90 Complex*, octave_idx_type*, octave_idx_type&); 97 Complex*, octave_idx_type*, octave_idx_type&);
104 F77_FUNC (zgtsv, ZGTSV) (const octave_idx_type&, const octave_idx_type&, Complex*, Complex*, 111 F77_FUNC (zgtsv, ZGTSV) (const octave_idx_type&, const octave_idx_type&, Complex*, Complex*,
105 Complex*, Complex*, const octave_idx_type&, octave_idx_type&); 112 Complex*, Complex*, const octave_idx_type&, octave_idx_type&);
106 } 113 }
107 114
108 SparseComplexMatrix::SparseComplexMatrix (const SparseMatrix& a) 115 SparseComplexMatrix::SparseComplexMatrix (const SparseMatrix& a)
109 : MSparse<Complex> (a.rows (), a.cols (), a.nzmax ()) 116 : MSparse<Complex> (a.rows (), a.cols (), a.nnz ())
110 { 117 {
111 octave_idx_type nc = cols (); 118 octave_idx_type nc = cols ();
112 octave_idx_type nz = nzmax (); 119 octave_idx_type nz = a.nnz ();
113 120
114 for (octave_idx_type i = 0; i < nc + 1; i++) 121 for (octave_idx_type i = 0; i < nc + 1; i++)
115 cidx (i) = a.cidx (i); 122 cidx (i) = a.cidx (i);
116 123
117 for (octave_idx_type i = 0; i < nz; i++) 124 for (octave_idx_type i = 0; i < nz; i++)
118 { 125 {
119 data (i) = a.data (i); 126 data (i) = Complex (a.data (i));
120 ridx (i) = a.ridx (i); 127 ridx (i) = a.ridx (i);
121 } 128 }
122 } 129 }
123 130
124 SparseComplexMatrix::SparseComplexMatrix (const SparseBoolMatrix& a) 131 SparseComplexMatrix::SparseComplexMatrix (const SparseBoolMatrix& a)
125 : MSparse<Complex> (a.rows (), a.cols (), a.nzmax ()) 132 : MSparse<Complex> (a.rows (), a.cols (), a.nnz ())
126 { 133 {
127 octave_idx_type nc = cols (); 134 octave_idx_type nc = cols ();
128 octave_idx_type nz = nzmax (); 135 octave_idx_type nz = a.nnz ();
129 136
130 for (octave_idx_type i = 0; i < nc + 1; i++) 137 for (octave_idx_type i = 0; i < nc + 1; i++)
131 cidx (i) = a.cidx (i); 138 cidx (i) = a.cidx (i);
132 139
133 for (octave_idx_type i = 0; i < nz; i++) 140 for (octave_idx_type i = 0; i < nz; i++)
134 { 141 {
135 data (i) = a.data (i); 142 data (i) = Complex (a.data (i));
136 ridx (i) = a.ridx (i); 143 ridx (i) = a.ridx (i);
137 } 144 }
138 } 145 }
139 146
140 bool 147 bool
141 SparseComplexMatrix::operator == (const SparseComplexMatrix& a) const 148 SparseComplexMatrix::operator == (const SparseComplexMatrix& a) const
142 { 149 {
143 octave_idx_type nr = rows (); 150 octave_idx_type nr = rows ();
144 octave_idx_type nc = cols (); 151 octave_idx_type nc = cols ();
145 octave_idx_type nz = nzmax (); 152 octave_idx_type nz = nnz ();
146 octave_idx_type nr_a = a.rows (); 153 octave_idx_type nr_a = a.rows ();
147 octave_idx_type nc_a = a.cols (); 154 octave_idx_type nc_a = a.cols ();
148 octave_idx_type nz_a = a.nzmax (); 155 octave_idx_type nz_a = a.nnz ();
149 156
150 if (nr != nr_a || nc != nc_a || nz != nz_a) 157 if (nr != nr_a || nc != nc_a || nz != nz_a)
151 return false; 158 return false;
152 159
153 for (octave_idx_type i = 0; i < nc + 1; i++) 160 for (octave_idx_type i = 0; i < nc + 1; i++)
544 SparseComplexMatrix 551 SparseComplexMatrix
545 SparseComplexMatrix::hermitian (void) const 552 SparseComplexMatrix::hermitian (void) const
546 { 553 {
547 octave_idx_type nr = rows (); 554 octave_idx_type nr = rows ();
548 octave_idx_type nc = cols (); 555 octave_idx_type nc = cols ();
549 octave_idx_type nz = nzmax (); 556 octave_idx_type nz = nnz ();
550 SparseComplexMatrix retval (nc, nr, nz); 557 SparseComplexMatrix retval (nc, nr, nz);
551 558
552 OCTAVE_LOCAL_BUFFER (octave_idx_type, w, nr + 1); 559 OCTAVE_LOCAL_BUFFER (octave_idx_type, w, nr + 1);
553 for (octave_idx_type i = 0; i < nr; i++) 560 for (octave_idx_type i = 0; i < nr; i++)
554 w[i] = 0; 561 w[i] = 0;
578 SparseComplexMatrix 585 SparseComplexMatrix
579 conj (const SparseComplexMatrix& a) 586 conj (const SparseComplexMatrix& a)
580 { 587 {
581 octave_idx_type nr = a.rows (); 588 octave_idx_type nr = a.rows ();
582 octave_idx_type nc = a.cols (); 589 octave_idx_type nc = a.cols ();
583 octave_idx_type nz = a.nzmax (); 590 octave_idx_type nz = a.nnz ();
584 SparseComplexMatrix retval (nc, nr, nz); 591 SparseComplexMatrix retval (nc, nr, nz);
585 592
586 for (octave_idx_type i = 0; i < nc + 1; i++) 593 for (octave_idx_type i = 0; i < nc + 1; i++)
587 retval.cidx (i) = a.cidx (i); 594 retval.cidx (i) = a.cidx (i);
588 595
711 } 718 }
712 } 719 }
713 720
714 if (typ == SparseType::Upper || typ == SparseType::Lower) 721 if (typ == SparseType::Upper || typ == SparseType::Lower)
715 { 722 {
716 octave_idx_type nz = nzmax (); 723 octave_idx_type nz = nnz ();
717 octave_idx_type cx = 0; 724 octave_idx_type cx = 0;
718 octave_idx_type nz2 = nz; 725 octave_idx_type nz2 = nz;
719 retval = SparseComplexMatrix (nr, nc, nz2); 726 retval = SparseComplexMatrix (nr, nc, nz2);
720 727
721 for (octave_idx_type i = 0; i < nr; i++) 728 for (octave_idx_type i = 0; i < nr; i++)
796 retval.xcidx(nr) = cx; 803 retval.xcidx(nr) = cx;
797 retval.maybe_compress (); 804 retval.maybe_compress ();
798 } 805 }
799 else 806 else
800 { 807 {
801 octave_idx_type nz = nzmax (); 808 octave_idx_type nz = nnz ();
802 octave_idx_type cx = 0; 809 octave_idx_type cx = 0;
803 octave_idx_type nz2 = nz; 810 octave_idx_type nz2 = nz;
804 retval = SparseComplexMatrix (nr, nc, nz2); 811 retval = SparseComplexMatrix (nr, nc, nz2);
805 812
806 OCTAVE_LOCAL_BUFFER (Complex, work, nr); 813 OCTAVE_LOCAL_BUFFER (Complex, work, nr);
1116 return retval; 1123 return retval;
1117 } 1124 }
1118 1125
1119 ComplexMatrix 1126 ComplexMatrix
1120 SparseComplexMatrix::dsolve (SparseType &mattype, const Matrix& b, 1127 SparseComplexMatrix::dsolve (SparseType &mattype, const Matrix& b,
1121 octave_idx_type& err, 1128 octave_idx_type& err, double& rcond,
1122 double& rcond, solve_singularity_handler) const 1129 solve_singularity_handler, bool calc_cond) const
1123 { 1130 {
1124 ComplexMatrix retval; 1131 ComplexMatrix retval;
1125 1132
1126 octave_idx_type nr = rows (); 1133 octave_idx_type nr = rows ();
1127 octave_idx_type nc = cols (); 1134 octave_idx_type nc = cols ();
1149 for (octave_idx_type j = 0; j < b.cols(); j++) 1156 for (octave_idx_type j = 0; j < b.cols(); j++)
1150 for (octave_idx_type k = 0; k < nc; k++) 1157 for (octave_idx_type k = 0; k < nc; k++)
1151 for (octave_idx_type i = cidx(k); i < cidx(k+1); i++) 1158 for (octave_idx_type i = cidx(k); i < cidx(k+1); i++)
1152 retval(k,j) = b(ridx(i),j) / data (i); 1159 retval(k,j) = b(ridx(i),j) / data (i);
1153 1160
1154 double dmax = 0., dmin = octave_Inf; 1161 if (calc_cond)
1155 for (octave_idx_type i = 0; i < nm; i++) 1162 {
1156 { 1163 double dmax = 0., dmin = octave_Inf;
1157 double tmp = std::abs(data(i)); 1164 for (octave_idx_type i = 0; i < nm; i++)
1158 if (tmp > dmax) 1165 {
1159 dmax = tmp; 1166 double tmp = std::abs(data(i));
1160 if (tmp < dmin) 1167 if (tmp > dmax)
1161 dmin = tmp; 1168 dmax = tmp;
1162 } 1169 if (tmp < dmin)
1163 rcond = dmin / dmax; 1170 dmin = tmp;
1171 }
1172 rcond = dmin / dmax;
1173 }
1174 else
1175 rcond = 1.0;
1164 } 1176 }
1165 else 1177 else
1166 (*current_liboctave_error_handler) ("incorrect matrix type"); 1178 (*current_liboctave_error_handler) ("incorrect matrix type");
1167 } 1179 }
1168 1180
1170 } 1182 }
1171 1183
1172 SparseComplexMatrix 1184 SparseComplexMatrix
1173 SparseComplexMatrix::dsolve (SparseType &mattype, const SparseMatrix& b, 1185 SparseComplexMatrix::dsolve (SparseType &mattype, const SparseMatrix& b,
1174 octave_idx_type& err, double& rcond, 1186 octave_idx_type& err, double& rcond,
1175 solve_singularity_handler) const 1187 solve_singularity_handler,
1188 bool calc_cond) const
1176 { 1189 {
1177 SparseComplexMatrix retval; 1190 SparseComplexMatrix retval;
1178 1191
1179 octave_idx_type nr = rows (); 1192 octave_idx_type nr = rows ();
1180 octave_idx_type nc = cols (); 1193 octave_idx_type nc = cols ();
1192 1205
1193 if (typ == SparseType::Diagonal || 1206 if (typ == SparseType::Diagonal ||
1194 typ == SparseType::Permuted_Diagonal) 1207 typ == SparseType::Permuted_Diagonal)
1195 { 1208 {
1196 octave_idx_type b_nc = b.cols (); 1209 octave_idx_type b_nc = b.cols ();
1197 octave_idx_type b_nz = b.nzmax (); 1210 octave_idx_type b_nz = b.nnz ();
1198 retval = SparseComplexMatrix (nc, b_nc, b_nz); 1211 retval = SparseComplexMatrix (nc, b_nc, b_nz);
1199 1212
1200 retval.xcidx(0) = 0; 1213 retval.xcidx(0) = 0;
1201 octave_idx_type ii = 0; 1214 octave_idx_type ii = 0;
1202 if (typ == SparseType::Diagonal) 1215 if (typ == SparseType::Diagonal)
1203 for (octave_idx_type j = 0; j < b.cols(); j++) 1216 for (octave_idx_type j = 0; j < b.cols(); j++)
1204 { 1217 {
1205 for (octave_idx_type i = b.cidx(j); i < b.cidx(j+1); i++) 1218 for (octave_idx_type i = b.cidx(j); i < b.cidx(j+1); i++)
1206 { 1219 {
1220 if (b.ridx(i) >= nm)
1221 break;
1207 retval.xridx (ii) = b.ridx(i); 1222 retval.xridx (ii) = b.ridx(i);
1208 retval.xdata (ii++) = b.data(i) / data (b.ridx (i)); 1223 retval.xdata (ii++) = b.data(i) / data (b.ridx (i));
1209 } 1224 }
1210 retval.xcidx(j+1) = ii; 1225 retval.xcidx(j+1) = ii;
1211 } 1226 }
1230 } 1245 }
1231 } 1246 }
1232 retval.xcidx(j+1) = ii; 1247 retval.xcidx(j+1) = ii;
1233 } 1248 }
1234 1249
1235 double dmax = 0., dmin = octave_Inf; 1250 if (calc_cond)
1236 for (octave_idx_type i = 0; i < nm; i++) 1251 {
1237 { 1252 double dmax = 0., dmin = octave_Inf;
1238 double tmp = std::abs(data(i)); 1253 for (octave_idx_type i = 0; i < nm; i++)
1239 if (tmp > dmax) 1254 {
1240 dmax = tmp; 1255 double tmp = std::abs(data(i));
1241 if (tmp < dmin) 1256 if (tmp > dmax)
1242 dmin = tmp; 1257 dmax = tmp;
1243 } 1258 if (tmp < dmin)
1244 rcond = dmin / dmax; 1259 dmin = tmp;
1260 }
1261 rcond = dmin / dmax;
1262 }
1263 else
1264 rcond = 1.0;
1245 } 1265 }
1246 else 1266 else
1247 (*current_liboctave_error_handler) ("incorrect matrix type"); 1267 (*current_liboctave_error_handler) ("incorrect matrix type");
1248 } 1268 }
1249 1269
1251 } 1271 }
1252 1272
1253 ComplexMatrix 1273 ComplexMatrix
1254 SparseComplexMatrix::dsolve (SparseType &mattype, const ComplexMatrix& b, 1274 SparseComplexMatrix::dsolve (SparseType &mattype, const ComplexMatrix& b,
1255 octave_idx_type& err, double& rcond, 1275 octave_idx_type& err, double& rcond,
1256 solve_singularity_handler) const 1276 solve_singularity_handler,
1277 bool calc_cond) const
1257 { 1278 {
1258 ComplexMatrix retval; 1279 ComplexMatrix retval;
1259 1280
1260 octave_idx_type nr = rows (); 1281 octave_idx_type nr = rows ();
1261 octave_idx_type nc = cols (); 1282 octave_idx_type nc = cols ();
1283 for (octave_idx_type j = 0; j < b.cols(); j++) 1304 for (octave_idx_type j = 0; j < b.cols(); j++)
1284 for (octave_idx_type k = 0; k < nc; k++) 1305 for (octave_idx_type k = 0; k < nc; k++)
1285 for (octave_idx_type i = cidx(k); i < cidx(k+1); i++) 1306 for (octave_idx_type i = cidx(k); i < cidx(k+1); i++)
1286 retval(k,j) = b(ridx(i),j) / data (i); 1307 retval(k,j) = b(ridx(i),j) / data (i);
1287 1308
1288 double dmax = 0., dmin = octave_Inf; 1309 if (calc_cond)
1289 for (octave_idx_type i = 0; i < nr; i++) 1310 {
1290 { 1311 double dmax = 0., dmin = octave_Inf;
1291 double tmp = std::abs(data(i)); 1312 for (octave_idx_type i = 0; i < nr; i++)
1292 if (tmp > dmax) 1313 {
1293 dmax = tmp; 1314 double tmp = std::abs(data(i));
1294 if (tmp < dmin) 1315 if (tmp > dmax)
1295 dmin = tmp; 1316 dmax = tmp;
1296 } 1317 if (tmp < dmin)
1297 rcond = dmin / dmax; 1318 dmin = tmp;
1319 }
1320 rcond = dmin / dmax;
1321 }
1322 else
1323 rcond = 1.0;
1298 } 1324 }
1299 else 1325 else
1300 (*current_liboctave_error_handler) ("incorrect matrix type"); 1326 (*current_liboctave_error_handler) ("incorrect matrix type");
1301 } 1327 }
1302 1328
1304 } 1330 }
1305 1331
1306 SparseComplexMatrix 1332 SparseComplexMatrix
1307 SparseComplexMatrix::dsolve (SparseType &mattype, const SparseComplexMatrix& b, 1333 SparseComplexMatrix::dsolve (SparseType &mattype, const SparseComplexMatrix& b,
1308 octave_idx_type& err, double& rcond, 1334 octave_idx_type& err, double& rcond,
1309 solve_singularity_handler) const 1335 solve_singularity_handler,
1336 bool calc_cond) const
1310 { 1337 {
1311 SparseComplexMatrix retval; 1338 SparseComplexMatrix retval;
1312 1339
1313 octave_idx_type nr = rows (); 1340 octave_idx_type nr = rows ();
1314 octave_idx_type nc = cols (); 1341 octave_idx_type nc = cols ();
1326 1353
1327 if (typ == SparseType::Diagonal || 1354 if (typ == SparseType::Diagonal ||
1328 typ == SparseType::Permuted_Diagonal) 1355 typ == SparseType::Permuted_Diagonal)
1329 { 1356 {
1330 octave_idx_type b_nc = b.cols (); 1357 octave_idx_type b_nc = b.cols ();
1331 octave_idx_type b_nz = b.nzmax (); 1358 octave_idx_type b_nz = b.nnz ();
1332 retval = SparseComplexMatrix (nc, b_nc, b_nz); 1359 retval = SparseComplexMatrix (nc, b_nc, b_nz);
1333 1360
1334 retval.xcidx(0) = 0; 1361 retval.xcidx(0) = 0;
1335 octave_idx_type ii = 0; 1362 octave_idx_type ii = 0;
1336 if (typ == SparseType::Diagonal) 1363 if (typ == SparseType::Diagonal)
1337 for (octave_idx_type j = 0; j < b.cols(); j++) 1364 for (octave_idx_type j = 0; j < b.cols(); j++)
1338 { 1365 {
1339 for (octave_idx_type i = b.cidx(j); i < b.cidx(j+1); i++) 1366 for (octave_idx_type i = b.cidx(j); i < b.cidx(j+1); i++)
1340 { 1367 {
1368 if (b.ridx(i) >= nm)
1369 break;
1341 retval.xridx (ii) = b.ridx(i); 1370 retval.xridx (ii) = b.ridx(i);
1342 retval.xdata (ii++) = b.data(i) / data (b.ridx (i)); 1371 retval.xdata (ii++) = b.data(i) / data (b.ridx (i));
1343 } 1372 }
1344 retval.xcidx(j+1) = ii; 1373 retval.xcidx(j+1) = ii;
1345 } 1374 }
1364 } 1393 }
1365 } 1394 }
1366 retval.xcidx(j+1) = ii; 1395 retval.xcidx(j+1) = ii;
1367 } 1396 }
1368 1397
1369 double dmax = 0., dmin = octave_Inf; 1398 if (calc_cond)
1370 for (octave_idx_type i = 0; i < nm; i++) 1399 {
1371 { 1400 double dmax = 0., dmin = octave_Inf;
1372 double tmp = std::abs(data(i)); 1401 for (octave_idx_type i = 0; i < nm; i++)
1373 if (tmp > dmax) 1402 {
1374 dmax = tmp; 1403 double tmp = std::abs(data(i));
1375 if (tmp < dmin) 1404 if (tmp > dmax)
1376 dmin = tmp; 1405 dmax = tmp;
1377 } 1406 if (tmp < dmin)
1378 rcond = dmin / dmax; 1407 dmin = tmp;
1408 }
1409 rcond = dmin / dmax;
1410 }
1411 else
1412 rcond = 1.0;
1379 } 1413 }
1380 else 1414 else
1381 (*current_liboctave_error_handler) ("incorrect matrix type"); 1415 (*current_liboctave_error_handler) ("incorrect matrix type");
1382 } 1416 }
1383 1417
1385 } 1419 }
1386 1420
1387 ComplexMatrix 1421 ComplexMatrix
1388 SparseComplexMatrix::utsolve (SparseType &mattype, const Matrix& b, 1422 SparseComplexMatrix::utsolve (SparseType &mattype, const Matrix& b,
1389 octave_idx_type& err, double& rcond, 1423 octave_idx_type& err, double& rcond,
1390 solve_singularity_handler sing_handler) const 1424 solve_singularity_handler sing_handler,
1425 bool calc_cond) const
1391 { 1426 {
1392 ComplexMatrix retval; 1427 ComplexMatrix retval;
1393 1428
1394 octave_idx_type nr = rows (); 1429 octave_idx_type nr = rows ();
1395 octave_idx_type nc = cols (); 1430 octave_idx_type nc = cols ();
1409 typ == SparseType::Upper) 1444 typ == SparseType::Upper)
1410 { 1445 {
1411 double anorm = 0.; 1446 double anorm = 0.;
1412 double ainvnorm = 0.; 1447 double ainvnorm = 0.;
1413 octave_idx_type b_nc = b.cols (); 1448 octave_idx_type b_nc = b.cols ();
1414 rcond = 0.; 1449 rcond = 1.;
1415 1450
1416 // Calculate the 1-norm of matrix for rcond calculation 1451 if (calc_cond)
1417 for (octave_idx_type j = 0; j < nc; j++) 1452 {
1418 { 1453 // Calculate the 1-norm of matrix for rcond calculation
1419 double atmp = 0.; 1454 for (octave_idx_type j = 0; j < nc; j++)
1420 for (octave_idx_type i = cidx(j); i < cidx(j+1); i++) 1455 {
1421 atmp += std::abs(data(i)); 1456 double atmp = 0.;
1422 if (atmp > anorm) 1457 for (octave_idx_type i = cidx(j); i < cidx(j+1); i++)
1423 anorm = atmp; 1458 atmp += std::abs(data(i));
1459 if (atmp > anorm)
1460 anorm = atmp;
1461 }
1424 } 1462 }
1425 1463
1426 if (typ == SparseType::Permuted_Upper) 1464 if (typ == SparseType::Permuted_Upper)
1427 { 1465 {
1428 retval.resize (nc, b_nc); 1466 retval.resize (nc, b_nc);
1429 octave_idx_type *perm = mattype.triangular_perm (); 1467 octave_idx_type *perm = mattype.triangular_perm ();
1430 OCTAVE_LOCAL_BUFFER (Complex, work, nr); 1468 OCTAVE_LOCAL_BUFFER (Complex, work, nm);
1431 1469
1432 for (octave_idx_type j = 0; j < b_nc; j++) 1470 for (octave_idx_type j = 0; j < b_nc; j++)
1433 { 1471 {
1434 for (octave_idx_type i = 0; i < nr; i++) 1472 for (octave_idx_type i = 0; i < nr; i++)
1435 work[i] = b(i,j); 1473 work[i] = b(i,j);
1440 { 1478 {
1441 octave_idx_type kidx = perm[k]; 1479 octave_idx_type kidx = perm[k];
1442 1480
1443 if (work[k] != 0.) 1481 if (work[k] != 0.)
1444 { 1482 {
1445 if (ridx(cidx(kidx+1)-1) != k) 1483 if (ridx(cidx(kidx+1)-1) != k ||
1484 data(cidx(kidx+1)-1) == 0.)
1446 { 1485 {
1447 err = -2; 1486 err = -2;
1448 goto triangular_error; 1487 goto triangular_error;
1449 } 1488 }
1450 1489
1461 1500
1462 for (octave_idx_type i = 0; i < nc; i++) 1501 for (octave_idx_type i = 0; i < nc; i++)
1463 retval (perm[i], j) = work[i]; 1502 retval (perm[i], j) = work[i];
1464 } 1503 }
1465 1504
1466 // Calculation of 1-norm of inv(*this) 1505 if (calc_cond)
1467 for (octave_idx_type i = 0; i < nm; i++) 1506 {
1468 work[i] = 0.; 1507 // Calculation of 1-norm of inv(*this)
1469 1508 for (octave_idx_type i = 0; i < nm; i++)
1470 for (octave_idx_type j = 0; j < nr; j++) 1509 work[i] = 0.;
1471 { 1510
1472 work[j] = 1.; 1511 for (octave_idx_type j = 0; j < nr; j++)
1473 1512 {
1474 for (octave_idx_type k = j; k >= 0; k--) 1513 work[j] = 1.;
1475 { 1514
1476 octave_idx_type iidx = perm[k]; 1515 for (octave_idx_type k = j; k >= 0; k--)
1477
1478 if (work[k] != 0.)
1479 { 1516 {
1480 Complex tmp = work[k] / data(cidx(iidx+1)-1); 1517 octave_idx_type iidx = perm[k];
1481 work[k] = tmp; 1518
1482 for (octave_idx_type i = cidx(iidx); 1519 if (work[k] != 0.)
1483 i < cidx(iidx+1)-1; i++)
1484 { 1520 {
1485 octave_idx_type idx2 = ridx(i); 1521 Complex tmp = work[k] / data(cidx(iidx+1)-1);
1486 work[idx2] = work[idx2] - tmp * data(i); 1522 work[k] = tmp;
1523 for (octave_idx_type i = cidx(iidx);
1524 i < cidx(iidx+1)-1; i++)
1525 {
1526 octave_idx_type idx2 = ridx(i);
1527 work[idx2] = work[idx2] - tmp * data(i);
1528 }
1487 } 1529 }
1488 } 1530 }
1489 } 1531 double atmp = 0;
1490 double atmp = 0; 1532 for (octave_idx_type i = 0; i < j+1; i++)
1491 for (octave_idx_type i = 0; i < j+1; i++) 1533 {
1492 { 1534 atmp += std::abs(work[i]);
1493 atmp += std::abs(work[i]); 1535 work[i] = 0.;
1494 work[i] = 0.; 1536 }
1495 } 1537 if (atmp > ainvnorm)
1496 if (atmp > ainvnorm) 1538 ainvnorm = atmp;
1497 ainvnorm = atmp; 1539 }
1540 rcond = 1. / ainvnorm / anorm;
1498 } 1541 }
1499 } 1542 }
1500 else 1543 else
1501 { 1544 {
1502 OCTAVE_LOCAL_BUFFER (Complex, work, nm); 1545 OCTAVE_LOCAL_BUFFER (Complex, work, nm);
1511 1554
1512 for (octave_idx_type k = nc-1; k >= 0; k--) 1555 for (octave_idx_type k = nc-1; k >= 0; k--)
1513 { 1556 {
1514 if (work[k] != 0.) 1557 if (work[k] != 0.)
1515 { 1558 {
1516 if (ridx(cidx(k+1)-1) != k) 1559 if (ridx(cidx(k+1)-1) != k ||
1560 data(cidx(k+1)-1) == 0.)
1517 { 1561 {
1518 err = -2; 1562 err = -2;
1519 goto triangular_error; 1563 goto triangular_error;
1520 } 1564 }
1521 1565
1531 1575
1532 for (octave_idx_type i = 0; i < nc; i++) 1576 for (octave_idx_type i = 0; i < nc; i++)
1533 retval.xelem (i, j) = work[i]; 1577 retval.xelem (i, j) = work[i];
1534 } 1578 }
1535 1579
1536 // Calculation of 1-norm of inv(*this) 1580 if (calc_cond)
1537 for (octave_idx_type i = 0; i < nm; i++) 1581 {
1538 work[i] = 0.; 1582 // Calculation of 1-norm of inv(*this)
1539 1583 for (octave_idx_type i = 0; i < nm; i++)
1540 for (octave_idx_type j = 0; j < nr; j++) 1584 work[i] = 0.;
1541 { 1585
1542 work[j] = 1.; 1586 for (octave_idx_type j = 0; j < nr; j++)
1543 1587 {
1544 for (octave_idx_type k = j; k >= 0; k--) 1588 work[j] = 1.;
1545 { 1589
1546 if (work[k] != 0.) 1590 for (octave_idx_type k = j; k >= 0; k--)
1547 { 1591 {
1548 Complex tmp = work[k] / data(cidx(k+1)-1); 1592 if (work[k] != 0.)
1549 work[k] = tmp;
1550 for (octave_idx_type i = cidx(k); i < cidx(k+1)-1; i++)
1551 { 1593 {
1552 octave_idx_type iidx = ridx(i); 1594 Complex tmp = work[k] / data(cidx(k+1)-1);
1553 work[iidx] = work[iidx] - tmp * data(i); 1595 work[k] = tmp;
1596 for (octave_idx_type i = cidx(k);
1597 i < cidx(k+1)-1; i++)
1598 {
1599 octave_idx_type iidx = ridx(i);
1600 work[iidx] = work[iidx] - tmp * data(i);
1601 }
1554 } 1602 }
1555 } 1603 }
1556 } 1604 double atmp = 0;
1557 double atmp = 0; 1605 for (octave_idx_type i = 0; i < j+1; i++)
1558 for (octave_idx_type i = 0; i < j+1; i++) 1606 {
1559 { 1607 atmp += std::abs(work[i]);
1560 atmp += std::abs(work[i]); 1608 work[i] = 0.;
1561 work[i] = 0.; 1609 }
1562 } 1610 if (atmp > ainvnorm)
1563 if (atmp > ainvnorm) 1611 ainvnorm = atmp;
1564 ainvnorm = atmp; 1612 }
1565 } 1613 rcond = 1. / ainvnorm / anorm;
1566 } 1614 }
1567 1615 }
1568 rcond = 1. / ainvnorm / anorm;
1569 1616
1570 triangular_error: 1617 triangular_error:
1571 if (err != 0) 1618 if (err != 0)
1572 { 1619 {
1573 if (sing_handler) 1620 if (sing_handler)
1574 sing_handler (rcond); 1621 {
1622 sing_handler (rcond);
1623 mattype.mark_as_rectangular ();
1624 }
1575 else 1625 else
1576 (*current_liboctave_error_handler) 1626 (*current_liboctave_error_handler)
1577 ("SparseComplexMatrix::solve matrix singular to machine precision, rcond = %g", 1627 ("SparseComplexMatrix::solve matrix singular to machine precision, rcond = %g",
1578 rcond); 1628 rcond);
1579 } 1629 }
1583 if (rcond_plus_one == 1.0 || xisnan (rcond)) 1633 if (rcond_plus_one == 1.0 || xisnan (rcond))
1584 { 1634 {
1585 err = -2; 1635 err = -2;
1586 1636
1587 if (sing_handler) 1637 if (sing_handler)
1588 sing_handler (rcond); 1638 {
1639 sing_handler (rcond);
1640 mattype.mark_as_rectangular ();
1641 }
1589 else 1642 else
1590 (*current_liboctave_error_handler) 1643 (*current_liboctave_error_handler)
1591 ("matrix singular to machine precision, rcond = %g", 1644 ("matrix singular to machine precision, rcond = %g",
1592 rcond); 1645 rcond);
1593 } 1646 }
1600 } 1653 }
1601 1654
1602 SparseComplexMatrix 1655 SparseComplexMatrix
1603 SparseComplexMatrix::utsolve (SparseType &mattype, const SparseMatrix& b, 1656 SparseComplexMatrix::utsolve (SparseType &mattype, const SparseMatrix& b,
1604 octave_idx_type& err, double& rcond, 1657 octave_idx_type& err, double& rcond,
1605 solve_singularity_handler sing_handler) const 1658 solve_singularity_handler sing_handler,
1659 bool calc_cond) const
1606 { 1660 {
1607 SparseComplexMatrix retval; 1661 SparseComplexMatrix retval;
1608 1662
1609 octave_idx_type nr = rows (); 1663 octave_idx_type nr = rows ();
1610 octave_idx_type nc = cols (); 1664 octave_idx_type nc = cols ();
1623 if (typ == SparseType::Permuted_Upper || 1677 if (typ == SparseType::Permuted_Upper ||
1624 typ == SparseType::Upper) 1678 typ == SparseType::Upper)
1625 { 1679 {
1626 double anorm = 0.; 1680 double anorm = 0.;
1627 double ainvnorm = 0.; 1681 double ainvnorm = 0.;
1628 rcond = 0.; 1682 rcond = 1.;
1629 1683
1630 // Calculate the 1-norm of matrix for rcond calculation 1684 if (calc_cond)
1631 for (octave_idx_type j = 0; j < nc; j++) 1685 {
1632 { 1686 // Calculate the 1-norm of matrix for rcond calculation
1633 double atmp = 0.; 1687 for (octave_idx_type j = 0; j < nc; j++)
1634 for (octave_idx_type i = cidx(j); i < cidx(j+1); i++) 1688 {
1635 atmp += std::abs(data(i)); 1689 double atmp = 0.;
1636 if (atmp > anorm) 1690 for (octave_idx_type i = cidx(j); i < cidx(j+1); i++)
1637 anorm = atmp; 1691 atmp += std::abs(data(i));
1692 if (atmp > anorm)
1693 anorm = atmp;
1694 }
1638 } 1695 }
1639 1696
1640 octave_idx_type b_nc = b.cols (); 1697 octave_idx_type b_nc = b.cols ();
1641 octave_idx_type b_nz = b.nzmax (); 1698 octave_idx_type b_nz = b.nnz ();
1642 retval = SparseComplexMatrix (nc, b_nc, b_nz); 1699 retval = SparseComplexMatrix (nc, b_nc, b_nz);
1643 retval.xcidx(0) = 0; 1700 retval.xcidx(0) = 0;
1644 octave_idx_type ii = 0; 1701 octave_idx_type ii = 0;
1645 octave_idx_type x_nz = b_nz; 1702 octave_idx_type x_nz = b_nz;
1646 1703
1664 { 1721 {
1665 octave_idx_type kidx = perm[k]; 1722 octave_idx_type kidx = perm[k];
1666 1723
1667 if (work[k] != 0.) 1724 if (work[k] != 0.)
1668 { 1725 {
1669 if (ridx(cidx(kidx+1)-1) != k) 1726 if (ridx(cidx(kidx+1)-1) != k ||
1727 data(cidx(kidx+1)-1) == 0.)
1670 { 1728 {
1671 err = -2; 1729 err = -2;
1672 goto triangular_error; 1730 goto triangular_error;
1673 } 1731 }
1674 1732
1707 retval.xcidx(j+1) = ii; 1765 retval.xcidx(j+1) = ii;
1708 } 1766 }
1709 1767
1710 retval.maybe_compress (); 1768 retval.maybe_compress ();
1711 1769
1712 // Calculation of 1-norm of inv(*this) 1770 if (calc_cond)
1713 for (octave_idx_type i = 0; i < nm; i++) 1771 {
1714 work[i] = 0.; 1772 // Calculation of 1-norm of inv(*this)
1715 1773 for (octave_idx_type i = 0; i < nm; i++)
1716 for (octave_idx_type j = 0; j < nr; j++) 1774 work[i] = 0.;
1717 { 1775
1718 work[j] = 1.; 1776 for (octave_idx_type j = 0; j < nr; j++)
1719 1777 {
1720 for (octave_idx_type k = j; k >= 0; k--) 1778 work[j] = 1.;
1721 { 1779
1722 octave_idx_type iidx = perm[k]; 1780 for (octave_idx_type k = j; k >= 0; k--)
1723
1724 if (work[k] != 0.)
1725 { 1781 {
1726 Complex tmp = work[k] / data(cidx(iidx+1)-1); 1782 octave_idx_type iidx = perm[k];
1727 work[k] = tmp; 1783
1728 for (octave_idx_type i = cidx(iidx); 1784 if (work[k] != 0.)
1729 i < cidx(iidx+1)-1; i++)
1730 { 1785 {
1731 octave_idx_type idx2 = ridx(i); 1786 Complex tmp = work[k] / data(cidx(iidx+1)-1);
1732 work[idx2] = work[idx2] - tmp * data(i); 1787 work[k] = tmp;
1788 for (octave_idx_type i = cidx(iidx);
1789 i < cidx(iidx+1)-1; i++)
1790 {
1791 octave_idx_type idx2 = ridx(i);
1792 work[idx2] = work[idx2] - tmp * data(i);
1793 }
1733 } 1794 }
1734 } 1795 }
1735 } 1796 double atmp = 0;
1736 double atmp = 0; 1797 for (octave_idx_type i = 0; i < j+1; i++)
1737 for (octave_idx_type i = 0; i < j+1; i++) 1798 {
1738 { 1799 atmp += std::abs(work[i]);
1739 atmp += std::abs(work[i]); 1800 work[i] = 0.;
1740 work[i] = 0.; 1801 }
1741 } 1802 if (atmp > ainvnorm)
1742 if (atmp > ainvnorm) 1803 ainvnorm = atmp;
1743 ainvnorm = atmp; 1804 }
1805 rcond = 1. / ainvnorm / anorm;
1744 } 1806 }
1745 } 1807 }
1746 else 1808 else
1747 { 1809 {
1748 OCTAVE_LOCAL_BUFFER (Complex, work, nm); 1810 OCTAVE_LOCAL_BUFFER (Complex, work, nm);
1756 1818
1757 for (octave_idx_type k = nc-1; k >= 0; k--) 1819 for (octave_idx_type k = nc-1; k >= 0; k--)
1758 { 1820 {
1759 if (work[k] != 0.) 1821 if (work[k] != 0.)
1760 { 1822 {
1761 if (ridx(cidx(k+1)-1) != k) 1823 if (ridx(cidx(k+1)-1) != k ||
1824 data(cidx(k+1)-1) == 0.)
1762 { 1825 {
1763 err = -2; 1826 err = -2;
1764 goto triangular_error; 1827 goto triangular_error;
1765 } 1828 }
1766 1829
1798 retval.xcidx(j+1) = ii; 1861 retval.xcidx(j+1) = ii;
1799 } 1862 }
1800 1863
1801 retval.maybe_compress (); 1864 retval.maybe_compress ();
1802 1865
1803 // Calculation of 1-norm of inv(*this) 1866 if (calc_cond)
1804 for (octave_idx_type i = 0; i < nm; i++) 1867 {
1805 work[i] = 0.; 1868 // Calculation of 1-norm of inv(*this)
1806 1869 for (octave_idx_type i = 0; i < nm; i++)
1807 for (octave_idx_type j = 0; j < nr; j++) 1870 work[i] = 0.;
1808 { 1871
1809 work[j] = 1.; 1872 for (octave_idx_type j = 0; j < nr; j++)
1810 1873 {
1811 for (octave_idx_type k = j; k >= 0; k--) 1874 work[j] = 1.;
1812 { 1875
1813 if (work[k] != 0.) 1876 for (octave_idx_type k = j; k >= 0; k--)
1814 { 1877 {
1815 Complex tmp = work[k] / data(cidx(k+1)-1); 1878 if (work[k] != 0.)
1816 work[k] = tmp;
1817 for (octave_idx_type i = cidx(k); i < cidx(k+1)-1; i++)
1818 { 1879 {
1819 octave_idx_type iidx = ridx(i); 1880 Complex tmp = work[k] / data(cidx(k+1)-1);
1820 work[iidx] = work[iidx] - tmp * data(i); 1881 work[k] = tmp;
1882 for (octave_idx_type i = cidx(k);
1883 i < cidx(k+1)-1; i++)
1884 {
1885 octave_idx_type iidx = ridx(i);
1886 work[iidx] = work[iidx] - tmp * data(i);
1887 }
1821 } 1888 }
1822 } 1889 }
1823 } 1890 double atmp = 0;
1824 double atmp = 0; 1891 for (octave_idx_type i = 0; i < j+1; i++)
1825 for (octave_idx_type i = 0; i < j+1; i++) 1892 {
1826 { 1893 atmp += std::abs(work[i]);
1827 atmp += std::abs(work[i]); 1894 work[i] = 0.;
1828 work[i] = 0.; 1895 }
1829 } 1896 if (atmp > ainvnorm)
1830 if (atmp > ainvnorm) 1897 ainvnorm = atmp;
1831 ainvnorm = atmp; 1898 }
1832 } 1899 rcond = 1. / ainvnorm / anorm;
1833 } 1900 }
1834 1901 }
1835 rcond = 1. / ainvnorm / anorm;
1836 1902
1837 triangular_error: 1903 triangular_error:
1838 if (err != 0) 1904 if (err != 0)
1839 { 1905 {
1840 if (sing_handler) 1906 if (sing_handler)
1841 sing_handler (rcond); 1907 {
1908 sing_handler (rcond);
1909 mattype.mark_as_rectangular ();
1910 }
1842 else 1911 else
1843 (*current_liboctave_error_handler) 1912 (*current_liboctave_error_handler)
1844 ("SparseComplexMatrix::solve matrix singular to machine precision, rcond = %g", 1913 ("SparseComplexMatrix::solve matrix singular to machine precision, rcond = %g",
1845 rcond); 1914 rcond);
1846 } 1915 }
1850 if (rcond_plus_one == 1.0 || xisnan (rcond)) 1919 if (rcond_plus_one == 1.0 || xisnan (rcond))
1851 { 1920 {
1852 err = -2; 1921 err = -2;
1853 1922
1854 if (sing_handler) 1923 if (sing_handler)
1855 sing_handler (rcond); 1924 {
1925 sing_handler (rcond);
1926 mattype.mark_as_rectangular ();
1927 }
1856 else 1928 else
1857 (*current_liboctave_error_handler) 1929 (*current_liboctave_error_handler)
1858 ("matrix singular to machine precision, rcond = %g", 1930 ("matrix singular to machine precision, rcond = %g",
1859 rcond); 1931 rcond);
1860 } 1932 }
1866 } 1938 }
1867 1939
1868 ComplexMatrix 1940 ComplexMatrix
1869 SparseComplexMatrix::utsolve (SparseType &mattype, const ComplexMatrix& b, 1941 SparseComplexMatrix::utsolve (SparseType &mattype, const ComplexMatrix& b,
1870 octave_idx_type& err, double& rcond, 1942 octave_idx_type& err, double& rcond,
1871 solve_singularity_handler sing_handler) const 1943 solve_singularity_handler sing_handler,
1944 bool calc_cond) const
1872 { 1945 {
1873 ComplexMatrix retval; 1946 ComplexMatrix retval;
1874 1947
1875 octave_idx_type nr = rows (); 1948 octave_idx_type nr = rows ();
1876 octave_idx_type nc = cols (); 1949 octave_idx_type nc = cols ();
1890 typ == SparseType::Upper) 1963 typ == SparseType::Upper)
1891 { 1964 {
1892 double anorm = 0.; 1965 double anorm = 0.;
1893 double ainvnorm = 0.; 1966 double ainvnorm = 0.;
1894 octave_idx_type b_nc = b.cols (); 1967 octave_idx_type b_nc = b.cols ();
1895 rcond = 0.; 1968 rcond = 1.;
1896 1969
1897 // Calculate the 1-norm of matrix for rcond calculation 1970 if (calc_cond)
1898 for (octave_idx_type j = 0; j < nc; j++) 1971 {
1899 { 1972 // Calculate the 1-norm of matrix for rcond calculation
1900 double atmp = 0.; 1973 for (octave_idx_type j = 0; j < nc; j++)
1901 for (octave_idx_type i = cidx(j); i < cidx(j+1); i++) 1974 {
1902 atmp += std::abs(data(i)); 1975 double atmp = 0.;
1903 if (atmp > anorm) 1976 for (octave_idx_type i = cidx(j); i < cidx(j+1); i++)
1904 anorm = atmp; 1977 atmp += std::abs(data(i));
1978 if (atmp > anorm)
1979 anorm = atmp;
1980 }
1905 } 1981 }
1906 1982
1907 if (typ == SparseType::Permuted_Upper) 1983 if (typ == SparseType::Permuted_Upper)
1908 { 1984 {
1909 retval.resize (nc, b_nc); 1985 retval.resize (nc, b_nc);
1921 { 1997 {
1922 octave_idx_type kidx = perm[k]; 1998 octave_idx_type kidx = perm[k];
1923 1999
1924 if (work[k] != 0.) 2000 if (work[k] != 0.)
1925 { 2001 {
1926 if (ridx(cidx(kidx+1)-1) != k) 2002 if (ridx(cidx(kidx+1)-1) != k ||
2003 data(cidx(kidx+1)-1) == 0.)
1927 { 2004 {
1928 err = -2; 2005 err = -2;
1929 goto triangular_error; 2006 goto triangular_error;
1930 } 2007 }
1931 2008
1942 2019
1943 for (octave_idx_type i = 0; i < nc; i++) 2020 for (octave_idx_type i = 0; i < nc; i++)
1944 retval (perm[i], j) = work[i]; 2021 retval (perm[i], j) = work[i];
1945 } 2022 }
1946 2023
1947 // Calculation of 1-norm of inv(*this) 2024 if (calc_cond)
1948 for (octave_idx_type i = 0; i < nm; i++) 2025 {
1949 work[i] = 0.; 2026 // Calculation of 1-norm of inv(*this)
1950 2027 for (octave_idx_type i = 0; i < nm; i++)
1951 for (octave_idx_type j = 0; j < nr; j++) 2028 work[i] = 0.;
1952 { 2029
1953 work[j] = 1.; 2030 for (octave_idx_type j = 0; j < nr; j++)
1954 2031 {
1955 for (octave_idx_type k = j; k >= 0; k--) 2032 work[j] = 1.;
1956 { 2033
1957 octave_idx_type iidx = perm[k]; 2034 for (octave_idx_type k = j; k >= 0; k--)
1958
1959 if (work[k] != 0.)
1960 { 2035 {
1961 Complex tmp = work[k] / data(cidx(iidx+1)-1); 2036 octave_idx_type iidx = perm[k];
1962 work[k] = tmp; 2037
1963 for (octave_idx_type i = cidx(iidx); 2038 if (work[k] != 0.)
1964 i < cidx(iidx+1)-1; i++)
1965 { 2039 {
1966 octave_idx_type idx2 = ridx(i); 2040 Complex tmp = work[k] / data(cidx(iidx+1)-1);
1967 work[idx2] = work[idx2] - tmp * data(i); 2041 work[k] = tmp;
2042 for (octave_idx_type i = cidx(iidx);
2043 i < cidx(iidx+1)-1; i++)
2044 {
2045 octave_idx_type idx2 = ridx(i);
2046 work[idx2] = work[idx2] - tmp * data(i);
2047 }
1968 } 2048 }
1969 } 2049 }
1970 } 2050 double atmp = 0;
1971 double atmp = 0; 2051 for (octave_idx_type i = 0; i < j+1; i++)
1972 for (octave_idx_type i = 0; i < j+1; i++) 2052 {
1973 { 2053 atmp += std::abs(work[i]);
1974 atmp += std::abs(work[i]); 2054 work[i] = 0.;
1975 work[i] = 0.; 2055 }
1976 } 2056 if (atmp > ainvnorm)
1977 if (atmp > ainvnorm) 2057 ainvnorm = atmp;
1978 ainvnorm = atmp; 2058 }
2059 rcond = 1. / ainvnorm / anorm;
1979 } 2060 }
1980 } 2061 }
1981 else 2062 else
1982 { 2063 {
1983 OCTAVE_LOCAL_BUFFER (Complex, work, nm); 2064 OCTAVE_LOCAL_BUFFER (Complex, work, nm);
1992 2073
1993 for (octave_idx_type k = nc-1; k >= 0; k--) 2074 for (octave_idx_type k = nc-1; k >= 0; k--)
1994 { 2075 {
1995 if (work[k] != 0.) 2076 if (work[k] != 0.)
1996 { 2077 {
1997 if (ridx(cidx(k+1)-1) != k) 2078 if (ridx(cidx(k+1)-1) != k ||
2079 data(cidx(k+1)-1) == 0.)
1998 { 2080 {
1999 err = -2; 2081 err = -2;
2000 goto triangular_error; 2082 goto triangular_error;
2001 } 2083 }
2002 2084
2012 2094
2013 for (octave_idx_type i = 0; i < nc; i++) 2095 for (octave_idx_type i = 0; i < nc; i++)
2014 retval.xelem (i, j) = work[i]; 2096 retval.xelem (i, j) = work[i];
2015 } 2097 }
2016 2098
2017 // Calculation of 1-norm of inv(*this) 2099 if (calc_cond)
2018 for (octave_idx_type i = 0; i < nm; i++) 2100 {
2019 work[i] = 0.; 2101 // Calculation of 1-norm of inv(*this)
2020 2102 for (octave_idx_type i = 0; i < nm; i++)
2021 for (octave_idx_type j = 0; j < nr; j++) 2103 work[i] = 0.;
2022 { 2104
2023 work[j] = 1.; 2105 for (octave_idx_type j = 0; j < nr; j++)
2024 2106 {
2025 for (octave_idx_type k = j; k >= 0; k--) 2107 work[j] = 1.;
2026 { 2108
2027 if (work[k] != 0.) 2109 for (octave_idx_type k = j; k >= 0; k--)
2028 { 2110 {
2029 Complex tmp = work[k] / data(cidx(k+1)-1); 2111 if (work[k] != 0.)
2030 work[k] = tmp;
2031 for (octave_idx_type i = cidx(k); i < cidx(k+1)-1; i++)
2032 { 2112 {
2033 octave_idx_type iidx = ridx(i); 2113 Complex tmp = work[k] / data(cidx(k+1)-1);
2034 work[iidx] = work[iidx] - tmp * data(i); 2114 work[k] = tmp;
2115 for (octave_idx_type i = cidx(k);
2116 i < cidx(k+1)-1; i++)
2117 {
2118 octave_idx_type iidx = ridx(i);
2119 work[iidx] = work[iidx] - tmp * data(i);
2120 }
2035 } 2121 }
2036 } 2122 }
2037 } 2123 double atmp = 0;
2038 double atmp = 0; 2124 for (octave_idx_type i = 0; i < j+1; i++)
2039 for (octave_idx_type i = 0; i < j+1; i++) 2125 {
2040 { 2126 atmp += std::abs(work[i]);
2041 atmp += std::abs(work[i]); 2127 work[i] = 0.;
2042 work[i] = 0.; 2128 }
2043 } 2129 if (atmp > ainvnorm)
2044 if (atmp > ainvnorm) 2130 ainvnorm = atmp;
2045 ainvnorm = atmp; 2131 }
2046 } 2132 rcond = 1. / ainvnorm / anorm;
2047 } 2133 }
2048 2134 }
2049 rcond = 1. / ainvnorm / anorm;
2050 2135
2051 triangular_error: 2136 triangular_error:
2052 if (err != 0) 2137 if (err != 0)
2053 { 2138 {
2054 if (sing_handler) 2139 if (sing_handler)
2055 sing_handler (rcond); 2140 {
2141 sing_handler (rcond);
2142 mattype.mark_as_rectangular ();
2143 }
2056 else 2144 else
2057 (*current_liboctave_error_handler) 2145 (*current_liboctave_error_handler)
2058 ("SparseComplexMatrix::solve matrix singular to machine precision, rcond = %g", 2146 ("SparseComplexMatrix::solve matrix singular to machine precision, rcond = %g",
2059 rcond); 2147 rcond);
2060 } 2148 }
2064 if (rcond_plus_one == 1.0 || xisnan (rcond)) 2152 if (rcond_plus_one == 1.0 || xisnan (rcond))
2065 { 2153 {
2066 err = -2; 2154 err = -2;
2067 2155
2068 if (sing_handler) 2156 if (sing_handler)
2069 sing_handler (rcond); 2157 {
2158 sing_handler (rcond);
2159 mattype.mark_as_rectangular ();
2160 }
2070 else 2161 else
2071 (*current_liboctave_error_handler) 2162 (*current_liboctave_error_handler)
2072 ("matrix singular to machine precision, rcond = %g", 2163 ("matrix singular to machine precision, rcond = %g",
2073 rcond); 2164 rcond);
2074 } 2165 }
2081 } 2172 }
2082 2173
2083 SparseComplexMatrix 2174 SparseComplexMatrix
2084 SparseComplexMatrix::utsolve (SparseType &mattype, const SparseComplexMatrix& b, 2175 SparseComplexMatrix::utsolve (SparseType &mattype, const SparseComplexMatrix& b,
2085 octave_idx_type& err, double& rcond, 2176 octave_idx_type& err, double& rcond,
2086 solve_singularity_handler sing_handler) const 2177 solve_singularity_handler sing_handler,
2178 bool calc_cond) const
2087 { 2179 {
2088 SparseComplexMatrix retval; 2180 SparseComplexMatrix retval;
2089 2181
2090 octave_idx_type nr = rows (); 2182 octave_idx_type nr = rows ();
2091 octave_idx_type nc = cols (); 2183 octave_idx_type nc = cols ();
2104 if (typ == SparseType::Permuted_Upper || 2196 if (typ == SparseType::Permuted_Upper ||
2105 typ == SparseType::Upper) 2197 typ == SparseType::Upper)
2106 { 2198 {
2107 double anorm = 0.; 2199 double anorm = 0.;
2108 double ainvnorm = 0.; 2200 double ainvnorm = 0.;
2109 rcond = 0.; 2201 rcond = 1.;
2110 2202
2111 // Calculate the 1-norm of matrix for rcond calculation 2203 if (calc_cond)
2112 for (octave_idx_type j = 0; j < nc; j++) 2204 {
2113 { 2205 // Calculate the 1-norm of matrix for rcond calculation
2114 double atmp = 0.; 2206 for (octave_idx_type j = 0; j < nc; j++)
2115 for (octave_idx_type i = cidx(j); i < cidx(j+1); i++) 2207 {
2116 atmp += std::abs(data(i)); 2208 double atmp = 0.;
2117 if (atmp > anorm) 2209 for (octave_idx_type i = cidx(j); i < cidx(j+1); i++)
2118 anorm = atmp; 2210 atmp += std::abs(data(i));
2211 if (atmp > anorm)
2212 anorm = atmp;
2213 }
2119 } 2214 }
2120 2215
2121 octave_idx_type b_nc = b.cols (); 2216 octave_idx_type b_nc = b.cols ();
2122 octave_idx_type b_nz = b.nzmax (); 2217 octave_idx_type b_nz = b.nnz ();
2123 retval = SparseComplexMatrix (nc, b_nc, b_nz); 2218 retval = SparseComplexMatrix (nc, b_nc, b_nz);
2124 retval.xcidx(0) = 0; 2219 retval.xcidx(0) = 0;
2125 octave_idx_type ii = 0; 2220 octave_idx_type ii = 0;
2126 octave_idx_type x_nz = b_nz; 2221 octave_idx_type x_nz = b_nz;
2127 2222
2145 { 2240 {
2146 octave_idx_type kidx = perm[k]; 2241 octave_idx_type kidx = perm[k];
2147 2242
2148 if (work[k] != 0.) 2243 if (work[k] != 0.)
2149 { 2244 {
2150 if (ridx(cidx(kidx+1)-1) != k) 2245 if (ridx(cidx(kidx+1)-1) != k ||
2246 data(cidx(kidx+1)-1) == 0.)
2151 { 2247 {
2152 err = -2; 2248 err = -2;
2153 goto triangular_error; 2249 goto triangular_error;
2154 } 2250 }
2155 2251
2188 retval.xcidx(j+1) = ii; 2284 retval.xcidx(j+1) = ii;
2189 } 2285 }
2190 2286
2191 retval.maybe_compress (); 2287 retval.maybe_compress ();
2192 2288
2193 // Calculation of 1-norm of inv(*this) 2289 if (calc_cond)
2194 for (octave_idx_type i = 0; i < nm; i++) 2290 {
2195 work[i] = 0.; 2291 // Calculation of 1-norm of inv(*this)
2196 2292 for (octave_idx_type i = 0; i < nm; i++)
2197 for (octave_idx_type j = 0; j < nr; j++) 2293 work[i] = 0.;
2198 { 2294
2199 work[j] = 1.; 2295 for (octave_idx_type j = 0; j < nr; j++)
2200 2296 {
2201 for (octave_idx_type k = j; k >= 0; k--) 2297 work[j] = 1.;
2202 { 2298
2203 octave_idx_type iidx = perm[k]; 2299 for (octave_idx_type k = j; k >= 0; k--)
2204
2205 if (work[k] != 0.)
2206 { 2300 {
2207 Complex tmp = work[k] / data(cidx(iidx+1)-1); 2301 octave_idx_type iidx = perm[k];
2208 work[k] = tmp; 2302
2209 for (octave_idx_type i = cidx(iidx); 2303 if (work[k] != 0.)
2210 i < cidx(iidx+1)-1; i++)
2211 { 2304 {
2212 octave_idx_type idx2 = ridx(i); 2305 Complex tmp = work[k] / data(cidx(iidx+1)-1);
2213 work[idx2] = work[idx2] - tmp * data(i); 2306 work[k] = tmp;
2307 for (octave_idx_type i = cidx(iidx);
2308 i < cidx(iidx+1)-1; i++)
2309 {
2310 octave_idx_type idx2 = ridx(i);
2311 work[idx2] = work[idx2] - tmp * data(i);
2312 }
2214 } 2313 }
2215 } 2314 }
2216 } 2315 double atmp = 0;
2217 double atmp = 0; 2316 for (octave_idx_type i = 0; i < j+1; i++)
2218 for (octave_idx_type i = 0; i < j+1; i++) 2317 {
2219 { 2318 atmp += std::abs(work[i]);
2220 atmp += std::abs(work[i]); 2319 work[i] = 0.;
2221 work[i] = 0.; 2320 }
2222 } 2321 if (atmp > ainvnorm)
2223 if (atmp > ainvnorm) 2322 ainvnorm = atmp;
2224 ainvnorm = atmp; 2323 }
2324 rcond = 1. / ainvnorm / anorm;
2225 } 2325 }
2226 } 2326 }
2227 else 2327 else
2228 { 2328 {
2229 OCTAVE_LOCAL_BUFFER (Complex, work, nm); 2329 OCTAVE_LOCAL_BUFFER (Complex, work, nm);
2237 2337
2238 for (octave_idx_type k = nr-1; k >= 0; k--) 2338 for (octave_idx_type k = nr-1; k >= 0; k--)
2239 { 2339 {
2240 if (work[k] != 0.) 2340 if (work[k] != 0.)
2241 { 2341 {
2242 if (ridx(cidx(k+1)-1) != k) 2342 if (ridx(cidx(k+1)-1) != k ||
2343 data(cidx(k+1)-1) == 0.)
2243 { 2344 {
2244 err = -2; 2345 err = -2;
2245 goto triangular_error; 2346 goto triangular_error;
2246 } 2347 }
2247 2348
2279 retval.xcidx(j+1) = ii; 2380 retval.xcidx(j+1) = ii;
2280 } 2381 }
2281 2382
2282 retval.maybe_compress (); 2383 retval.maybe_compress ();
2283 2384
2284 // Calculation of 1-norm of inv(*this) 2385 if (calc_cond)
2285 for (octave_idx_type i = 0; i < nm; i++) 2386 {
2286 work[i] = 0.; 2387 // Calculation of 1-norm of inv(*this)
2287 2388 for (octave_idx_type i = 0; i < nm; i++)
2288 for (octave_idx_type j = 0; j < nr; j++) 2389 work[i] = 0.;
2289 { 2390
2290 work[j] = 1.; 2391 for (octave_idx_type j = 0; j < nr; j++)
2291 2392 {
2292 for (octave_idx_type k = j; k >= 0; k--) 2393 work[j] = 1.;
2293 { 2394
2294 if (work[k] != 0.) 2395 for (octave_idx_type k = j; k >= 0; k--)
2295 { 2396 {
2296 Complex tmp = work[k] / data(cidx(k+1)-1); 2397 if (work[k] != 0.)
2297 work[k] = tmp;
2298 for (octave_idx_type i = cidx(k); i < cidx(k+1)-1; i++)
2299 { 2398 {
2300 octave_idx_type iidx = ridx(i); 2399 Complex tmp = work[k] / data(cidx(k+1)-1);
2301 work[iidx] = work[iidx] - tmp * data(i); 2400 work[k] = tmp;
2401 for (octave_idx_type i = cidx(k);
2402 i < cidx(k+1)-1; i++)
2403 {
2404 octave_idx_type iidx = ridx(i);
2405 work[iidx] = work[iidx] - tmp * data(i);
2406 }
2302 } 2407 }
2303 } 2408 }
2304 } 2409 double atmp = 0;
2305 double atmp = 0; 2410 for (octave_idx_type i = 0; i < j+1; i++)
2306 for (octave_idx_type i = 0; i < j+1; i++) 2411 {
2307 { 2412 atmp += std::abs(work[i]);
2308 atmp += std::abs(work[i]); 2413 work[i] = 0.;
2309 work[i] = 0.; 2414 }
2310 } 2415 if (atmp > ainvnorm)
2311 if (atmp > ainvnorm) 2416 ainvnorm = atmp;
2312 ainvnorm = atmp; 2417 }
2313 } 2418 rcond = 1. / ainvnorm / anorm;
2314 } 2419 }
2315 2420 }
2316 rcond = 1. / ainvnorm / anorm;
2317 2421
2318 triangular_error: 2422 triangular_error:
2319 if (err != 0) 2423 if (err != 0)
2320 { 2424 {
2321 if (sing_handler) 2425 if (sing_handler)
2322 sing_handler (rcond); 2426 {
2427 sing_handler (rcond);
2428 mattype.mark_as_rectangular ();
2429 }
2323 else 2430 else
2324 (*current_liboctave_error_handler) 2431 (*current_liboctave_error_handler)
2325 ("SparseComplexMatrix::solve matrix singular to machine precision, rcond = %g", 2432 ("SparseComplexMatrix::solve matrix singular to machine precision, rcond = %g",
2326 rcond); 2433 rcond);
2327 } 2434 }
2331 if (rcond_plus_one == 1.0 || xisnan (rcond)) 2438 if (rcond_plus_one == 1.0 || xisnan (rcond))
2332 { 2439 {
2333 err = -2; 2440 err = -2;
2334 2441
2335 if (sing_handler) 2442 if (sing_handler)
2336 sing_handler (rcond); 2443 {
2444 sing_handler (rcond);
2445 mattype.mark_as_rectangular ();
2446 }
2337 else 2447 else
2338 (*current_liboctave_error_handler) 2448 (*current_liboctave_error_handler)
2339 ("matrix singular to machine precision, rcond = %g", 2449 ("matrix singular to machine precision, rcond = %g",
2340 rcond); 2450 rcond);
2341 } 2451 }
2348 } 2458 }
2349 2459
2350 ComplexMatrix 2460 ComplexMatrix
2351 SparseComplexMatrix::ltsolve (SparseType &mattype, const Matrix& b, 2461 SparseComplexMatrix::ltsolve (SparseType &mattype, const Matrix& b,
2352 octave_idx_type& err, double& rcond, 2462 octave_idx_type& err, double& rcond,
2353 solve_singularity_handler sing_handler) const 2463 solve_singularity_handler sing_handler,
2464 bool calc_cond) const
2354 { 2465 {
2355 ComplexMatrix retval; 2466 ComplexMatrix retval;
2356 2467
2357 octave_idx_type nr = rows (); 2468 octave_idx_type nr = rows ();
2358 octave_idx_type nc = cols (); 2469 octave_idx_type nc = cols ();
2372 typ == SparseType::Lower) 2483 typ == SparseType::Lower)
2373 { 2484 {
2374 double anorm = 0.; 2485 double anorm = 0.;
2375 double ainvnorm = 0.; 2486 double ainvnorm = 0.;
2376 octave_idx_type b_nc = b.cols (); 2487 octave_idx_type b_nc = b.cols ();
2377 rcond = 0.; 2488 rcond = 1.;
2378 2489
2379 // Calculate the 1-norm of matrix for rcond calculation 2490 if (calc_cond)
2380 for (octave_idx_type j = 0; j < nc; j++) 2491 {
2381 { 2492 // Calculate the 1-norm of matrix for rcond calculation
2382 double atmp = 0.; 2493 for (octave_idx_type j = 0; j < nc; j++)
2383 for (octave_idx_type i = cidx(j); i < cidx(j+1); i++) 2494 {
2384 atmp += std::abs(data(i)); 2495 double atmp = 0.;
2385 if (atmp > anorm) 2496 for (octave_idx_type i = cidx(j); i < cidx(j+1); i++)
2386 anorm = atmp; 2497 atmp += std::abs(data(i));
2498 if (atmp > anorm)
2499 anorm = atmp;
2500 }
2387 } 2501 }
2388 2502
2389 if (typ == SparseType::Permuted_Lower) 2503 if (typ == SparseType::Permuted_Lower)
2390 { 2504 {
2391 retval.resize (nc, b_nc); 2505 retval.resize (nc, b_nc);
2411 { 2525 {
2412 minr = perm[ridx(i)]; 2526 minr = perm[ridx(i)];
2413 mini = i; 2527 mini = i;
2414 } 2528 }
2415 2529
2416 if (minr != k) 2530 if (minr != k || data (mini) == 0.)
2417 { 2531 {
2418 err = -2; 2532 err = -2;
2419 goto triangular_error; 2533 goto triangular_error;
2420 } 2534 }
2421 2535
2434 2548
2435 for (octave_idx_type i = 0; i < nc; i++) 2549 for (octave_idx_type i = 0; i < nc; i++)
2436 retval (i, j) = work[i]; 2550 retval (i, j) = work[i];
2437 } 2551 }
2438 2552
2439 // Calculation of 1-norm of inv(*this) 2553 if (calc_cond)
2440 for (octave_idx_type i = 0; i < nm; i++) 2554 {
2441 work[i] = 0.; 2555 // Calculation of 1-norm of inv(*this)
2442 2556 for (octave_idx_type i = 0; i < nm; i++)
2443 for (octave_idx_type j = 0; j < nr; j++) 2557 work[i] = 0.;
2444 { 2558
2445 work[j] = 1.; 2559 for (octave_idx_type j = 0; j < nr; j++)
2446 2560 {
2447 for (octave_idx_type k = 0; k < nc; k++) 2561 work[j] = 1.;
2448 { 2562
2449 if (work[k] != 0.) 2563 for (octave_idx_type k = 0; k < nc; k++)
2450 { 2564 {
2451 octave_idx_type minr = nr; 2565 if (work[k] != 0.)
2452 octave_idx_type mini = 0;
2453
2454 for (octave_idx_type i = cidx(k); i < cidx(k+1); i++)
2455 if (perm[ridx(i)] < minr)
2456 {
2457 minr = perm[ridx(i)];
2458 mini = i;
2459 }
2460
2461 Complex tmp = work[k] / data(mini);
2462 work[k] = tmp;
2463 for (octave_idx_type i = cidx(k); i < cidx(k+1); i++)
2464 { 2566 {
2465 if (i == mini) 2567 octave_idx_type minr = nr;
2466 continue; 2568 octave_idx_type mini = 0;
2467 2569
2468 octave_idx_type iidx = perm[ridx(i)]; 2570 for (octave_idx_type i = cidx(k);
2469 work[iidx] = work[iidx] - tmp * data(i); 2571 i < cidx(k+1); i++)
2572 if (perm[ridx(i)] < minr)
2573 {
2574 minr = perm[ridx(i)];
2575 mini = i;
2576 }
2577
2578 Complex tmp = work[k] / data(mini);
2579 work[k] = tmp;
2580 for (octave_idx_type i = cidx(k);
2581 i < cidx(k+1); i++)
2582 {
2583 if (i == mini)
2584 continue;
2585
2586 octave_idx_type iidx = perm[ridx(i)];
2587 work[iidx] = work[iidx] - tmp * data(i);
2588 }
2470 } 2589 }
2471 } 2590 }
2472 } 2591
2473 2592 double atmp = 0;
2474 double atmp = 0; 2593 for (octave_idx_type i = j; i < nc; i++)
2475 for (octave_idx_type i = j; i < nc; i++) 2594 {
2476 { 2595 atmp += std::abs(work[i]);
2477 atmp += std::abs(work[i]); 2596 work[i] = 0.;
2478 work[i] = 0.; 2597 }
2479 } 2598 if (atmp > ainvnorm)
2480 if (atmp > ainvnorm) 2599 ainvnorm = atmp;
2481 ainvnorm = atmp; 2600 }
2601 rcond = 1. / ainvnorm / anorm;
2482 } 2602 }
2483 } 2603 }
2484 else 2604 else
2485 { 2605 {
2486 OCTAVE_LOCAL_BUFFER (Complex, work, nm); 2606 OCTAVE_LOCAL_BUFFER (Complex, work, nm);
2494 work[i] = 0.; 2614 work[i] = 0.;
2495 for (octave_idx_type k = 0; k < nc; k++) 2615 for (octave_idx_type k = 0; k < nc; k++)
2496 { 2616 {
2497 if (work[k] != 0.) 2617 if (work[k] != 0.)
2498 { 2618 {
2499 if (ridx(cidx(k)) != k) 2619 if (ridx(cidx(k)) != k ||
2620 data(cidx(k)) == 0.)
2500 { 2621 {
2501 err = -2; 2622 err = -2;
2502 goto triangular_error; 2623 goto triangular_error;
2503 } 2624 }
2504 2625
2513 } 2634 }
2514 for (octave_idx_type i = 0; i < nc; i++) 2635 for (octave_idx_type i = 0; i < nc; i++)
2515 retval.xelem (i, j) = work[i]; 2636 retval.xelem (i, j) = work[i];
2516 } 2637 }
2517 2638
2518 // Calculation of 1-norm of inv(*this) 2639 if (calc_cond)
2519 for (octave_idx_type i = 0; i < nm; i++) 2640 {
2520 work[i] = 0.; 2641 // Calculation of 1-norm of inv(*this)
2521 2642 for (octave_idx_type i = 0; i < nm; i++)
2522 for (octave_idx_type j = 0; j < nr; j++) 2643 work[i] = 0.;
2523 { 2644
2524 work[j] = 1.; 2645 for (octave_idx_type j = 0; j < nr; j++)
2525 2646 {
2526 for (octave_idx_type k = j; k < nc; k++) 2647 work[j] = 1.;
2527 { 2648
2528 2649 for (octave_idx_type k = j; k < nc; k++)
2529 if (work[k] != 0.)
2530 { 2650 {
2531 Complex tmp = work[k] / data(cidx(k)); 2651
2532 work[k] = tmp; 2652 if (work[k] != 0.)
2533 for (octave_idx_type i = cidx(k)+1; i < cidx(k+1); i++)
2534 { 2653 {
2535 octave_idx_type iidx = ridx(i); 2654 Complex tmp = work[k] / data(cidx(k));
2536 work[iidx] = work[iidx] - tmp * data(i); 2655 work[k] = tmp;
2656 for (octave_idx_type i = cidx(k)+1;
2657 i < cidx(k+1); i++)
2658 {
2659 octave_idx_type iidx = ridx(i);
2660 work[iidx] = work[iidx] - tmp * data(i);
2661 }
2537 } 2662 }
2538 } 2663 }
2539 } 2664 double atmp = 0;
2540 double atmp = 0; 2665 for (octave_idx_type i = j; i < nc; i++)
2541 for (octave_idx_type i = j; i < nc; i++) 2666 {
2542 { 2667 atmp += std::abs(work[i]);
2543 atmp += std::abs(work[i]); 2668 work[i] = 0.;
2544 work[i] = 0.; 2669 }
2545 } 2670 if (atmp > ainvnorm)
2546 if (atmp > ainvnorm) 2671 ainvnorm = atmp;
2547 ainvnorm = atmp; 2672 }
2548 } 2673 rcond = 1. / ainvnorm / anorm;
2549 } 2674 }
2550 2675 }
2551 rcond = 1. / ainvnorm / anorm;
2552
2553 triangular_error: 2676 triangular_error:
2554 if (err != 0) 2677 if (err != 0)
2555 { 2678 {
2556 if (sing_handler) 2679 if (sing_handler)
2557 sing_handler (rcond); 2680 {
2681 sing_handler (rcond);
2682 mattype.mark_as_rectangular ();
2683 }
2558 else 2684 else
2559 (*current_liboctave_error_handler) 2685 (*current_liboctave_error_handler)
2560 ("SparseComplexMatrix::solve matrix singular to machine precision, rcond = %g", 2686 ("SparseComplexMatrix::solve matrix singular to machine precision, rcond = %g",
2561 rcond); 2687 rcond);
2562 } 2688 }
2566 if (rcond_plus_one == 1.0 || xisnan (rcond)) 2692 if (rcond_plus_one == 1.0 || xisnan (rcond))
2567 { 2693 {
2568 err = -2; 2694 err = -2;
2569 2695
2570 if (sing_handler) 2696 if (sing_handler)
2571 sing_handler (rcond); 2697 {
2698 sing_handler (rcond);
2699 mattype.mark_as_rectangular ();
2700 }
2572 else 2701 else
2573 (*current_liboctave_error_handler) 2702 (*current_liboctave_error_handler)
2574 ("matrix singular to machine precision, rcond = %g", 2703 ("matrix singular to machine precision, rcond = %g",
2575 rcond); 2704 rcond);
2576 } 2705 }
2583 } 2712 }
2584 2713
2585 SparseComplexMatrix 2714 SparseComplexMatrix
2586 SparseComplexMatrix::ltsolve (SparseType &mattype, const SparseMatrix& b, 2715 SparseComplexMatrix::ltsolve (SparseType &mattype, const SparseMatrix& b,
2587 octave_idx_type& err, double& rcond, 2716 octave_idx_type& err, double& rcond,
2588 solve_singularity_handler sing_handler) const 2717 solve_singularity_handler sing_handler,
2718 bool calc_cond) const
2589 { 2719 {
2590 SparseComplexMatrix retval; 2720 SparseComplexMatrix retval;
2591 2721
2592 octave_idx_type nr = rows (); 2722 octave_idx_type nr = rows ();
2593 octave_idx_type nc = cols (); 2723 octave_idx_type nc = cols ();
2607 if (typ == SparseType::Permuted_Lower || 2737 if (typ == SparseType::Permuted_Lower ||
2608 typ == SparseType::Lower) 2738 typ == SparseType::Lower)
2609 { 2739 {
2610 double anorm = 0.; 2740 double anorm = 0.;
2611 double ainvnorm = 0.; 2741 double ainvnorm = 0.;
2612 rcond = 0.; 2742 rcond = 1.;
2613 2743
2614 // Calculate the 1-norm of matrix for rcond calculation 2744 if (calc_cond)
2615 for (octave_idx_type j = 0; j < nc; j++) 2745 {
2616 { 2746 // Calculate the 1-norm of matrix for rcond calculation
2617 double atmp = 0.; 2747 for (octave_idx_type j = 0; j < nc; j++)
2618 for (octave_idx_type i = cidx(j); i < cidx(j+1); i++) 2748 {
2619 atmp += std::abs(data(i)); 2749 double atmp = 0.;
2620 if (atmp > anorm) 2750 for (octave_idx_type i = cidx(j); i < cidx(j+1); i++)
2621 anorm = atmp; 2751 atmp += std::abs(data(i));
2752 if (atmp > anorm)
2753 anorm = atmp;
2754 }
2622 } 2755 }
2623 2756
2624 octave_idx_type b_nc = b.cols (); 2757 octave_idx_type b_nc = b.cols ();
2625 octave_idx_type b_nz = b.nzmax (); 2758 octave_idx_type b_nz = b.nnz ();
2626 retval = SparseComplexMatrix (nc, b_nc, b_nz); 2759 retval = SparseComplexMatrix (nc, b_nc, b_nz);
2627 retval.xcidx(0) = 0; 2760 retval.xcidx(0) = 0;
2628 octave_idx_type ii = 0; 2761 octave_idx_type ii = 0;
2629 octave_idx_type x_nz = b_nz; 2762 octave_idx_type x_nz = b_nz;
2630 2763
2652 { 2785 {
2653 minr = perm[ridx(i)]; 2786 minr = perm[ridx(i)];
2654 mini = i; 2787 mini = i;
2655 } 2788 }
2656 2789
2657 if (minr != k) 2790 if (minr != k || data (mini) == 0.)
2658 { 2791 {
2659 err = -2; 2792 err = -2;
2660 goto triangular_error; 2793 goto triangular_error;
2661 } 2794 }
2662 2795
2697 retval.xcidx(j+1) = ii; 2830 retval.xcidx(j+1) = ii;
2698 } 2831 }
2699 2832
2700 retval.maybe_compress (); 2833 retval.maybe_compress ();
2701 2834
2702 // Calculation of 1-norm of inv(*this) 2835 if (calc_cond)
2703 for (octave_idx_type i = 0; i < nm; i++) 2836 {
2704 work[i] = 0.; 2837 // Calculation of 1-norm of inv(*this)
2705 2838 for (octave_idx_type i = 0; i < nm; i++)
2706 for (octave_idx_type j = 0; j < nr; j++) 2839 work[i] = 0.;
2707 { 2840
2708 work[j] = 1.; 2841 for (octave_idx_type j = 0; j < nr; j++)
2709 2842 {
2710 for (octave_idx_type k = 0; k < nc; k++) 2843 work[j] = 1.;
2711 { 2844
2712 if (work[k] != 0.) 2845 for (octave_idx_type k = 0; k < nc; k++)
2713 { 2846 {
2714 octave_idx_type minr = nr; 2847 if (work[k] != 0.)
2715 octave_idx_type mini = 0;
2716
2717 for (octave_idx_type i = cidx(k); i < cidx(k+1); i++)
2718 if (perm[ridx(i)] < minr)
2719 {
2720 minr = perm[ridx(i)];
2721 mini = i;
2722 }
2723
2724 Complex tmp = work[k] / data(mini);
2725 work[k] = tmp;
2726 for (octave_idx_type i = cidx(k); i < cidx(k+1); i++)
2727 { 2848 {
2728 if (i == mini) 2849 octave_idx_type minr = nr;
2729 continue; 2850 octave_idx_type mini = 0;
2730 2851
2731 octave_idx_type iidx = perm[ridx(i)]; 2852 for (octave_idx_type i = cidx(k);
2732 work[iidx] = work[iidx] - tmp * data(i); 2853 i < cidx(k+1); i++)
2854 if (perm[ridx(i)] < minr)
2855 {
2856 minr = perm[ridx(i)];
2857 mini = i;
2858 }
2859
2860 Complex tmp = work[k] / data(mini);
2861 work[k] = tmp;
2862 for (octave_idx_type i = cidx(k);
2863 i < cidx(k+1); i++)
2864 {
2865 if (i == mini)
2866 continue;
2867
2868 octave_idx_type iidx = perm[ridx(i)];
2869 work[iidx] = work[iidx] - tmp * data(i);
2870 }
2733 } 2871 }
2734 } 2872 }
2735 } 2873
2736 2874 double atmp = 0;
2737 double atmp = 0; 2875 for (octave_idx_type i = j; i < nc; i++)
2738 for (octave_idx_type i = j; i < nc; i++) 2876 {
2739 { 2877 atmp += std::abs(work[i]);
2740 atmp += std::abs(work[i]); 2878 work[i] = 0.;
2741 work[i] = 0.; 2879 }
2742 } 2880 if (atmp > ainvnorm)
2743 if (atmp > ainvnorm) 2881 ainvnorm = atmp;
2744 ainvnorm = atmp; 2882 }
2883 rcond = 1. / ainvnorm / anorm;
2745 } 2884 }
2746 } 2885 }
2747 else 2886 else
2748 { 2887 {
2749 OCTAVE_LOCAL_BUFFER (Complex, work, nm); 2888 OCTAVE_LOCAL_BUFFER (Complex, work, nm);
2757 2896
2758 for (octave_idx_type k = 0; k < nc; k++) 2897 for (octave_idx_type k = 0; k < nc; k++)
2759 { 2898 {
2760 if (work[k] != 0.) 2899 if (work[k] != 0.)
2761 { 2900 {
2762 if (ridx(cidx(k)) != k) 2901 if (ridx(cidx(k)) != k ||
2902 data(cidx(k)) == 0.)
2763 { 2903 {
2764 err = -2; 2904 err = -2;
2765 goto triangular_error; 2905 goto triangular_error;
2766 } 2906 }
2767 2907
2799 retval.xcidx(j+1) = ii; 2939 retval.xcidx(j+1) = ii;
2800 } 2940 }
2801 2941
2802 retval.maybe_compress (); 2942 retval.maybe_compress ();
2803 2943
2804 // Calculation of 1-norm of inv(*this) 2944 if (calc_cond)
2805 for (octave_idx_type i = 0; i < nm; i++) 2945 {
2806 work[i] = 0.; 2946 // Calculation of 1-norm of inv(*this)
2807 2947 for (octave_idx_type i = 0; i < nm; i++)
2808 for (octave_idx_type j = 0; j < nr; j++) 2948 work[i] = 0.;
2809 { 2949
2810 work[j] = 1.; 2950 for (octave_idx_type j = 0; j < nr; j++)
2811 2951 {
2812 for (octave_idx_type k = j; k < nc; k++) 2952 work[j] = 1.;
2813 { 2953
2814 2954 for (octave_idx_type k = j; k < nc; k++)
2815 if (work[k] != 0.)
2816 { 2955 {
2817 Complex tmp = work[k] / data(cidx(k)); 2956
2818 work[k] = tmp; 2957 if (work[k] != 0.)
2819 for (octave_idx_type i = cidx(k)+1; i < cidx(k+1); i++)
2820 { 2958 {
2821 octave_idx_type iidx = ridx(i); 2959 Complex tmp = work[k] / data(cidx(k));
2822 work[iidx] = work[iidx] - tmp * data(i); 2960 work[k] = tmp;
2961 for (octave_idx_type i = cidx(k)+1;
2962 i < cidx(k+1); i++)
2963 {
2964 octave_idx_type iidx = ridx(i);
2965 work[iidx] = work[iidx] - tmp * data(i);
2966 }
2823 } 2967 }
2824 } 2968 }
2825 } 2969 double atmp = 0;
2826 double atmp = 0; 2970 for (octave_idx_type i = j; i < nc; i++)
2827 for (octave_idx_type i = j; i < nc; i++) 2971 {
2828 { 2972 atmp += std::abs(work[i]);
2829 atmp += std::abs(work[i]); 2973 work[i] = 0.;
2830 work[i] = 0.; 2974 }
2831 } 2975 if (atmp > ainvnorm)
2832 if (atmp > ainvnorm) 2976 ainvnorm = atmp;
2833 ainvnorm = atmp; 2977 }
2834 } 2978 rcond = 1. / ainvnorm / anorm;
2835 2979 }
2836 } 2980 }
2837
2838 rcond = 1. / ainvnorm / anorm;
2839 2981
2840 triangular_error: 2982 triangular_error:
2841 if (err != 0) 2983 if (err != 0)
2842 { 2984 {
2843 if (sing_handler) 2985 if (sing_handler)
2844 sing_handler (rcond); 2986 {
2987 sing_handler (rcond);
2988 mattype.mark_as_rectangular ();
2989 }
2845 else 2990 else
2846 (*current_liboctave_error_handler) 2991 (*current_liboctave_error_handler)
2847 ("SparseComplexMatrix::solve matrix singular to machine precision, rcond = %g", 2992 ("SparseComplexMatrix::solve matrix singular to machine precision, rcond = %g",
2848 rcond); 2993 rcond);
2849 } 2994 }
2853 if (rcond_plus_one == 1.0 || xisnan (rcond)) 2998 if (rcond_plus_one == 1.0 || xisnan (rcond))
2854 { 2999 {
2855 err = -2; 3000 err = -2;
2856 3001
2857 if (sing_handler) 3002 if (sing_handler)
2858 sing_handler (rcond); 3003 {
3004 sing_handler (rcond);
3005 mattype.mark_as_rectangular ();
3006 }
2859 else 3007 else
2860 (*current_liboctave_error_handler) 3008 (*current_liboctave_error_handler)
2861 ("matrix singular to machine precision, rcond = %g", 3009 ("matrix singular to machine precision, rcond = %g",
2862 rcond); 3010 rcond);
2863 } 3011 }
2870 } 3018 }
2871 3019
2872 ComplexMatrix 3020 ComplexMatrix
2873 SparseComplexMatrix::ltsolve (SparseType &mattype, const ComplexMatrix& b, 3021 SparseComplexMatrix::ltsolve (SparseType &mattype, const ComplexMatrix& b,
2874 octave_idx_type& err, double& rcond, 3022 octave_idx_type& err, double& rcond,
2875 solve_singularity_handler sing_handler) const 3023 solve_singularity_handler sing_handler,
3024 bool calc_cond) const
2876 { 3025 {
2877 ComplexMatrix retval; 3026 ComplexMatrix retval;
2878 3027
2879 octave_idx_type nr = rows (); 3028 octave_idx_type nr = rows ();
2880 octave_idx_type nc = cols (); 3029 octave_idx_type nc = cols ();
2894 typ == SparseType::Lower) 3043 typ == SparseType::Lower)
2895 { 3044 {
2896 double anorm = 0.; 3045 double anorm = 0.;
2897 double ainvnorm = 0.; 3046 double ainvnorm = 0.;
2898 octave_idx_type b_nc = b.cols (); 3047 octave_idx_type b_nc = b.cols ();
2899 rcond = 0.; 3048 rcond = 1.;
2900 3049
2901 // Calculate the 1-norm of matrix for rcond calculation 3050 if (calc_cond)
2902 for (octave_idx_type j = 0; j < nc; j++) 3051 {
2903 { 3052 // Calculate the 1-norm of matrix for rcond calculation
2904 double atmp = 0.; 3053 for (octave_idx_type j = 0; j < nc; j++)
2905 for (octave_idx_type i = cidx(j); i < cidx(j+1); i++) 3054 {
2906 atmp += std::abs(data(i)); 3055 double atmp = 0.;
2907 if (atmp > anorm) 3056 for (octave_idx_type i = cidx(j); i < cidx(j+1); i++)
2908 anorm = atmp; 3057 atmp += std::abs(data(i));
3058 if (atmp > anorm)
3059 anorm = atmp;
3060 }
2909 } 3061 }
2910 3062
2911 if (typ == SparseType::Permuted_Lower) 3063 if (typ == SparseType::Permuted_Lower)
2912 { 3064 {
2913 retval.resize (nc, b_nc); 3065 retval.resize (nc, b_nc);
2933 { 3085 {
2934 minr = perm[ridx(i)]; 3086 minr = perm[ridx(i)];
2935 mini = i; 3087 mini = i;
2936 } 3088 }
2937 3089
2938 if (minr != k) 3090 if (minr != k || data (mini) == 0.)
2939 { 3091 {
2940 err = -2; 3092 err = -2;
2941 goto triangular_error; 3093 goto triangular_error;
2942 } 3094 }
2943 3095
2956 3108
2957 for (octave_idx_type i = 0; i < nc; i++) 3109 for (octave_idx_type i = 0; i < nc; i++)
2958 retval (i, j) = work[i]; 3110 retval (i, j) = work[i];
2959 } 3111 }
2960 3112
2961 // Calculation of 1-norm of inv(*this) 3113 if (calc_cond)
2962 for (octave_idx_type i = 0; i < nm; i++) 3114 {
2963 work[i] = 0.; 3115 // Calculation of 1-norm of inv(*this)
2964 3116 for (octave_idx_type i = 0; i < nm; i++)
2965 for (octave_idx_type j = 0; j < nr; j++) 3117 work[i] = 0.;
2966 { 3118
2967 work[j] = 1.; 3119 for (octave_idx_type j = 0; j < nr; j++)
2968 3120 {
2969 for (octave_idx_type k = 0; k < nc; k++) 3121 work[j] = 1.;
2970 { 3122
2971 if (work[k] != 0.) 3123 for (octave_idx_type k = 0; k < nc; k++)
2972 { 3124 {
2973 octave_idx_type minr = nr; 3125 if (work[k] != 0.)
2974 octave_idx_type mini = 0;
2975
2976 for (octave_idx_type i = cidx(k); i < cidx(k+1); i++)
2977 if (perm[ridx(i)] < minr)
2978 {
2979 minr = perm[ridx(i)];
2980 mini = i;
2981 }
2982
2983 Complex tmp = work[k] / data(mini);
2984 work[k] = tmp;
2985 for (octave_idx_type i = cidx(k); i < cidx(k+1); i++)
2986 { 3126 {
2987 if (i == mini) 3127 octave_idx_type minr = nr;
2988 continue; 3128 octave_idx_type mini = 0;
2989 3129
2990 octave_idx_type iidx = perm[ridx(i)]; 3130 for (octave_idx_type i = cidx(k);
2991 work[iidx] = work[iidx] - tmp * data(i); 3131 i < cidx(k+1); i++)
3132 if (perm[ridx(i)] < minr)
3133 {
3134 minr = perm[ridx(i)];
3135 mini = i;
3136 }
3137
3138 Complex tmp = work[k] / data(mini);
3139 work[k] = tmp;
3140 for (octave_idx_type i = cidx(k);
3141 i < cidx(k+1); i++)
3142 {
3143 if (i == mini)
3144 continue;
3145
3146 octave_idx_type iidx = perm[ridx(i)];
3147 work[iidx] = work[iidx] - tmp * data(i);
3148 }
2992 } 3149 }
2993 } 3150 }
2994 } 3151
2995 3152 double atmp = 0;
2996 double atmp = 0; 3153 for (octave_idx_type i = j; i < nc; i++)
2997 for (octave_idx_type i = j; i < nc; i++) 3154 {
2998 { 3155 atmp += std::abs(work[i]);
2999 atmp += std::abs(work[i]); 3156 work[i] = 0.;
3000 work[i] = 0.; 3157 }
3001 } 3158 if (atmp > ainvnorm)
3002 if (atmp > ainvnorm) 3159 ainvnorm = atmp;
3003 ainvnorm = atmp; 3160 }
3161 rcond = 1. / ainvnorm / anorm;
3004 } 3162 }
3005 } 3163 }
3006 else 3164 else
3007 { 3165 {
3008 OCTAVE_LOCAL_BUFFER (Complex, work, nm); 3166 OCTAVE_LOCAL_BUFFER (Complex, work, nm);
3018 3176
3019 for (octave_idx_type k = 0; k < nc; k++) 3177 for (octave_idx_type k = 0; k < nc; k++)
3020 { 3178 {
3021 if (work[k] != 0.) 3179 if (work[k] != 0.)
3022 { 3180 {
3023 if (ridx(cidx(k)) != k) 3181 if (ridx(cidx(k)) != k ||
3182 data(cidx(k)) == 0.)
3024 { 3183 {
3025 err = -2; 3184 err = -2;
3026 goto triangular_error; 3185 goto triangular_error;
3027 } 3186 }
3028 3187
3038 3197
3039 for (octave_idx_type i = 0; i < nc; i++) 3198 for (octave_idx_type i = 0; i < nc; i++)
3040 retval.xelem (i, j) = work[i]; 3199 retval.xelem (i, j) = work[i];
3041 } 3200 }
3042 3201
3043 // Calculation of 1-norm of inv(*this) 3202 if (calc_cond)
3044 for (octave_idx_type i = 0; i < nm; i++) 3203 {
3045 work[i] = 0.; 3204 // Calculation of 1-norm of inv(*this)
3046 3205 for (octave_idx_type i = 0; i < nm; i++)
3047 for (octave_idx_type j = 0; j < nr; j++) 3206 work[i] = 0.;
3048 { 3207
3049 work[j] = 1.; 3208 for (octave_idx_type j = 0; j < nr; j++)
3050 3209 {
3051 for (octave_idx_type k = j; k < nc; k++) 3210 work[j] = 1.;
3052 { 3211
3053 3212 for (octave_idx_type k = j; k < nc; k++)
3054 if (work[k] != 0.)
3055 { 3213 {
3056 Complex tmp = work[k] / data(cidx(k)); 3214
3057 work[k] = tmp; 3215 if (work[k] != 0.)
3058 for (octave_idx_type i = cidx(k)+1; i < cidx(k+1); i++)
3059 { 3216 {
3060 octave_idx_type iidx = ridx(i); 3217 Complex tmp = work[k] / data(cidx(k));
3061 work[iidx] = work[iidx] - tmp * data(i); 3218 work[k] = tmp;
3219 for (octave_idx_type i = cidx(k)+1;
3220 i < cidx(k+1); i++)
3221 {
3222 octave_idx_type iidx = ridx(i);
3223 work[iidx] = work[iidx] - tmp * data(i);
3224 }
3062 } 3225 }
3063 } 3226 }
3064 } 3227 double atmp = 0;
3065 double atmp = 0; 3228 for (octave_idx_type i = j; i < nc; i++)
3066 for (octave_idx_type i = j; i < nc; i++) 3229 {
3067 { 3230 atmp += std::abs(work[i]);
3068 atmp += std::abs(work[i]); 3231 work[i] = 0.;
3069 work[i] = 0.; 3232 }
3070 } 3233 if (atmp > ainvnorm)
3071 if (atmp > ainvnorm) 3234 ainvnorm = atmp;
3072 ainvnorm = atmp; 3235 }
3073 } 3236 rcond = 1. / ainvnorm / anorm;
3074 3237 }
3075 } 3238 }
3076
3077 rcond = 1. / ainvnorm / anorm;
3078 3239
3079 triangular_error: 3240 triangular_error:
3080 if (err != 0) 3241 if (err != 0)
3081 { 3242 {
3082 if (sing_handler) 3243 if (sing_handler)
3083 sing_handler (rcond); 3244 {
3245 sing_handler (rcond);
3246 mattype.mark_as_rectangular ();
3247 }
3084 else 3248 else
3085 (*current_liboctave_error_handler) 3249 (*current_liboctave_error_handler)
3086 ("SparseComplexMatrix::solve matrix singular to machine precision, rcond = %g", 3250 ("SparseComplexMatrix::solve matrix singular to machine precision, rcond = %g",
3087 rcond); 3251 rcond);
3088 } 3252 }
3092 if (rcond_plus_one == 1.0 || xisnan (rcond)) 3256 if (rcond_plus_one == 1.0 || xisnan (rcond))
3093 { 3257 {
3094 err = -2; 3258 err = -2;
3095 3259
3096 if (sing_handler) 3260 if (sing_handler)
3097 sing_handler (rcond); 3261 {
3262 sing_handler (rcond);
3263 mattype.mark_as_rectangular ();
3264 }
3098 else 3265 else
3099 (*current_liboctave_error_handler) 3266 (*current_liboctave_error_handler)
3100 ("matrix singular to machine precision, rcond = %g", 3267 ("matrix singular to machine precision, rcond = %g",
3101 rcond); 3268 rcond);
3102 } 3269 }
3109 } 3276 }
3110 3277
3111 SparseComplexMatrix 3278 SparseComplexMatrix
3112 SparseComplexMatrix::ltsolve (SparseType &mattype, const SparseComplexMatrix& b, 3279 SparseComplexMatrix::ltsolve (SparseType &mattype, const SparseComplexMatrix& b,
3113 octave_idx_type& err, double& rcond, 3280 octave_idx_type& err, double& rcond,
3114 solve_singularity_handler sing_handler) const 3281 solve_singularity_handler sing_handler,
3282 bool calc_cond) const
3115 { 3283 {
3116 SparseComplexMatrix retval; 3284 SparseComplexMatrix retval;
3117 3285
3118 octave_idx_type nr = rows (); 3286 octave_idx_type nr = rows ();
3119 octave_idx_type nc = cols (); 3287 octave_idx_type nc = cols ();
3132 if (typ == SparseType::Permuted_Lower || 3300 if (typ == SparseType::Permuted_Lower ||
3133 typ == SparseType::Lower) 3301 typ == SparseType::Lower)
3134 { 3302 {
3135 double anorm = 0.; 3303 double anorm = 0.;
3136 double ainvnorm = 0.; 3304 double ainvnorm = 0.;
3137 rcond = 0.; 3305 rcond = 1.;
3138 3306
3139 // Calculate the 1-norm of matrix for rcond calculation 3307 if (calc_cond)
3140 for (octave_idx_type j = 0; j < nc; j++) 3308 {
3141 { 3309 // Calculate the 1-norm of matrix for rcond calculation
3142 double atmp = 0.; 3310 for (octave_idx_type j = 0; j < nc; j++)
3143 for (octave_idx_type i = cidx(j); i < cidx(j+1); i++) 3311 {
3144 atmp += std::abs(data(i)); 3312 double atmp = 0.;
3145 if (atmp > anorm) 3313 for (octave_idx_type i = cidx(j); i < cidx(j+1); i++)
3146 anorm = atmp; 3314 atmp += std::abs(data(i));
3315 if (atmp > anorm)
3316 anorm = atmp;
3317 }
3147 } 3318 }
3148 3319
3149 octave_idx_type b_nc = b.cols (); 3320 octave_idx_type b_nc = b.cols ();
3150 octave_idx_type b_nz = b.nzmax (); 3321 octave_idx_type b_nz = b.nnz ();
3151 retval = SparseComplexMatrix (nc, b_nc, b_nz); 3322 retval = SparseComplexMatrix (nc, b_nc, b_nz);
3152 retval.xcidx(0) = 0; 3323 retval.xcidx(0) = 0;
3153 octave_idx_type ii = 0; 3324 octave_idx_type ii = 0;
3154 octave_idx_type x_nz = b_nz; 3325 octave_idx_type x_nz = b_nz;
3155 3326
3177 { 3348 {
3178 minr = perm[ridx(i)]; 3349 minr = perm[ridx(i)];
3179 mini = i; 3350 mini = i;
3180 } 3351 }
3181 3352
3182 if (minr != k) 3353 if (minr != k || data (mini) == 0.)
3183 { 3354 {
3184 err = -2; 3355 err = -2;
3185 goto triangular_error; 3356 goto triangular_error;
3186 } 3357 }
3187 3358
3222 retval.xcidx(j+1) = ii; 3393 retval.xcidx(j+1) = ii;
3223 } 3394 }
3224 3395
3225 retval.maybe_compress (); 3396 retval.maybe_compress ();
3226 3397
3227 // Calculation of 1-norm of inv(*this) 3398 if (calc_cond)
3228 for (octave_idx_type i = 0; i < nm; i++) 3399 {
3229 work[i] = 0.; 3400 // Calculation of 1-norm of inv(*this)
3230 3401 for (octave_idx_type i = 0; i < nm; i++)
3231 for (octave_idx_type j = 0; j < nr; j++) 3402 work[i] = 0.;
3232 { 3403
3233 work[j] = 1.; 3404 for (octave_idx_type j = 0; j < nr; j++)
3234 3405 {
3235 for (octave_idx_type k = 0; k < nc; k++) 3406 work[j] = 1.;
3236 { 3407
3237 if (work[k] != 0.) 3408 for (octave_idx_type k = 0; k < nc; k++)
3238 { 3409 {
3239 octave_idx_type minr = nr; 3410 if (work[k] != 0.)
3240 octave_idx_type mini = 0;
3241
3242 for (octave_idx_type i = cidx(k); i < cidx(k+1); i++)
3243 if (perm[ridx(i)] < minr)
3244 {
3245 minr = perm[ridx(i)];
3246 mini = i;
3247 }
3248
3249 Complex tmp = work[k] / data(mini);
3250 work[k] = tmp;
3251 for (octave_idx_type i = cidx(k); i < cidx(k+1); i++)
3252 { 3411 {
3253 if (i == mini) 3412 octave_idx_type minr = nr;
3254 continue; 3413 octave_idx_type mini = 0;
3255 3414
3256 octave_idx_type iidx = perm[ridx(i)]; 3415 for (octave_idx_type i = cidx(k);
3257 work[iidx] = work[iidx] - tmp * data(i); 3416 i < cidx(k+1); i++)
3417 if (perm[ridx(i)] < minr)
3418 {
3419 minr = perm[ridx(i)];
3420 mini = i;
3421 }
3422
3423 Complex tmp = work[k] / data(mini);
3424 work[k] = tmp;
3425 for (octave_idx_type i = cidx(k);
3426 i < cidx(k+1); i++)
3427 {
3428 if (i == mini)
3429 continue;
3430
3431 octave_idx_type iidx = perm[ridx(i)];
3432 work[iidx] = work[iidx] - tmp * data(i);
3433 }
3258 } 3434 }
3259 } 3435 }
3260 } 3436
3261 3437 double atmp = 0;
3262 double atmp = 0; 3438 for (octave_idx_type i = j; i < nc; i++)
3263 for (octave_idx_type i = j; i < nc; i++) 3439 {
3264 { 3440 atmp += std::abs(work[i]);
3265 atmp += std::abs(work[i]); 3441 work[i] = 0.;
3266 work[i] = 0.; 3442 }
3267 } 3443 if (atmp > ainvnorm)
3268 if (atmp > ainvnorm) 3444 ainvnorm = atmp;
3269 ainvnorm = atmp; 3445 }
3446 rcond = 1. / ainvnorm / anorm;
3270 } 3447 }
3271 } 3448 }
3272 else 3449 else
3273 { 3450 {
3274 OCTAVE_LOCAL_BUFFER (Complex, work, nm); 3451 OCTAVE_LOCAL_BUFFER (Complex, work, nm);
3282 3459
3283 for (octave_idx_type k = 0; k < nc; k++) 3460 for (octave_idx_type k = 0; k < nc; k++)
3284 { 3461 {
3285 if (work[k] != 0.) 3462 if (work[k] != 0.)
3286 { 3463 {
3287 if (ridx(cidx(k)) != k) 3464 if (ridx(cidx(k)) != k ||
3465 data(cidx(k)) == 0.)
3288 { 3466 {
3289 err = -2; 3467 err = -2;
3290 goto triangular_error; 3468 goto triangular_error;
3291 } 3469 }
3292 3470
3324 retval.xcidx(j+1) = ii; 3502 retval.xcidx(j+1) = ii;
3325 } 3503 }
3326 3504
3327 retval.maybe_compress (); 3505 retval.maybe_compress ();
3328 3506
3329 // Calculation of 1-norm of inv(*this) 3507 if (calc_cond)
3330 for (octave_idx_type i = 0; i < nm; i++) 3508 {
3331 work[i] = 0.; 3509 // Calculation of 1-norm of inv(*this)
3332 3510 for (octave_idx_type i = 0; i < nm; i++)
3333 for (octave_idx_type j = 0; j < nr; j++) 3511 work[i] = 0.;
3334 { 3512
3335 work[j] = 1.; 3513 for (octave_idx_type j = 0; j < nr; j++)
3336 3514 {
3337 for (octave_idx_type k = j; k < nc; k++) 3515 work[j] = 1.;
3338 { 3516
3339 3517 for (octave_idx_type k = j; k < nc; k++)
3340 if (work[k] != 0.)
3341 { 3518 {
3342 Complex tmp = work[k] / data(cidx(k)); 3519
3343 work[k] = tmp; 3520 if (work[k] != 0.)
3344 for (octave_idx_type i = cidx(k)+1; i < cidx(k+1); i++)
3345 { 3521 {
3346 octave_idx_type iidx = ridx(i); 3522 Complex tmp = work[k] / data(cidx(k));
3347 work[iidx] = work[iidx] - tmp * data(i); 3523 work[k] = tmp;
3524 for (octave_idx_type i = cidx(k)+1;
3525 i < cidx(k+1); i++)
3526 {
3527 octave_idx_type iidx = ridx(i);
3528 work[iidx] = work[iidx] - tmp * data(i);
3529 }
3348 } 3530 }
3349 } 3531 }
3350 } 3532 double atmp = 0;
3351 double atmp = 0; 3533 for (octave_idx_type i = j; i < nc; i++)
3352 for (octave_idx_type i = j; i < nc; i++) 3534 {
3353 { 3535 atmp += std::abs(work[i]);
3354 atmp += std::abs(work[i]); 3536 work[i] = 0.;
3355 work[i] = 0.; 3537 }
3356 } 3538 if (atmp > ainvnorm)
3357 if (atmp > ainvnorm) 3539 ainvnorm = atmp;
3358 ainvnorm = atmp; 3540 }
3359 } 3541 rcond = 1. / ainvnorm / anorm;
3360 3542 }
3361 } 3543 }
3362
3363 rcond = 1. / ainvnorm / anorm;
3364 3544
3365 triangular_error: 3545 triangular_error:
3366 if (err != 0) 3546 if (err != 0)
3367 { 3547 {
3368 if (sing_handler) 3548 if (sing_handler)
3369 sing_handler (rcond); 3549 {
3550 sing_handler (rcond);
3551 mattype.mark_as_rectangular ();
3552 }
3370 else 3553 else
3371 (*current_liboctave_error_handler) 3554 (*current_liboctave_error_handler)
3372 ("SparseComplexMatrix::solve matrix singular to machine precision, rcond = %g", 3555 ("SparseComplexMatrix::solve matrix singular to machine precision, rcond = %g",
3373 rcond); 3556 rcond);
3374 } 3557 }
3378 if (rcond_plus_one == 1.0 || xisnan (rcond)) 3561 if (rcond_plus_one == 1.0 || xisnan (rcond))
3379 { 3562 {
3380 err = -2; 3563 err = -2;
3381 3564
3382 if (sing_handler) 3565 if (sing_handler)
3383 sing_handler (rcond); 3566 {
3567 sing_handler (rcond);
3568 mattype.mark_as_rectangular ();
3569 }
3384 else 3570 else
3385 (*current_liboctave_error_handler) 3571 (*current_liboctave_error_handler)
3386 ("matrix singular to machine precision, rcond = %g", 3572 ("matrix singular to machine precision, rcond = %g",
3387 rcond); 3573 rcond);
3388 } 3574 }
3393 3579
3394 return retval; 3580 return retval;
3395 } 3581 }
3396 3582
3397 ComplexMatrix 3583 ComplexMatrix
3398 SparseComplexMatrix::trisolve (SparseType &mattype, const Matrix& b, octave_idx_type& err, 3584 SparseComplexMatrix::trisolve (SparseType &mattype, const Matrix& b,
3399 double& rcond, 3585 octave_idx_type& err, double& rcond,
3400 solve_singularity_handler sing_handler) const 3586 solve_singularity_handler sing_handler,
3587 bool calc_cond) const
3401 { 3588 {
3402 ComplexMatrix retval; 3589 ComplexMatrix retval;
3403 3590
3404 octave_idx_type nr = rows (); 3591 octave_idx_type nr = rows ();
3405 octave_idx_type nc = cols (); 3592 octave_idx_type nc = cols ();
3406 err = 0; 3593 err = 0;
3407 3594
3408 if (nr == 0 || nc == 0 || nr != nc || nr != b.rows ()) 3595 if (nr == 0 || nc == 0 || nr != nc || nr != b.rows ())
3409 (*current_liboctave_error_handler) 3596 (*current_liboctave_error_handler)
3410 ("matrix dimension mismatch solution of linear equations"); 3597 ("matrix dimension mismatch solution of linear equations");
3598 else if (calc_cond)
3599 (*current_liboctave_error_handler)
3600 ("calculation of condition number not implemented");
3411 else 3601 else
3412 { 3602 {
3413 // Print spparms("spumoni") info if requested 3603 // Print spparms("spumoni") info if requested
3414 volatile int typ = mattype.type (); 3604 volatile int typ = mattype.type ();
3415 mattype.info (); 3605 mattype.info ();
3524 { 3714 {
3525 rcond = 0.; 3715 rcond = 0.;
3526 err = -2; 3716 err = -2;
3527 3717
3528 if (sing_handler) 3718 if (sing_handler)
3529 sing_handler (rcond); 3719 {
3720 sing_handler (rcond);
3721 mattype.mark_as_rectangular ();
3722 }
3530 else 3723 else
3531 (*current_liboctave_error_handler) 3724 (*current_liboctave_error_handler)
3532 ("matrix singular to machine precision"); 3725 ("matrix singular to machine precision");
3533 3726
3534 } 3727 }
3542 return retval; 3735 return retval;
3543 } 3736 }
3544 3737
3545 SparseComplexMatrix 3738 SparseComplexMatrix
3546 SparseComplexMatrix::trisolve (SparseType &mattype, const SparseMatrix& b, 3739 SparseComplexMatrix::trisolve (SparseType &mattype, const SparseMatrix& b,
3547 octave_idx_type& err, double& rcond, 3740 octave_idx_type& err, double& rcond,
3548 solve_singularity_handler sing_handler) const 3741 solve_singularity_handler sing_handler,
3742 bool calc_cond) const
3549 { 3743 {
3550 SparseComplexMatrix retval; 3744 SparseComplexMatrix retval;
3551 3745
3552 octave_idx_type nr = rows (); 3746 octave_idx_type nr = rows ();
3553 octave_idx_type nc = cols (); 3747 octave_idx_type nc = cols ();
3554 err = 0; 3748 err = 0;
3555 3749
3556 if (nr == 0 || nc == 0 || nr != nc || nr != b.rows ()) 3750 if (nr == 0 || nc == 0 || nr != nc || nr != b.rows ())
3557 (*current_liboctave_error_handler) 3751 (*current_liboctave_error_handler)
3558 ("matrix dimension mismatch solution of linear equations"); 3752 ("matrix dimension mismatch solution of linear equations");
3753 else if (calc_cond)
3754 (*current_liboctave_error_handler)
3755 ("calculation of condition number not implemented");
3559 else 3756 else
3560 { 3757 {
3561 // Print spparms("spumoni") info if requested 3758 // Print spparms("spumoni") info if requested
3562 int typ = mattype.type (); 3759 int typ = mattype.type ();
3563 mattype.info (); 3760 mattype.info ();
3612 if (f77_exception_encountered) 3809 if (f77_exception_encountered)
3613 (*current_liboctave_error_handler) 3810 (*current_liboctave_error_handler)
3614 ("unrecoverable error in zgttrf"); 3811 ("unrecoverable error in zgttrf");
3615 else 3812 else
3616 { 3813 {
3617 rcond = 0.0;
3618 if (err != 0) 3814 if (err != 0)
3619 { 3815 {
3620 err = -2; 3816 err = -2;
3817 rcond = 0.0;
3621 3818
3622 if (sing_handler) 3819 if (sing_handler)
3623 sing_handler (rcond); 3820 {
3821 sing_handler (rcond);
3822 mattype.mark_as_rectangular ();
3823 }
3624 else 3824 else
3625 (*current_liboctave_error_handler) 3825 (*current_liboctave_error_handler)
3626 ("matrix singular to machine precision"); 3826 ("matrix singular to machine precision");
3627 3827
3628 } 3828 }
3629 else 3829 else
3630 { 3830 {
3631 char job = 'N'; 3831 char job = 'N';
3632 volatile octave_idx_type x_nz = b.nzmax (); 3832 volatile octave_idx_type x_nz = b.nnz ();
3633 octave_idx_type b_nc = b.cols (); 3833 octave_idx_type b_nc = b.cols ();
3634 retval = SparseComplexMatrix (nr, b_nc, x_nz); 3834 retval = SparseComplexMatrix (nr, b_nc, x_nz);
3635 retval.xcidx(0) = 0; 3835 retval.xcidx(0) = 0;
3636 volatile octave_idx_type ii = 0; 3836 volatile octave_idx_type ii = 0;
3837 rcond = 1.0;
3637 3838
3638 OCTAVE_LOCAL_BUFFER (Complex, work, nr); 3839 OCTAVE_LOCAL_BUFFER (Complex, work, nr);
3639 3840
3640 for (volatile octave_idx_type j = 0; j < b_nc; j++) 3841 for (volatile octave_idx_type j = 0; j < b_nc; j++)
3641 { 3842 {
3693 } 3894 }
3694 3895
3695 ComplexMatrix 3896 ComplexMatrix
3696 SparseComplexMatrix::trisolve (SparseType &mattype, const ComplexMatrix& b, 3897 SparseComplexMatrix::trisolve (SparseType &mattype, const ComplexMatrix& b,
3697 octave_idx_type& err, double& rcond, 3898 octave_idx_type& err, double& rcond,
3698 solve_singularity_handler sing_handler) const 3899 solve_singularity_handler sing_handler,
3900 bool calc_cond) const
3699 { 3901 {
3700 ComplexMatrix retval; 3902 ComplexMatrix retval;
3701 3903
3702 octave_idx_type nr = rows (); 3904 octave_idx_type nr = rows ();
3703 octave_idx_type nc = cols (); 3905 octave_idx_type nc = cols ();
3704 err = 0; 3906 err = 0;
3705 3907
3706 if (nr == 0 || nc == 0 || nr != nc || nr != b.rows ()) 3908 if (nr == 0 || nc == 0 || nr != nc || nr != b.rows ())
3707 (*current_liboctave_error_handler) 3909 (*current_liboctave_error_handler)
3708 ("matrix dimension mismatch solution of linear equations"); 3910 ("matrix dimension mismatch solution of linear equations");
3911 else if (calc_cond)
3912 (*current_liboctave_error_handler)
3913 ("calculation of condition number not implemented");
3709 else 3914 else
3710 { 3915 {
3711 // Print spparms("spumoni") info if requested 3916 // Print spparms("spumoni") info if requested
3712 volatile int typ = mattype.type (); 3917 volatile int typ = mattype.type ();
3713 mattype.info (); 3918 mattype.info ();
3832 { 4037 {
3833 rcond = 0.; 4038 rcond = 0.;
3834 err = -2; 4039 err = -2;
3835 4040
3836 if (sing_handler) 4041 if (sing_handler)
3837 sing_handler (rcond); 4042 {
4043 sing_handler (rcond);
4044 mattype.mark_as_rectangular ();
4045 }
3838 else 4046 else
3839 (*current_liboctave_error_handler) 4047 (*current_liboctave_error_handler)
3840 ("matrix singular to machine precision"); 4048 ("matrix singular to machine precision");
3841 } 4049 }
3842 } 4050 }
3847 return retval; 4055 return retval;
3848 } 4056 }
3849 4057
3850 SparseComplexMatrix 4058 SparseComplexMatrix
3851 SparseComplexMatrix::trisolve (SparseType &mattype, 4059 SparseComplexMatrix::trisolve (SparseType &mattype,
3852 const SparseComplexMatrix& b, octave_idx_type& err, double& rcond, 4060 const SparseComplexMatrix& b,
3853 solve_singularity_handler sing_handler) const 4061 octave_idx_type& err, double& rcond,
4062 solve_singularity_handler sing_handler,
4063 bool calc_cond) const
3854 { 4064 {
3855 SparseComplexMatrix retval; 4065 SparseComplexMatrix retval;
3856 4066
3857 octave_idx_type nr = rows (); 4067 octave_idx_type nr = rows ();
3858 octave_idx_type nc = cols (); 4068 octave_idx_type nc = cols ();
3859 err = 0; 4069 err = 0;
3860 4070
3861 if (nr == 0 || nc == 0 || nr != nc || nr != b.rows ()) 4071 if (nr == 0 || nc == 0 || nr != nc || nr != b.rows ())
3862 (*current_liboctave_error_handler) 4072 (*current_liboctave_error_handler)
3863 ("matrix dimension mismatch solution of linear equations"); 4073 ("matrix dimension mismatch solution of linear equations");
4074 else if (calc_cond)
4075 (*current_liboctave_error_handler)
4076 ("calculation of condition number not implemented");
3864 else 4077 else
3865 { 4078 {
3866 // Print spparms("spumoni") info if requested 4079 // Print spparms("spumoni") info if requested
3867 int typ = mattype.type (); 4080 int typ = mattype.type ();
3868 mattype.info (); 4081 mattype.info ();
3917 if (f77_exception_encountered) 4130 if (f77_exception_encountered)
3918 (*current_liboctave_error_handler) 4131 (*current_liboctave_error_handler)
3919 ("unrecoverable error in zgttrf"); 4132 ("unrecoverable error in zgttrf");
3920 else 4133 else
3921 { 4134 {
3922 rcond = 0.0;
3923 if (err != 0) 4135 if (err != 0)
3924 { 4136 {
4137 rcond = 0.0;
3925 err = -2; 4138 err = -2;
3926 4139
3927 if (sing_handler) 4140 if (sing_handler)
3928 sing_handler (rcond); 4141 {
4142 sing_handler (rcond);
4143 mattype.mark_as_rectangular ();
4144 }
3929 else 4145 else
3930 (*current_liboctave_error_handler) 4146 (*current_liboctave_error_handler)
3931 ("matrix singular to machine precision"); 4147 ("matrix singular to machine precision");
3932 } 4148 }
3933 else 4149 else
3938 octave_idx_type b_nc = b.cols (); 4154 octave_idx_type b_nc = b.cols ();
3939 OCTAVE_LOCAL_BUFFER (Complex, Bx, b_nr); 4155 OCTAVE_LOCAL_BUFFER (Complex, Bx, b_nr);
3940 4156
3941 // Take a first guess that the number of non-zero terms 4157 // Take a first guess that the number of non-zero terms
3942 // will be as many as in b 4158 // will be as many as in b
3943 volatile octave_idx_type x_nz = b.nzmax (); 4159 volatile octave_idx_type x_nz = b.nnz ();
3944 volatile octave_idx_type ii = 0; 4160 volatile octave_idx_type ii = 0;
3945 retval = SparseComplexMatrix (b_nr, b_nc, x_nz); 4161 retval = SparseComplexMatrix (b_nr, b_nc, x_nz);
3946 4162
3947 retval.xcidx(0) = 0; 4163 retval.xcidx(0) = 0;
3948 for (volatile octave_idx_type j = 0; j < b_nc; j++) 4164 for (volatile octave_idx_type j = 0; j < b_nc; j++)
4008 4224
4009 return retval; 4225 return retval;
4010 } 4226 }
4011 4227
4012 ComplexMatrix 4228 ComplexMatrix
4013 SparseComplexMatrix::bsolve (SparseType &mattype, const Matrix& b, octave_idx_type& err, 4229 SparseComplexMatrix::bsolve (SparseType &mattype, const Matrix& b,
4014 double& rcond, 4230 octave_idx_type& err, double& rcond,
4015 solve_singularity_handler sing_handler) const 4231 solve_singularity_handler sing_handler,
4232 bool calc_cond) const
4016 { 4233 {
4017 ComplexMatrix retval; 4234 ComplexMatrix retval;
4018 4235
4019 octave_idx_type nr = rows (); 4236 octave_idx_type nr = rows ();
4020 octave_idx_type nc = cols (); 4237 octave_idx_type nc = cols ();
4052 if (ri >= j) 4269 if (ri >= j)
4053 m_band(ri - j, j) = data(i); 4270 m_band(ri - j, j) = data(i);
4054 } 4271 }
4055 4272
4056 // Calculate the norm of the matrix, for later use. 4273 // Calculate the norm of the matrix, for later use.
4057 // double anorm = m_band.abs().sum().row(0).max(); 4274 double anorm;
4275 if (calc_cond)
4276 anorm = m_band.abs().sum().row(0).max();
4058 4277
4059 char job = 'L'; 4278 char job = 'L';
4060 F77_XFCN (zpbtrf, ZPBTRF, (F77_CONST_CHAR_ARG2 (&job, 1), 4279 F77_XFCN (zpbtrf, ZPBTRF, (F77_CONST_CHAR_ARG2 (&job, 1),
4061 nr, n_lower, tmp_data, ldm, err 4280 nr, n_lower, tmp_data, ldm, err
4062 F77_CHAR_ARG_LEN (1))); 4281 F77_CHAR_ARG_LEN (1)));
4064 if (f77_exception_encountered) 4283 if (f77_exception_encountered)
4065 (*current_liboctave_error_handler) 4284 (*current_liboctave_error_handler)
4066 ("unrecoverable error in zpbtrf"); 4285 ("unrecoverable error in zpbtrf");
4067 else 4286 else
4068 { 4287 {
4069 rcond = 0.0;
4070 if (err != 0) 4288 if (err != 0)
4071 { 4289 {
4290 rcond = 0.0;
4072 // Matrix is not positive definite!! Fall through to 4291 // Matrix is not positive definite!! Fall through to
4073 // unsymmetric banded solver. 4292 // unsymmetric banded solver.
4074 mattype.mark_as_unsymmetric (); 4293 mattype.mark_as_unsymmetric ();
4075 typ = SparseType::Banded; 4294 typ = SparseType::Banded;
4076 err = 0; 4295 err = 0;
4077 } 4296 }
4078 else 4297 else
4079 { 4298 {
4080 // Unfortunately, the time to calculate the condition 4299 if (calc_cond)
4081 // number is dominant for narrow banded matrices and 4300 {
4082 // so we rely on the "err" flag from xPBTRF to flag 4301 Array<Complex> z (2 * nr);
4083 // singularity. The commented code below is left here 4302 Complex *pz = z.fortran_vec ();
4084 // for reference 4303 Array<double> iz (nr);
4085 4304 double *piz = iz.fortran_vec ();
4086 //Array<double> z (3 * nr); 4305
4087 //Complex *pz = z.fortran_vec (); 4306 F77_XFCN (zpbcon, ZPBCON,
4088 //Array<octave_idx_type> iz (nr); 4307 (F77_CONST_CHAR_ARG2 (&job, 1),
4089 //octave_idx_type *piz = iz.fortran_vec (); 4308 nr, n_lower, tmp_data, ldm,
4090 // 4309 anorm, rcond, pz, piz, err
4091 //F77_XFCN (zpbcon, ZGBCON, 4310 F77_CHAR_ARG_LEN (1)));
4092 // (F77_CONST_CHAR_ARG2 (&job, 1), 4311
4093 // nr, n_lower, tmp_data, ldm, 4312 if (f77_exception_encountered)
4094 // anorm, rcond, pz, piz, err 4313 (*current_liboctave_error_handler)
4095 // F77_CHAR_ARG_LEN (1))); 4314 ("unrecoverable error in zpbcon");
4096 // 4315
4097 // 4316 if (err != 0)
4098 //if (f77_exception_encountered) 4317 err = -2;
4099 // (*current_liboctave_error_handler) 4318
4100 // ("unrecoverable error in zpbcon"); 4319 volatile double rcond_plus_one = rcond + 1.0;
4101 // 4320
4102 //if (err != 0) 4321 if (rcond_plus_one == 1.0 || xisnan (rcond))
4103 // err = -2; 4322 {
4104 // 4323 err = -2;
4105 //volatile double rcond_plus_one = rcond + 1.0; 4324
4106 // 4325 if (sing_handler)
4107 //if (rcond_plus_one == 1.0 || xisnan (rcond)) 4326 {
4108 // { 4327 sing_handler (rcond);
4109 // err = -2; 4328 mattype.mark_as_rectangular ();
4110 // 4329 }
4111 // if (sing_handler) 4330 else
4112 // sing_handler (rcond); 4331 (*current_liboctave_error_handler)
4113 // else 4332 ("matrix singular to machine precision, rcond = %g",
4114 // (*current_liboctave_error_handler) 4333 rcond);
4115 // ("matrix singular to machine precision, rcond = %g", 4334 }
4116 // rcond); 4335 }
4117 // } 4336 else
4118 //else 4337 rcond = 1.0;
4119 // REST OF CODE, EXCEPT rcond=1 4338
4120 4339 if (err == 0)
4121 rcond = 1.; 4340 {
4122 retval = ComplexMatrix (b); 4341 retval = ComplexMatrix (b);
4123 Complex *result = retval.fortran_vec (); 4342 Complex *result = retval.fortran_vec ();
4124 4343
4125 octave_idx_type b_nc = b.cols (); 4344 octave_idx_type b_nc = b.cols ();
4126 4345
4127 F77_XFCN (zpbtrs, ZPBTRS, 4346 F77_XFCN (zpbtrs, ZPBTRS,
4128 (F77_CONST_CHAR_ARG2 (&job, 1), 4347 (F77_CONST_CHAR_ARG2 (&job, 1),
4129 nr, n_lower, b_nc, tmp_data, 4348 nr, n_lower, b_nc, tmp_data,
4130 ldm, result, b.rows(), err 4349 ldm, result, b.rows(), err
4131 F77_CHAR_ARG_LEN (1))); 4350 F77_CHAR_ARG_LEN (1)));
4132 4351
4133 if (f77_exception_encountered) 4352 if (f77_exception_encountered)
4134 (*current_liboctave_error_handler) 4353 (*current_liboctave_error_handler)
4135 ("unrecoverable error in zpbtrs"); 4354 ("unrecoverable error in zpbtrs");
4136 4355
4137 if (err != 0) 4356 if (err != 0)
4138 { 4357 {
4139 (*current_liboctave_error_handler) 4358 (*current_liboctave_error_handler)
4140 ("SparseMatrix::solve solve failed"); 4359 ("SparseMatrix::solve solve failed");
4141 err = -1; 4360 err = -1;
4361 }
4142 } 4362 }
4143 } 4363 }
4144 } 4364 }
4145 } 4365 }
4146 4366
4164 } 4384 }
4165 4385
4166 for (octave_idx_type j = 0; j < nc; j++) 4386 for (octave_idx_type j = 0; j < nc; j++)
4167 for (octave_idx_type i = cidx(j); i < cidx(j+1); i++) 4387 for (octave_idx_type i = cidx(j); i < cidx(j+1); i++)
4168 m_band(ridx(i) - j + n_lower + n_upper, j) = data(i); 4388 m_band(ridx(i) - j + n_lower + n_upper, j) = data(i);
4389
4390 // Calculate the norm of the matrix, for later use.
4391 double anorm;
4392 if (calc_cond)
4393 {
4394 for (octave_idx_type j = 0; j < nr; j++)
4395 {
4396 double atmp = 0.;
4397 for (octave_idx_type i = cidx(j); i < cidx(j+1); i++)
4398 atmp += std::abs(data(i));
4399 if (atmp > anorm)
4400 anorm = atmp;
4401 }
4402 }
4169 4403
4170 Array<octave_idx_type> ipvt (nr); 4404 Array<octave_idx_type> ipvt (nr);
4171 octave_idx_type *pipvt = ipvt.fortran_vec (); 4405 octave_idx_type *pipvt = ipvt.fortran_vec ();
4172 4406
4173 F77_XFCN (zgbtrf, ZGBTRF, (nr, nc, n_lower, n_upper, tmp_data, 4407 F77_XFCN (zgbtrf, ZGBTRF, (nr, nc, n_lower, n_upper, tmp_data,
4178 ("unrecoverable error in zgbtrf"); 4412 ("unrecoverable error in zgbtrf");
4179 else 4413 else
4180 { 4414 {
4181 // Throw-away extra info LAPACK gives so as to not 4415 // Throw-away extra info LAPACK gives so as to not
4182 // change output. 4416 // change output.
4183 rcond = 0.0;
4184 if (err != 0) 4417 if (err != 0)
4185 { 4418 {
4419 rcond = 0.0;
4186 err = -2; 4420 err = -2;
4187 4421
4188 if (sing_handler) 4422 if (sing_handler)
4189 sing_handler (rcond); 4423 {
4424 sing_handler (rcond);
4425 mattype.mark_as_rectangular ();
4426 }
4190 else 4427 else
4191 (*current_liboctave_error_handler) 4428 (*current_liboctave_error_handler)
4192 ("matrix singular to machine precision"); 4429 ("matrix singular to machine precision");
4193
4194 } 4430 }
4195 else 4431 else
4196 { 4432 {
4197 char job = '1'; 4433 if (calc_cond)
4198 4434 {
4199 // Unfortunately, the time to calculate the condition 4435 char job = '1';
4200 // number is dominant for narrow banded matrices and 4436 Array<Complex> z (2 * nr);
4201 // so we rely on the "err" flag from xPBTRF to flag 4437 Complex *pz = z.fortran_vec ();
4202 // singularity. The commented code below is left here 4438 Array<double> iz (nr);
4203 // for reference 4439 double *piz = iz.fortran_vec ();
4204 4440
4205 //F77_XFCN (zgbcon, ZGBCON, 4441 F77_XFCN (zgbcon, ZGBCON,
4206 // (F77_CONST_CHAR_ARG2 (&job, 1), 4442 (F77_CONST_CHAR_ARG2 (&job, 1),
4207 // nc, n_lower, n_upper, tmp_data, ldm, pipvt, 4443 nc, n_lower, n_upper, tmp_data, ldm, pipvt,
4208 // anorm, rcond, pz, piz, err 4444 anorm, rcond, pz, piz, err
4209 // F77_CHAR_ARG_LEN (1))); 4445 F77_CHAR_ARG_LEN (1)));
4210 // 4446
4211 //if (f77_exception_encountered) 4447 if (f77_exception_encountered)
4212 // (*current_liboctave_error_handler) 4448 (*current_liboctave_error_handler)
4213 // ("unrecoverable error in zgbcon"); 4449 ("unrecoverable error in zgbcon");
4214 // 4450
4215 // if (err != 0) 4451 if (err != 0)
4216 // err = -2; 4452 err = -2;
4217 // 4453
4218 //volatile double rcond_plus_one = rcond + 1.0; 4454 volatile double rcond_plus_one = rcond + 1.0;
4219 // 4455
4220 //if (rcond_plus_one == 1.0 || xisnan (rcond)) 4456 if (rcond_plus_one == 1.0 || xisnan (rcond))
4221 // { 4457 {
4222 // err = -2; 4458 err = -2;
4223 // 4459
4224 // if (sing_handler) 4460 if (sing_handler)
4225 // sing_handler (rcond); 4461 {
4226 // else 4462 sing_handler (rcond);
4227 // (*current_liboctave_error_handler) 4463 mattype.mark_as_rectangular ();
4228 // ("matrix singular to machine precision, rcond = %g", 4464 }
4229 // rcond); 4465 else
4230 // } 4466 (*current_liboctave_error_handler)
4231 //else 4467 ("matrix singular to machine precision, rcond = %g",
4232 // REST OF CODE, EXCEPT rcond=1 4468 rcond);
4233 4469 }
4234 rcond = 1.; 4470 }
4235 retval = ComplexMatrix (b); 4471 else
4236 Complex *result = retval.fortran_vec (); 4472 rcond = 1.;
4237 4473
4238 octave_idx_type b_nc = b.cols (); 4474 if (err == 0)
4239 4475 {
4240 job = 'N'; 4476 retval = ComplexMatrix (b);
4241 F77_XFCN (zgbtrs, ZGBTRS, 4477 Complex *result = retval.fortran_vec ();
4242 (F77_CONST_CHAR_ARG2 (&job, 1), 4478
4243 nr, n_lower, n_upper, b_nc, tmp_data, 4479 octave_idx_type b_nc = b.cols ();
4244 ldm, pipvt, result, b.rows(), err 4480
4245 F77_CHAR_ARG_LEN (1))); 4481 char job = 'N';
4482 F77_XFCN (zgbtrs, ZGBTRS,
4483 (F77_CONST_CHAR_ARG2 (&job, 1),
4484 nr, n_lower, n_upper, b_nc, tmp_data,
4485 ldm, pipvt, result, b.rows(), err
4486 F77_CHAR_ARG_LEN (1)));
4246 4487
4247 if (f77_exception_encountered) 4488 if (f77_exception_encountered)
4248 (*current_liboctave_error_handler) 4489 (*current_liboctave_error_handler)
4249 ("unrecoverable error in zgbtrs"); 4490 ("unrecoverable error in zgbtrs");
4491 }
4250 } 4492 }
4251 } 4493 }
4252 } 4494 }
4253 else if (typ != SparseType::Banded_Hermitian) 4495 else if (typ != SparseType::Banded_Hermitian)
4254 (*current_liboctave_error_handler) ("incorrect matrix type"); 4496 (*current_liboctave_error_handler) ("incorrect matrix type");
4258 } 4500 }
4259 4501
4260 SparseComplexMatrix 4502 SparseComplexMatrix
4261 SparseComplexMatrix::bsolve (SparseType &mattype, const SparseMatrix& b, 4503 SparseComplexMatrix::bsolve (SparseType &mattype, const SparseMatrix& b,
4262 octave_idx_type& err, double& rcond, 4504 octave_idx_type& err, double& rcond,
4263 solve_singularity_handler sing_handler) const 4505 solve_singularity_handler sing_handler,
4506 bool calc_cond) const
4264 { 4507 {
4265 SparseComplexMatrix retval; 4508 SparseComplexMatrix retval;
4266 4509
4267 octave_idx_type nr = rows (); 4510 octave_idx_type nr = rows ();
4268 octave_idx_type nc = cols (); 4511 octave_idx_type nc = cols ();
4299 { 4542 {
4300 octave_idx_type ri = ridx (i); 4543 octave_idx_type ri = ridx (i);
4301 if (ri >= j) 4544 if (ri >= j)
4302 m_band(ri - j, j) = data(i); 4545 m_band(ri - j, j) = data(i);
4303 } 4546 }
4547
4548 // Calculate the norm of the matrix, for later use.
4549 double anorm;
4550 if (calc_cond)
4551 anorm = m_band.abs().sum().row(0).max();
4304 4552
4305 char job = 'L'; 4553 char job = 'L';
4306 F77_XFCN (zpbtrf, ZPBTRF, (F77_CONST_CHAR_ARG2 (&job, 1), 4554 F77_XFCN (zpbtrf, ZPBTRF, (F77_CONST_CHAR_ARG2 (&job, 1),
4307 nr, n_lower, tmp_data, ldm, err 4555 nr, n_lower, tmp_data, ldm, err
4308 F77_CHAR_ARG_LEN (1))); 4556 F77_CHAR_ARG_LEN (1)));
4310 if (f77_exception_encountered) 4558 if (f77_exception_encountered)
4311 (*current_liboctave_error_handler) 4559 (*current_liboctave_error_handler)
4312 ("unrecoverable error in zpbtrf"); 4560 ("unrecoverable error in zpbtrf");
4313 else 4561 else
4314 { 4562 {
4315 rcond = 0.0;
4316 if (err != 0) 4563 if (err != 0)
4317 { 4564 {
4565 rcond = 0.0;
4318 mattype.mark_as_unsymmetric (); 4566 mattype.mark_as_unsymmetric ();
4319 typ = SparseType::Banded; 4567 typ = SparseType::Banded;
4320 err = 0; 4568 err = 0;
4321 } 4569 }
4322 else 4570 else
4323 { 4571 {
4324 rcond = 1.; 4572 if (calc_cond)
4325 octave_idx_type b_nr = b.rows (); 4573 {
4326 octave_idx_type b_nc = b.cols (); 4574 Array<Complex> z (2 * nr);
4327 OCTAVE_LOCAL_BUFFER (Complex, Bx, b_nr); 4575 Complex *pz = z.fortran_vec ();
4328 4576 Array<double> iz (nr);
4329 // Take a first guess that the number of non-zero terms 4577 double *piz = iz.fortran_vec ();
4330 // will be as many as in b 4578
4331 volatile octave_idx_type x_nz = b.nzmax (); 4579 F77_XFCN (zpbcon, ZPBCON,
4332 volatile octave_idx_type ii = 0; 4580 (F77_CONST_CHAR_ARG2 (&job, 1),
4333 retval = SparseComplexMatrix (b_nr, b_nc, x_nz); 4581 nr, n_lower, tmp_data, ldm,
4334 4582 anorm, rcond, pz, piz, err
4335 retval.xcidx(0) = 0; 4583 F77_CHAR_ARG_LEN (1)));
4336 for (volatile octave_idx_type j = 0; j < b_nc; j++) 4584
4337 { 4585 if (f77_exception_encountered)
4338 for (octave_idx_type i = 0; i < b_nr; i++) 4586 (*current_liboctave_error_handler)
4339 Bx[i] = b.elem (i, j); 4587 ("unrecoverable error in zpbcon");
4340 4588
4341 F77_XFCN (zpbtrs, ZPBTRS, 4589 if (err != 0)
4342 (F77_CONST_CHAR_ARG2 (&job, 1), 4590 err = -2;
4343 nr, n_lower, 1, tmp_data, 4591
4344 ldm, Bx, b_nr, err 4592 volatile double rcond_plus_one = rcond + 1.0;
4345 F77_CHAR_ARG_LEN (1))); 4593
4594 if (rcond_plus_one == 1.0 || xisnan (rcond))
4595 {
4596 err = -2;
4597
4598 if (sing_handler)
4599 {
4600 sing_handler (rcond);
4601 mattype.mark_as_rectangular ();
4602 }
4603 else
4604 (*current_liboctave_error_handler)
4605 ("matrix singular to machine precision, rcond = %g",
4606 rcond);
4607 }
4608 }
4609 else
4610 rcond = 1.0;
4611
4612 if (err == 0)
4613 {
4614 octave_idx_type b_nr = b.rows ();
4615 octave_idx_type b_nc = b.cols ();
4616 OCTAVE_LOCAL_BUFFER (Complex, Bx, b_nr);
4617
4618 // Take a first guess that the number of non-zero terms
4619 // will be as many as in b
4620 volatile octave_idx_type x_nz = b.nnz ();
4621 volatile octave_idx_type ii = 0;
4622 retval = SparseComplexMatrix (b_nr, b_nc, x_nz);
4623
4624 retval.xcidx(0) = 0;
4625 for (volatile octave_idx_type j = 0; j < b_nc; j++)
4626 {
4627 for (octave_idx_type i = 0; i < b_nr; i++)
4628 Bx[i] = b.elem (i, j);
4629
4630 F77_XFCN (zpbtrs, ZPBTRS,
4631 (F77_CONST_CHAR_ARG2 (&job, 1),
4632 nr, n_lower, 1, tmp_data,
4633 ldm, Bx, b_nr, err
4634 F77_CHAR_ARG_LEN (1)));
4346 4635
4347 if (f77_exception_encountered) 4636 if (f77_exception_encountered)
4348 { 4637 {
4349 (*current_liboctave_error_handler) 4638 (*current_liboctave_error_handler)
4350 ("unrecoverable error in dpbtrs"); 4639 ("unrecoverable error in dpbtrs");
4351 err = -1; 4640 err = -1;
4352 break; 4641 break;
4642 }
4643
4644 if (err != 0)
4645 {
4646 (*current_liboctave_error_handler)
4647 ("SparseComplexMatrix::solve solve failed");
4648 err = -1;
4649 break;
4650 }
4651
4652 for (octave_idx_type i = 0; i < b_nr; i++)
4653 {
4654 Complex tmp = Bx[i];
4655 if (tmp != 0.0)
4656 {
4657 if (ii == x_nz)
4658 {
4659 // Resize the sparse matrix
4660 octave_idx_type sz = x_nz *
4661 (b_nc - j) / b_nc;
4662 sz = (sz > 10 ? sz : 10) + x_nz;
4663 retval.change_capacity (sz);
4664 x_nz = sz;
4665 }
4666 retval.xdata(ii) = tmp;
4667 retval.xridx(ii++) = i;
4668 }
4669 }
4670 retval.xcidx(j+1) = ii;
4353 } 4671 }
4354 4672
4355 if (err != 0) 4673 retval.maybe_compress ();
4356 { 4674 }
4357 (*current_liboctave_error_handler)
4358 ("SparseComplexMatrix::solve solve failed");
4359 err = -1;
4360 break;
4361 }
4362
4363 for (octave_idx_type i = 0; i < b_nr; i++)
4364 {
4365 Complex tmp = Bx[i];
4366 if (tmp != 0.0)
4367 {
4368 if (ii == x_nz)
4369 {
4370 // Resize the sparse matrix
4371 octave_idx_type sz = x_nz * (b_nc - j) / b_nc;
4372 sz = (sz > 10 ? sz : 10) + x_nz;
4373 retval.change_capacity (sz);
4374 x_nz = sz;
4375 }
4376 retval.xdata(ii) = tmp;
4377 retval.xridx(ii++) = i;
4378 }
4379 }
4380 retval.xcidx(j+1) = ii;
4381 }
4382
4383 retval.maybe_compress ();
4384 } 4675 }
4385 } 4676 }
4386 } 4677 }
4387 4678
4388 if (typ == SparseType::Banded) 4679 if (typ == SparseType::Banded)
4405 } 4696 }
4406 4697
4407 for (octave_idx_type j = 0; j < nc; j++) 4698 for (octave_idx_type j = 0; j < nc; j++)
4408 for (octave_idx_type i = cidx(j); i < cidx(j+1); i++) 4699 for (octave_idx_type i = cidx(j); i < cidx(j+1); i++)
4409 m_band(ridx(i) - j + n_lower + n_upper, j) = data(i); 4700 m_band(ridx(i) - j + n_lower + n_upper, j) = data(i);
4701
4702 // Calculate the norm of the matrix, for later use.
4703 double anorm;
4704 if (calc_cond)
4705 {
4706 for (octave_idx_type j = 0; j < nr; j++)
4707 {
4708 double atmp = 0.;
4709 for (octave_idx_type i = cidx(j); i < cidx(j+1); i++)
4710 atmp += std::abs(data(i));
4711 if (atmp > anorm)
4712 anorm = atmp;
4713 }
4714 }
4410 4715
4411 Array<octave_idx_type> ipvt (nr); 4716 Array<octave_idx_type> ipvt (nr);
4412 octave_idx_type *pipvt = ipvt.fortran_vec (); 4717 octave_idx_type *pipvt = ipvt.fortran_vec ();
4413 4718
4414 F77_XFCN (zgbtrf, ZGBTRF, (nr, nr, n_lower, n_upper, tmp_data, 4719 F77_XFCN (zgbtrf, ZGBTRF, (nr, nr, n_lower, n_upper, tmp_data,
4417 if (f77_exception_encountered) 4722 if (f77_exception_encountered)
4418 (*current_liboctave_error_handler) 4723 (*current_liboctave_error_handler)
4419 ("unrecoverable error in zgbtrf"); 4724 ("unrecoverable error in zgbtrf");
4420 else 4725 else
4421 { 4726 {
4422 rcond = 0.0;
4423 if (err != 0) 4727 if (err != 0)
4424 { 4728 {
4729 rcond = 0.0;
4425 err = -2; 4730 err = -2;
4426 4731
4427 if (sing_handler) 4732 if (sing_handler)
4733 {
4428 sing_handler (rcond); 4734 sing_handler (rcond);
4735 mattype.mark_as_rectangular ();
4736 }
4429 else 4737 else
4430 (*current_liboctave_error_handler) 4738 (*current_liboctave_error_handler)
4431 ("matrix singular to machine precision"); 4739 ("matrix singular to machine precision");
4432 4740
4433 } 4741 }
4434 else 4742 else
4435 { 4743 {
4436 char job = 'N'; 4744 if (calc_cond)
4437 volatile octave_idx_type x_nz = b.nzmax (); 4745 {
4438 octave_idx_type b_nc = b.cols (); 4746 char job = '1';
4439 retval = SparseComplexMatrix (nr, b_nc, x_nz); 4747 Array<Complex> z (2 * nr);
4440 retval.xcidx(0) = 0; 4748 Complex *pz = z.fortran_vec ();
4441 volatile octave_idx_type ii = 0; 4749 Array<double> iz (nr);
4442 4750 double *piz = iz.fortran_vec ();
4443 OCTAVE_LOCAL_BUFFER (Complex, work, nr); 4751
4444 4752 F77_XFCN (zgbcon, ZGBCON,
4445 for (volatile octave_idx_type j = 0; j < b_nc; j++) 4753 (F77_CONST_CHAR_ARG2 (&job, 1),
4446 { 4754 nc, n_lower, n_upper, tmp_data, ldm, pipvt,
4447 for (octave_idx_type i = 0; i < nr; i++) 4755 anorm, rcond, pz, piz, err
4448 work[i] = 0.; 4756 F77_CHAR_ARG_LEN (1)));
4449 for (octave_idx_type i = b.cidx(j); i < b.cidx(j+1); i++) 4757
4450 work[b.ridx(i)] = b.data(i); 4758 if (f77_exception_encountered)
4451 4759 (*current_liboctave_error_handler)
4452 F77_XFCN (zgbtrs, ZGBTRS, 4760 ("unrecoverable error in zgbcon");
4453 (F77_CONST_CHAR_ARG2 (&job, 1), 4761
4454 nr, n_lower, n_upper, 1, tmp_data, 4762 if (err != 0)
4455 ldm, pipvt, work, b.rows (), err 4763 err = -2;
4456 F77_CHAR_ARG_LEN (1))); 4764
4765 volatile double rcond_plus_one = rcond + 1.0;
4766
4767 if (rcond_plus_one == 1.0 || xisnan (rcond))
4768 {
4769 err = -2;
4770
4771 if (sing_handler)
4772 {
4773 sing_handler (rcond);
4774 mattype.mark_as_rectangular ();
4775 }
4776 else
4777 (*current_liboctave_error_handler)
4778 ("matrix singular to machine precision, rcond = %g",
4779 rcond);
4780 }
4781 }
4782 else
4783 rcond = 1.;
4784
4785 if (err == 0)
4786 {
4787 char job = 'N';
4788 volatile octave_idx_type x_nz = b.nnz ();
4789 octave_idx_type b_nc = b.cols ();
4790 retval = SparseComplexMatrix (nr, b_nc, x_nz);
4791 retval.xcidx(0) = 0;
4792 volatile octave_idx_type ii = 0;
4793
4794 OCTAVE_LOCAL_BUFFER (Complex, work, nr);
4795
4796 for (volatile octave_idx_type j = 0; j < b_nc; j++)
4797 {
4798 for (octave_idx_type i = 0; i < nr; i++)
4799 work[i] = 0.;
4800 for (octave_idx_type i = b.cidx(j);
4801 i < b.cidx(j+1); i++)
4802 work[b.ridx(i)] = b.data(i);
4803
4804 F77_XFCN (zgbtrs, ZGBTRS,
4805 (F77_CONST_CHAR_ARG2 (&job, 1),
4806 nr, n_lower, n_upper, 1, tmp_data,
4807 ldm, pipvt, work, b.rows (), err
4808 F77_CHAR_ARG_LEN (1)));
4457 4809
4458 if (f77_exception_encountered) 4810 if (f77_exception_encountered)
4459 { 4811 {
4460 (*current_liboctave_error_handler) 4812 (*current_liboctave_error_handler)
4461 ("unrecoverable error in zgbtrs"); 4813 ("unrecoverable error in zgbtrs");
4462 break; 4814 break;
4815 }
4816
4817 // Count non-zeros in work vector and adjust
4818 // space in retval if needed
4819 octave_idx_type new_nnz = 0;
4820 for (octave_idx_type i = 0; i < nr; i++)
4821 if (work[i] != 0.)
4822 new_nnz++;
4823
4824 if (ii + new_nnz > x_nz)
4825 {
4826 // Resize the sparse matrix
4827 octave_idx_type sz = new_nnz * (b_nc - j) + x_nz;
4828 retval.change_capacity (sz);
4829 x_nz = sz;
4830 }
4831
4832 for (octave_idx_type i = 0; i < nr; i++)
4833 if (work[i] != 0.)
4834 {
4835 retval.xridx(ii) = i;
4836 retval.xdata(ii++) = work[i];
4837 }
4838 retval.xcidx(j+1) = ii;
4463 } 4839 }
4464 4840
4465 // Count non-zeros in work vector and adjust 4841 retval.maybe_compress ();
4466 // space in retval if needed 4842 }
4467 octave_idx_type new_nnz = 0;
4468 for (octave_idx_type i = 0; i < nr; i++)
4469 if (work[i] != 0.)
4470 new_nnz++;
4471
4472 if (ii + new_nnz > x_nz)
4473 {
4474 // Resize the sparse matrix
4475 octave_idx_type sz = new_nnz * (b_nc - j) + x_nz;
4476 retval.change_capacity (sz);
4477 x_nz = sz;
4478 }
4479
4480 for (octave_idx_type i = 0; i < nr; i++)
4481 if (work[i] != 0.)
4482 {
4483 retval.xridx(ii) = i;
4484 retval.xdata(ii++) = work[i];
4485 }
4486 retval.xcidx(j+1) = ii;
4487 }
4488
4489 retval.maybe_compress ();
4490 } 4843 }
4491 } 4844 }
4492 } 4845 }
4493 else if (typ != SparseType::Banded_Hermitian) 4846 else if (typ != SparseType::Banded_Hermitian)
4494 (*current_liboctave_error_handler) ("incorrect matrix type"); 4847 (*current_liboctave_error_handler) ("incorrect matrix type");
4498 } 4851 }
4499 4852
4500 ComplexMatrix 4853 ComplexMatrix
4501 SparseComplexMatrix::bsolve (SparseType &mattype, const ComplexMatrix& b, 4854 SparseComplexMatrix::bsolve (SparseType &mattype, const ComplexMatrix& b,
4502 octave_idx_type& err, double& rcond, 4855 octave_idx_type& err, double& rcond,
4503 solve_singularity_handler sing_handler) const 4856 solve_singularity_handler sing_handler,
4857 bool calc_cond) const
4504 { 4858 {
4505 ComplexMatrix retval; 4859 ComplexMatrix retval;
4506 4860
4507 octave_idx_type nr = rows (); 4861 octave_idx_type nr = rows ();
4508 octave_idx_type nc = cols (); 4862 octave_idx_type nc = cols ();
4539 { 4893 {
4540 octave_idx_type ri = ridx (i); 4894 octave_idx_type ri = ridx (i);
4541 if (ri >= j) 4895 if (ri >= j)
4542 m_band(ri - j, j) = data(i); 4896 m_band(ri - j, j) = data(i);
4543 } 4897 }
4898
4899 // Calculate the norm of the matrix, for later use.
4900 double anorm;
4901 if (calc_cond)
4902 anorm = m_band.abs().sum().row(0).max();
4544 4903
4545 char job = 'L'; 4904 char job = 'L';
4546 F77_XFCN (zpbtrf, ZPBTRF, (F77_CONST_CHAR_ARG2 (&job, 1), 4905 F77_XFCN (zpbtrf, ZPBTRF, (F77_CONST_CHAR_ARG2 (&job, 1),
4547 nr, n_lower, tmp_data, ldm, err 4906 nr, n_lower, tmp_data, ldm, err
4548 F77_CHAR_ARG_LEN (1))); 4907 F77_CHAR_ARG_LEN (1)));
4550 if (f77_exception_encountered) 4909 if (f77_exception_encountered)
4551 (*current_liboctave_error_handler) 4910 (*current_liboctave_error_handler)
4552 ("unrecoverable error in zpbtrf"); 4911 ("unrecoverable error in zpbtrf");
4553 else 4912 else
4554 { 4913 {
4555 rcond = 0.0;
4556 if (err != 0) 4914 if (err != 0)
4557 { 4915 {
4558 // Matrix is not positive definite!! Fall through to 4916 // Matrix is not positive definite!! Fall through to
4559 // unsymmetric banded solver. 4917 // unsymmetric banded solver.
4918 rcond = 0.0;
4560 mattype.mark_as_unsymmetric (); 4919 mattype.mark_as_unsymmetric ();
4561 typ = SparseType::Banded; 4920 typ = SparseType::Banded;
4562 err = 0; 4921 err = 0;
4563 } 4922 }
4564 else 4923 else
4565 { 4924 {
4566 rcond = 1.; 4925 if (calc_cond)
4567 octave_idx_type b_nr = b.rows (); 4926 {
4568 octave_idx_type b_nc = b.cols (); 4927 Array<Complex> z (2 * nr);
4569 retval = ComplexMatrix (b); 4928 Complex *pz = z.fortran_vec ();
4570 Complex *result = retval.fortran_vec (); 4929 Array<double> iz (nr);
4571 4930 double *piz = iz.fortran_vec ();
4572 F77_XFCN (zpbtrs, ZPBTRS, 4931
4573 (F77_CONST_CHAR_ARG2 (&job, 1), 4932 F77_XFCN (zpbcon, ZPBCON,
4574 nr, n_lower, b_nc, tmp_data, 4933 (F77_CONST_CHAR_ARG2 (&job, 1),
4575 ldm, result, b_nr, err 4934 nr, n_lower, tmp_data, ldm,
4576 F77_CHAR_ARG_LEN (1))); 4935 anorm, rcond, pz, piz, err
4936 F77_CHAR_ARG_LEN (1)));
4937
4938 if (f77_exception_encountered)
4939 (*current_liboctave_error_handler)
4940 ("unrecoverable error in zpbcon");
4941
4942 if (err != 0)
4943 err = -2;
4944
4945 volatile double rcond_plus_one = rcond + 1.0;
4946
4947 if (rcond_plus_one == 1.0 || xisnan (rcond))
4948 {
4949 err = -2;
4950
4951 if (sing_handler)
4952 {
4953 sing_handler (rcond);
4954 mattype.mark_as_rectangular ();
4955 }
4956 else
4957 (*current_liboctave_error_handler)
4958 ("matrix singular to machine precision, rcond = %g",
4959 rcond);
4960 }
4961 }
4962 else
4963 rcond = 1.0;
4964
4965 if (err == 0)
4966 {
4967 octave_idx_type b_nr = b.rows ();
4968 octave_idx_type b_nc = b.cols ();
4969 retval = ComplexMatrix (b);
4970 Complex *result = retval.fortran_vec ();
4971
4972 F77_XFCN (zpbtrs, ZPBTRS,
4973 (F77_CONST_CHAR_ARG2 (&job, 1),
4974 nr, n_lower, b_nc, tmp_data,
4975 ldm, result, b_nr, err
4976 F77_CHAR_ARG_LEN (1)));
4577 4977
4578 if (f77_exception_encountered) 4978 if (f77_exception_encountered)
4579 { 4979 {
4580 (*current_liboctave_error_handler) 4980 (*current_liboctave_error_handler)
4581 ("unrecoverable error in zpbtrs"); 4981 ("unrecoverable error in zpbtrs");
4582 err = -1; 4982 err = -1;
4583 } 4983 }
4584 4984
4585 if (err != 0) 4985 if (err != 0)
4586 { 4986 {
4587 (*current_liboctave_error_handler) 4987 (*current_liboctave_error_handler)
4588 ("SparseComplexMatrix::solve solve failed"); 4988 ("SparseComplexMatrix::solve solve failed");
4589 err = -1; 4989 err = -1;
4990 }
4590 } 4991 }
4591 } 4992 }
4592 } 4993 }
4593 } 4994 }
4594 4995
4612 } 5013 }
4613 5014
4614 for (octave_idx_type j = 0; j < nc; j++) 5015 for (octave_idx_type j = 0; j < nc; j++)
4615 for (octave_idx_type i = cidx(j); i < cidx(j+1); i++) 5016 for (octave_idx_type i = cidx(j); i < cidx(j+1); i++)
4616 m_band(ridx(i) - j + n_lower + n_upper, j) = data(i); 5017 m_band(ridx(i) - j + n_lower + n_upper, j) = data(i);
5018
5019 // Calculate the norm of the matrix, for later use.
5020 double anorm;
5021 if (calc_cond)
5022 {
5023 for (octave_idx_type j = 0; j < nr; j++)
5024 {
5025 double atmp = 0.;
5026 for (octave_idx_type i = cidx(j); i < cidx(j+1); i++)
5027 atmp += std::abs(data(i));
5028 if (atmp > anorm)
5029 anorm = atmp;
5030 }
5031 }
4617 5032
4618 Array<octave_idx_type> ipvt (nr); 5033 Array<octave_idx_type> ipvt (nr);
4619 octave_idx_type *pipvt = ipvt.fortran_vec (); 5034 octave_idx_type *pipvt = ipvt.fortran_vec ();
4620 5035
4621 F77_XFCN (zgbtrf, ZGBTRF, (nr, nr, n_lower, n_upper, tmp_data, 5036 F77_XFCN (zgbtrf, ZGBTRF, (nr, nr, n_lower, n_upper, tmp_data,
4624 if (f77_exception_encountered) 5039 if (f77_exception_encountered)
4625 (*current_liboctave_error_handler) 5040 (*current_liboctave_error_handler)
4626 ("unrecoverable error in zgbtrf"); 5041 ("unrecoverable error in zgbtrf");
4627 else 5042 else
4628 { 5043 {
4629 rcond = 0.0;
4630 if (err != 0) 5044 if (err != 0)
4631 { 5045 {
4632 err = -2; 5046 err = -2;
5047 rcond = 0.0;
4633 5048
4634 if (sing_handler) 5049 if (sing_handler)
4635 sing_handler (rcond); 5050 {
5051 sing_handler (rcond);
5052 mattype.mark_as_rectangular ();
5053 }
4636 else 5054 else
4637 (*current_liboctave_error_handler) 5055 (*current_liboctave_error_handler)
4638 ("matrix singular to machine precision"); 5056 ("matrix singular to machine precision");
4639
4640 } 5057 }
4641 else 5058 else
4642 { 5059 {
4643 char job = 'N'; 5060 if (calc_cond)
4644 octave_idx_type b_nc = b.cols (); 5061 {
4645 retval = ComplexMatrix (b); 5062 char job = '1';
4646 Complex *result = retval.fortran_vec (); 5063 Array<Complex> z (2 * nr);
4647 5064 Complex *pz = z.fortran_vec ();
4648 F77_XFCN (zgbtrs, ZGBTRS, 5065 Array<double> iz (nr);
4649 (F77_CONST_CHAR_ARG2 (&job, 1), 5066 double *piz = iz.fortran_vec ();
4650 nr, n_lower, n_upper, b_nc, tmp_data, 5067
4651 ldm, pipvt, result, b.rows (), err 5068 F77_XFCN (zgbcon, ZGBCON,
4652 F77_CHAR_ARG_LEN (1))); 5069 (F77_CONST_CHAR_ARG2 (&job, 1),
5070 nc, n_lower, n_upper, tmp_data, ldm, pipvt,
5071 anorm, rcond, pz, piz, err
5072 F77_CHAR_ARG_LEN (1)));
5073
5074 if (f77_exception_encountered)
5075 (*current_liboctave_error_handler)
5076 ("unrecoverable error in zgbcon");
5077
5078 if (err != 0)
5079 err = -2;
5080
5081 volatile double rcond_plus_one = rcond + 1.0;
5082
5083 if (rcond_plus_one == 1.0 || xisnan (rcond))
5084 {
5085 err = -2;
5086
5087 if (sing_handler)
5088 {
5089 sing_handler (rcond);
5090 mattype.mark_as_rectangular ();
5091 }
5092 else
5093 (*current_liboctave_error_handler)
5094 ("matrix singular to machine precision, rcond = %g",
5095 rcond);
5096 }
5097 }
5098 else
5099 rcond = 1.;
5100
5101 if (err == 0)
5102 {
5103 char job = 'N';
5104 octave_idx_type b_nc = b.cols ();
5105 retval = ComplexMatrix (b);
5106 Complex *result = retval.fortran_vec ();
5107
5108 F77_XFCN (zgbtrs, ZGBTRS,
5109 (F77_CONST_CHAR_ARG2 (&job, 1),
5110 nr, n_lower, n_upper, b_nc, tmp_data,
5111 ldm, pipvt, result, b.rows (), err
5112 F77_CHAR_ARG_LEN (1)));
4653 5113
4654 if (f77_exception_encountered) 5114 if (f77_exception_encountered)
4655 { 5115 {
4656 (*current_liboctave_error_handler) 5116 (*current_liboctave_error_handler)
4657 ("unrecoverable error in dgbtrs"); 5117 ("unrecoverable error in dgbtrs");
5118 }
4658 } 5119 }
4659 } 5120 }
4660 } 5121 }
4661 } 5122 }
4662 else if (typ != SparseType::Banded_Hermitian) 5123 else if (typ != SparseType::Banded_Hermitian)
4666 return retval; 5127 return retval;
4667 } 5128 }
4668 5129
4669 SparseComplexMatrix 5130 SparseComplexMatrix
4670 SparseComplexMatrix::bsolve (SparseType &mattype, const SparseComplexMatrix& b, 5131 SparseComplexMatrix::bsolve (SparseType &mattype, const SparseComplexMatrix& b,
4671 octave_idx_type& err, double& rcond, 5132 octave_idx_type& err, double& rcond,
4672 solve_singularity_handler sing_handler) const 5133 solve_singularity_handler sing_handler,
5134 bool calc_cond) const
4673 { 5135 {
4674 SparseComplexMatrix retval; 5136 SparseComplexMatrix retval;
4675 5137
4676 octave_idx_type nr = rows (); 5138 octave_idx_type nr = rows ();
4677 octave_idx_type nc = cols (); 5139 octave_idx_type nc = cols ();
4708 { 5170 {
4709 octave_idx_type ri = ridx (i); 5171 octave_idx_type ri = ridx (i);
4710 if (ri >= j) 5172 if (ri >= j)
4711 m_band(ri - j, j) = data(i); 5173 m_band(ri - j, j) = data(i);
4712 } 5174 }
5175
5176 // Calculate the norm of the matrix, for later use.
5177 double anorm;
5178 if (calc_cond)
5179 anorm = m_band.abs().sum().row(0).max();
4713 5180
4714 char job = 'L'; 5181 char job = 'L';
4715 F77_XFCN (zpbtrf, ZPBTRF, (F77_CONST_CHAR_ARG2 (&job, 1), 5182 F77_XFCN (zpbtrf, ZPBTRF, (F77_CONST_CHAR_ARG2 (&job, 1),
4716 nr, n_lower, tmp_data, ldm, err 5183 nr, n_lower, tmp_data, ldm, err
4717 F77_CHAR_ARG_LEN (1))); 5184 F77_CHAR_ARG_LEN (1)));
4719 if (f77_exception_encountered) 5186 if (f77_exception_encountered)
4720 (*current_liboctave_error_handler) 5187 (*current_liboctave_error_handler)
4721 ("unrecoverable error in zpbtrf"); 5188 ("unrecoverable error in zpbtrf");
4722 else 5189 else
4723 { 5190 {
4724 rcond = 0.0;
4725 if (err != 0) 5191 if (err != 0)
4726 { 5192 {
4727 // Matrix is not positive definite!! Fall through to 5193 // Matrix is not positive definite!! Fall through to
4728 // unsymmetric banded solver. 5194 // unsymmetric banded solver.
4729 mattype.mark_as_unsymmetric (); 5195 mattype.mark_as_unsymmetric ();
4730 typ = SparseType::Banded; 5196 typ = SparseType::Banded;
4731 5197
5198 rcond = 0.0;
4732 err = 0; 5199 err = 0;
4733 } 5200 }
4734 else 5201 else
4735 { 5202 {
4736 rcond = 1.; 5203 if (calc_cond)
4737 octave_idx_type b_nr = b.rows (); 5204 {
4738 octave_idx_type b_nc = b.cols (); 5205 Array<Complex> z (2 * nr);
4739 OCTAVE_LOCAL_BUFFER (Complex, Bx, b_nr); 5206 Complex *pz = z.fortran_vec ();
4740 5207 Array<double> iz (nr);
4741 // Take a first guess that the number of non-zero terms 5208 double *piz = iz.fortran_vec ();
4742 // will be as many as in b 5209
4743 volatile octave_idx_type x_nz = b.nzmax (); 5210 F77_XFCN (zpbcon, ZPBCON,
4744 volatile octave_idx_type ii = 0; 5211 (F77_CONST_CHAR_ARG2 (&job, 1),
4745 retval = SparseComplexMatrix (b_nr, b_nc, x_nz); 5212 nr, n_lower, tmp_data, ldm,
4746 5213 anorm, rcond, pz, piz, err
4747 retval.xcidx(0) = 0; 5214 F77_CHAR_ARG_LEN (1)));
4748 for (volatile octave_idx_type j = 0; j < b_nc; j++) 5215
4749 { 5216 if (f77_exception_encountered)
4750 5217 (*current_liboctave_error_handler)
4751 for (octave_idx_type i = 0; i < b_nr; i++) 5218 ("unrecoverable error in zpbcon");
4752 Bx[i] = b (i,j); 5219
4753 5220 if (err != 0)
4754 F77_XFCN (zpbtrs, ZPBTRS, 5221 err = -2;
4755 (F77_CONST_CHAR_ARG2 (&job, 1), 5222
4756 nr, n_lower, 1, tmp_data, 5223 volatile double rcond_plus_one = rcond + 1.0;
4757 ldm, Bx, b_nr, err 5224
4758 F77_CHAR_ARG_LEN (1))); 5225 if (rcond_plus_one == 1.0 || xisnan (rcond))
5226 {
5227 err = -2;
5228
5229 if (sing_handler)
5230 {
5231 sing_handler (rcond);
5232 mattype.mark_as_rectangular ();
5233 }
5234 else
5235 (*current_liboctave_error_handler)
5236 ("matrix singular to machine precision, rcond = %g",
5237 rcond);
5238 }
5239 }
5240 else
5241 rcond = 1.0;
5242
5243 if (err == 0)
5244 {
5245 octave_idx_type b_nr = b.rows ();
5246 octave_idx_type b_nc = b.cols ();
5247 OCTAVE_LOCAL_BUFFER (Complex, Bx, b_nr);
5248
5249 // Take a first guess that the number of non-zero terms
5250 // will be as many as in b
5251 volatile octave_idx_type x_nz = b.nnz ();
5252 volatile octave_idx_type ii = 0;
5253 retval = SparseComplexMatrix (b_nr, b_nc, x_nz);
5254
5255 retval.xcidx(0) = 0;
5256 for (volatile octave_idx_type j = 0; j < b_nc; j++)
5257 {
5258
5259 for (octave_idx_type i = 0; i < b_nr; i++)
5260 Bx[i] = b (i,j);
5261
5262 F77_XFCN (zpbtrs, ZPBTRS,
5263 (F77_CONST_CHAR_ARG2 (&job, 1),
5264 nr, n_lower, 1, tmp_data,
5265 ldm, Bx, b_nr, err
5266 F77_CHAR_ARG_LEN (1)));
4759 5267
4760 if (f77_exception_encountered) 5268 if (f77_exception_encountered)
4761 { 5269 {
4762 (*current_liboctave_error_handler) 5270 (*current_liboctave_error_handler)
4763 ("unrecoverable error in zpbtrs"); 5271 ("unrecoverable error in zpbtrs");
4764 err = -1; 5272 err = -1;
4765 break; 5273 break;
5274 }
5275
5276 if (err != 0)
5277 {
5278 (*current_liboctave_error_handler)
5279 ("SparseMatrix::solve solve failed");
5280 err = -1;
5281 break;
5282 }
5283
5284 // Count non-zeros in work vector and adjust
5285 // space in retval if needed
5286 octave_idx_type new_nnz = 0;
5287 for (octave_idx_type i = 0; i < nr; i++)
5288 if (Bx[i] != 0.)
5289 new_nnz++;
5290
5291 if (ii + new_nnz > x_nz)
5292 {
5293 // Resize the sparse matrix
5294 octave_idx_type sz = new_nnz * (b_nc - j) + x_nz;
5295 retval.change_capacity (sz);
5296 x_nz = sz;
5297 }
5298
5299 for (octave_idx_type i = 0; i < nr; i++)
5300 if (Bx[i] != 0.)
5301 {
5302 retval.xridx(ii) = i;
5303 retval.xdata(ii++) = Bx[i];
5304 }
5305
5306 retval.xcidx(j+1) = ii;
4766 } 5307 }
4767 5308
4768 if (err != 0) 5309 retval.maybe_compress ();
4769 { 5310 }
4770 (*current_liboctave_error_handler)
4771 ("SparseMatrix::solve solve failed");
4772 err = -1;
4773 break;
4774 }
4775
4776
4777 // Count non-zeros in work vector and adjust
4778 // space in retval if needed
4779 octave_idx_type new_nnz = 0;
4780 for (octave_idx_type i = 0; i < nr; i++)
4781 if (Bx[i] != 0.)
4782 new_nnz++;
4783
4784 if (ii + new_nnz > x_nz)
4785 {
4786 // Resize the sparse matrix
4787 octave_idx_type sz = new_nnz * (b_nc - j) + x_nz;
4788 retval.change_capacity (sz);
4789 x_nz = sz;
4790 }
4791
4792 for (octave_idx_type i = 0; i < nr; i++)
4793 if (Bx[i] != 0.)
4794 {
4795 retval.xridx(ii) = i;
4796 retval.xdata(ii++) = Bx[i];
4797 }
4798
4799 retval.xcidx(j+1) = ii;
4800 }
4801
4802 retval.maybe_compress ();
4803 } 5311 }
4804 } 5312 }
4805 } 5313 }
4806 5314
4807 if (typ == SparseType::Banded) 5315 if (typ == SparseType::Banded)
4824 } 5332 }
4825 5333
4826 for (octave_idx_type j = 0; j < nc; j++) 5334 for (octave_idx_type j = 0; j < nc; j++)
4827 for (octave_idx_type i = cidx(j); i < cidx(j+1); i++) 5335 for (octave_idx_type i = cidx(j); i < cidx(j+1); i++)
4828 m_band(ridx(i) - j + n_lower + n_upper, j) = data(i); 5336 m_band(ridx(i) - j + n_lower + n_upper, j) = data(i);
5337
5338 // Calculate the norm of the matrix, for later use.
5339 double anorm;
5340 if (calc_cond)
5341 {
5342 for (octave_idx_type j = 0; j < nr; j++)
5343 {
5344 double atmp = 0.;
5345 for (octave_idx_type i = cidx(j); i < cidx(j+1); i++)
5346 atmp += std::abs(data(i));
5347 if (atmp > anorm)
5348 anorm = atmp;
5349 }
5350 }
4829 5351
4830 Array<octave_idx_type> ipvt (nr); 5352 Array<octave_idx_type> ipvt (nr);
4831 octave_idx_type *pipvt = ipvt.fortran_vec (); 5353 octave_idx_type *pipvt = ipvt.fortran_vec ();
4832 5354
4833 F77_XFCN (zgbtrf, ZGBTRF, (nr, nr, n_lower, n_upper, tmp_data, 5355 F77_XFCN (zgbtrf, ZGBTRF, (nr, nr, n_lower, n_upper, tmp_data,
4836 if (f77_exception_encountered) 5358 if (f77_exception_encountered)
4837 (*current_liboctave_error_handler) 5359 (*current_liboctave_error_handler)
4838 ("unrecoverable error in xgbtrf"); 5360 ("unrecoverable error in xgbtrf");
4839 else 5361 else
4840 { 5362 {
4841 rcond = 0.0;
4842 if (err != 0) 5363 if (err != 0)
4843 { 5364 {
4844 err = -2; 5365 err = -2;
5366 rcond = 0.0;
4845 5367
4846 if (sing_handler) 5368 if (sing_handler)
4847 sing_handler (rcond); 5369 {
5370 sing_handler (rcond);
5371 mattype.mark_as_rectangular ();
5372 }
4848 else 5373 else
4849 (*current_liboctave_error_handler) 5374 (*current_liboctave_error_handler)
4850 ("matrix singular to machine precision"); 5375 ("matrix singular to machine precision");
4851 5376
4852 } 5377 }
4853 else 5378 else
4854 { 5379 {
4855 char job = 'N'; 5380 if (calc_cond)
4856 volatile octave_idx_type x_nz = b.nzmax (); 5381 {
4857 octave_idx_type b_nc = b.cols (); 5382 char job = '1';
4858 retval = SparseComplexMatrix (nr, b_nc, x_nz); 5383 Array<Complex> z (2 * nr);
4859 retval.xcidx(0) = 0; 5384 Complex *pz = z.fortran_vec ();
4860 volatile octave_idx_type ii = 0; 5385 Array<double> iz (nr);
4861 5386 double *piz = iz.fortran_vec ();
4862 OCTAVE_LOCAL_BUFFER (Complex, Bx, nr); 5387
4863 5388 F77_XFCN (zgbcon, ZGBCON,
4864 for (volatile octave_idx_type j = 0; j < b_nc; j++) 5389 (F77_CONST_CHAR_ARG2 (&job, 1),
4865 { 5390 nc, n_lower, n_upper, tmp_data, ldm, pipvt,
4866 for (octave_idx_type i = 0; i < nr; i++) 5391 anorm, rcond, pz, piz, err
4867 Bx[i] = 0.; 5392 F77_CHAR_ARG_LEN (1)));
4868 5393
4869 for (octave_idx_type i = b.cidx(j); i < b.cidx(j+1); i++) 5394 if (f77_exception_encountered)
4870 Bx[b.ridx(i)] = b.data(i); 5395 (*current_liboctave_error_handler)
4871 5396 ("unrecoverable error in zgbcon");
4872 F77_XFCN (zgbtrs, ZGBTRS, 5397
4873 (F77_CONST_CHAR_ARG2 (&job, 1), 5398 if (err != 0)
4874 nr, n_lower, n_upper, 1, tmp_data, 5399 err = -2;
4875 ldm, pipvt, Bx, b.rows (), err 5400
4876 F77_CHAR_ARG_LEN (1))); 5401 volatile double rcond_plus_one = rcond + 1.0;
5402
5403 if (rcond_plus_one == 1.0 || xisnan (rcond))
5404 {
5405 err = -2;
5406
5407 if (sing_handler)
5408 {
5409 sing_handler (rcond);
5410 mattype.mark_as_rectangular ();
5411 }
5412 else
5413 (*current_liboctave_error_handler)
5414 ("matrix singular to machine precision, rcond = %g",
5415 rcond);
5416 }
5417 }
5418 else
5419 rcond = 1.;
5420
5421 if (err == 0)
5422 {
5423 char job = 'N';
5424 volatile octave_idx_type x_nz = b.nnz ();
5425 octave_idx_type b_nc = b.cols ();
5426 retval = SparseComplexMatrix (nr, b_nc, x_nz);
5427 retval.xcidx(0) = 0;
5428 volatile octave_idx_type ii = 0;
5429
5430 OCTAVE_LOCAL_BUFFER (Complex, Bx, nr);
5431
5432 for (volatile octave_idx_type j = 0; j < b_nc; j++)
5433 {
5434 for (octave_idx_type i = 0; i < nr; i++)
5435 Bx[i] = 0.;
5436
5437 for (octave_idx_type i = b.cidx(j);
5438 i < b.cidx(j+1); i++)
5439 Bx[b.ridx(i)] = b.data(i);
5440
5441 F77_XFCN (zgbtrs, ZGBTRS,
5442 (F77_CONST_CHAR_ARG2 (&job, 1),
5443 nr, n_lower, n_upper, 1, tmp_data,
5444 ldm, pipvt, Bx, b.rows (), err
5445 F77_CHAR_ARG_LEN (1)));
4877 5446
4878 if (f77_exception_encountered) 5447 if (f77_exception_encountered)
4879 { 5448 {
4880 (*current_liboctave_error_handler) 5449 (*current_liboctave_error_handler)
4881 ("unrecoverable error in dgbtrs"); 5450 ("unrecoverable error in dgbtrs");
4882 break; 5451 break;
5452 }
5453
5454 // Count non-zeros in work vector and adjust
5455 // space in retval if needed
5456 octave_idx_type new_nnz = 0;
5457 for (octave_idx_type i = 0; i < nr; i++)
5458 if (Bx[i] != 0.)
5459 new_nnz++;
5460
5461 if (ii + new_nnz > x_nz)
5462 {
5463 // Resize the sparse matrix
5464 octave_idx_type sz = new_nnz * (b_nc - j) + x_nz;
5465 retval.change_capacity (sz);
5466 x_nz = sz;
5467 }
5468
5469 for (octave_idx_type i = 0; i < nr; i++)
5470 if (Bx[i] != 0.)
5471 {
5472 retval.xridx(ii) = i;
5473 retval.xdata(ii++) = Bx[i];
5474 }
5475 retval.xcidx(j+1) = ii;
4883 } 5476 }
4884 5477
4885 // Count non-zeros in work vector and adjust 5478 retval.maybe_compress ();
4886 // space in retval if needed 5479 }
4887 octave_idx_type new_nnz = 0;
4888 for (octave_idx_type i = 0; i < nr; i++)
4889 if (Bx[i] != 0.)
4890 new_nnz++;
4891
4892 if (ii + new_nnz > x_nz)
4893 {
4894 // Resize the sparse matrix
4895 octave_idx_type sz = new_nnz * (b_nc - j) + x_nz;
4896 retval.change_capacity (sz);
4897 x_nz = sz;
4898 }
4899
4900 for (octave_idx_type i = 0; i < nr; i++)
4901 if (Bx[i] != 0.)
4902 {
4903 retval.xridx(ii) = i;
4904 retval.xdata(ii++) = Bx[i];
4905 }
4906 retval.xcidx(j+1) = ii;
4907 }
4908
4909 retval.maybe_compress ();
4910 } 5480 }
4911 } 5481 }
4912 } 5482 }
4913 else if (typ != SparseType::Banded_Hermitian) 5483 else if (typ != SparseType::Banded_Hermitian)
4914 (*current_liboctave_error_handler) ("incorrect matrix type"); 5484 (*current_liboctave_error_handler) ("incorrect matrix type");
4916 5486
4917 return retval; 5487 return retval;
4918 } 5488 }
4919 5489
4920 void * 5490 void *
4921 SparseComplexMatrix::factorize (octave_idx_type& err, double &rcond, Matrix &Control, 5491 SparseComplexMatrix::factorize (octave_idx_type& err, double &rcond,
4922 Matrix &Info, 5492 Matrix &Control, Matrix &Info,
4923 solve_singularity_handler sing_handler) const 5493 solve_singularity_handler sing_handler,
5494 bool calc_cond) const
4924 { 5495 {
4925 // The return values 5496 // The return values
4926 void *Numeric = 0; 5497 void *Numeric = 0;
4927 err = 0; 5498 err = 0;
4928 5499
4983 status = UMFPACK_ZNAME (numeric) (Ap, Ai, 5554 status = UMFPACK_ZNAME (numeric) (Ap, Ai,
4984 X_CAST (const double *, Ax), NULL, 5555 X_CAST (const double *, Ax), NULL,
4985 Symbolic, &Numeric, control, info) ; 5556 Symbolic, &Numeric, control, info) ;
4986 UMFPACK_ZNAME (free_symbolic) (&Symbolic) ; 5557 UMFPACK_ZNAME (free_symbolic) (&Symbolic) ;
4987 5558
4988 rcond = Info (UMFPACK_RCOND); 5559 if (calc_cond)
5560 rcond = Info (UMFPACK_RCOND);
5561 else
5562 rcond = 1.;
4989 volatile double rcond_plus_one = rcond + 1.0; 5563 volatile double rcond_plus_one = rcond + 1.0;
4990 5564
4991 if (status == UMFPACK_WARNING_singular_matrix || 5565 if (status == UMFPACK_WARNING_singular_matrix ||
4992 rcond_plus_one == 1.0 || xisnan (rcond)) 5566 rcond_plus_one == 1.0 || xisnan (rcond))
4993 { 5567 {
5027 5601
5028 return Numeric; 5602 return Numeric;
5029 } 5603 }
5030 5604
5031 ComplexMatrix 5605 ComplexMatrix
5032 SparseComplexMatrix::fsolve (SparseType &mattype, const Matrix& b, octave_idx_type& err, 5606 SparseComplexMatrix::fsolve (SparseType &mattype, const Matrix& b,
5033 double& rcond, 5607 octave_idx_type& err, double& rcond,
5034 solve_singularity_handler sing_handler) const 5608 solve_singularity_handler sing_handler,
5609 bool calc_cond) const
5035 { 5610 {
5036 ComplexMatrix retval; 5611 ComplexMatrix retval;
5037 5612
5038 octave_idx_type nr = rows (); 5613 octave_idx_type nr = rows ();
5039 octave_idx_type nc = cols (); 5614 octave_idx_type nc = cols ();
5137 5712
5138 cholmod_factor *L; 5713 cholmod_factor *L;
5139 BEGIN_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE; 5714 BEGIN_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE;
5140 L = CHOLMOD_NAME(analyze) (A, cm); 5715 L = CHOLMOD_NAME(analyze) (A, cm);
5141 CHOLMOD_NAME(factorize) (A, L, cm); 5716 CHOLMOD_NAME(factorize) (A, L, cm);
5142 rcond = CHOLMOD_NAME(rcond)(L, cm); 5717 if (calc_cond)
5718 rcond = CHOLMOD_NAME(rcond)(L, cm);
5719 else
5720 rcond = 1.;
5143 END_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE; 5721 END_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE;
5144 5722
5145 if (rcond == 0.0) 5723 if (rcond == 0.0)
5146 { 5724 {
5147 // Either its indefinite or singular. Try UMFPACK 5725 // Either its indefinite or singular. Try UMFPACK
5155 if (rcond_plus_one == 1.0 || xisnan (rcond)) 5733 if (rcond_plus_one == 1.0 || xisnan (rcond))
5156 { 5734 {
5157 err = -2; 5735 err = -2;
5158 5736
5159 if (sing_handler) 5737 if (sing_handler)
5160 sing_handler (rcond); 5738 {
5739 sing_handler (rcond);
5740 mattype.mark_as_rectangular ();
5741 }
5161 else 5742 else
5162 (*current_liboctave_error_handler) 5743 (*current_liboctave_error_handler)
5163 ("SparseMatrix::solve matrix singular to machine precision, rcond = %g", 5744 ("SparseMatrix::solve matrix singular to machine precision, rcond = %g",
5164 rcond); 5745 rcond);
5165 5746
5198 if (typ == SparseType::Full) 5779 if (typ == SparseType::Full)
5199 { 5780 {
5200 #ifdef HAVE_UMFPACK 5781 #ifdef HAVE_UMFPACK
5201 Matrix Control, Info; 5782 Matrix Control, Info;
5202 void *Numeric = factorize (err, rcond, Control, Info, 5783 void *Numeric = factorize (err, rcond, Control, Info,
5203 sing_handler); 5784 sing_handler, calc_cond);
5204 5785
5205 if (err == 0) 5786 if (err == 0)
5206 { 5787 {
5207 octave_idx_type b_nr = b.rows (); 5788 octave_idx_type b_nr = b.rows ();
5208 octave_idx_type b_nc = b.cols (); 5789 octave_idx_type b_nc = b.cols ();
5262 5843
5263 UMFPACK_ZNAME (report_info) (control, info); 5844 UMFPACK_ZNAME (report_info) (control, info);
5264 5845
5265 UMFPACK_ZNAME (free_numeric) (&Numeric); 5846 UMFPACK_ZNAME (free_numeric) (&Numeric);
5266 } 5847 }
5848 else
5849 mattype.mark_as_rectangular ();
5850
5267 #else 5851 #else
5268 (*current_liboctave_error_handler) ("UMFPACK not installed"); 5852 (*current_liboctave_error_handler) ("UMFPACK not installed");
5269 #endif 5853 #endif
5270 } 5854 }
5271 else if (typ != SparseType::Hermitian) 5855 else if (typ != SparseType::Hermitian)
5276 } 5860 }
5277 5861
5278 SparseComplexMatrix 5862 SparseComplexMatrix
5279 SparseComplexMatrix::fsolve (SparseType &mattype, const SparseMatrix& b, 5863 SparseComplexMatrix::fsolve (SparseType &mattype, const SparseMatrix& b,
5280 octave_idx_type& err, double& rcond, 5864 octave_idx_type& err, double& rcond,
5281 solve_singularity_handler sing_handler) const 5865 solve_singularity_handler sing_handler,
5866 bool calc_cond) const
5282 { 5867 {
5283 SparseComplexMatrix retval; 5868 SparseComplexMatrix retval;
5284 5869
5285 octave_idx_type nr = rows (); 5870 octave_idx_type nr = rows ();
5286 octave_idx_type nc = cols (); 5871 octave_idx_type nc = cols ();
5395 5980
5396 cholmod_factor *L; 5981 cholmod_factor *L;
5397 BEGIN_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE; 5982 BEGIN_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE;
5398 L = CHOLMOD_NAME(analyze) (A, cm); 5983 L = CHOLMOD_NAME(analyze) (A, cm);
5399 CHOLMOD_NAME(factorize) (A, L, cm); 5984 CHOLMOD_NAME(factorize) (A, L, cm);
5400 rcond = CHOLMOD_NAME(rcond)(L, cm); 5985 if (calc_cond)
5986 rcond = CHOLMOD_NAME(rcond)(L, cm);
5987 else
5988 rcond = 1.;
5401 END_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE; 5989 END_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE;
5402 5990
5403 if (rcond == 0.0) 5991 if (rcond == 0.0)
5404 { 5992 {
5405 // Either its indefinite or singular. Try UMFPACK 5993 // Either its indefinite or singular. Try UMFPACK
5413 if (rcond_plus_one == 1.0 || xisnan (rcond)) 6001 if (rcond_plus_one == 1.0 || xisnan (rcond))
5414 { 6002 {
5415 err = -2; 6003 err = -2;
5416 6004
5417 if (sing_handler) 6005 if (sing_handler)
5418 sing_handler (rcond); 6006 {
6007 sing_handler (rcond);
6008 mattype.mark_as_rectangular ();
6009 }
5419 else 6010 else
5420 (*current_liboctave_error_handler) 6011 (*current_liboctave_error_handler)
5421 ("SparseMatrix::solve matrix singular to machine precision, rcond = %g", 6012 ("SparseMatrix::solve matrix singular to machine precision, rcond = %g",
5422 rcond); 6013 rcond);
5423 6014
5461 6052
5462 if (typ == SparseType::Full) 6053 if (typ == SparseType::Full)
5463 { 6054 {
5464 #ifdef HAVE_UMFPACK 6055 #ifdef HAVE_UMFPACK
5465 Matrix Control, Info; 6056 Matrix Control, Info;
5466 void *Numeric = factorize (err, rcond, Control, Info, sing_handler); 6057 void *Numeric = factorize (err, rcond, Control, Info,
6058 sing_handler, calc_cond);
5467 6059
5468 if (err == 0) 6060 if (err == 0)
5469 { 6061 {
5470 octave_idx_type b_nr = b.rows (); 6062 octave_idx_type b_nr = b.rows ();
5471 octave_idx_type b_nc = b.cols (); 6063 octave_idx_type b_nc = b.cols ();
5485 OCTAVE_LOCAL_BUFFER (Complex, Bz, b_nr); 6077 OCTAVE_LOCAL_BUFFER (Complex, Bz, b_nr);
5486 #endif 6078 #endif
5487 6079
5488 // Take a first guess that the number of non-zero terms 6080 // Take a first guess that the number of non-zero terms
5489 // will be as many as in b 6081 // will be as many as in b
5490 octave_idx_type x_nz = b.nzmax (); 6082 octave_idx_type x_nz = b.nnz ();
5491 octave_idx_type ii = 0; 6083 octave_idx_type ii = 0;
5492 retval = SparseComplexMatrix (b_nr, b_nc, x_nz); 6084 retval = SparseComplexMatrix (b_nr, b_nc, x_nz);
5493 6085
5494 OCTAVE_LOCAL_BUFFER (Complex, Xx, b_nr); 6086 OCTAVE_LOCAL_BUFFER (Complex, Xx, b_nr);
5495 6087
5555 6147
5556 UMFPACK_ZNAME (report_info) (control, info); 6148 UMFPACK_ZNAME (report_info) (control, info);
5557 6149
5558 UMFPACK_ZNAME (free_numeric) (&Numeric); 6150 UMFPACK_ZNAME (free_numeric) (&Numeric);
5559 } 6151 }
6152 else
6153 mattype.mark_as_rectangular ();
6154
5560 #else 6155 #else
5561 (*current_liboctave_error_handler) ("UMFPACK not installed"); 6156 (*current_liboctave_error_handler) ("UMFPACK not installed");
5562 #endif 6157 #endif
5563 } 6158 }
5564 else if (typ != SparseType::Hermitian) 6159 else if (typ != SparseType::Hermitian)
5569 } 6164 }
5570 6165
5571 ComplexMatrix 6166 ComplexMatrix
5572 SparseComplexMatrix::fsolve (SparseType &mattype, const ComplexMatrix& b, 6167 SparseComplexMatrix::fsolve (SparseType &mattype, const ComplexMatrix& b,
5573 octave_idx_type& err, double& rcond, 6168 octave_idx_type& err, double& rcond,
5574 solve_singularity_handler sing_handler) const 6169 solve_singularity_handler sing_handler,
6170 bool calc_cond) const
5575 { 6171 {
5576 ComplexMatrix retval; 6172 ComplexMatrix retval;
5577 6173
5578 octave_idx_type nr = rows (); 6174 octave_idx_type nr = rows ();
5579 octave_idx_type nc = cols (); 6175 octave_idx_type nc = cols ();
5678 6274
5679 cholmod_factor *L; 6275 cholmod_factor *L;
5680 BEGIN_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE; 6276 BEGIN_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE;
5681 L = CHOLMOD_NAME(analyze) (A, cm); 6277 L = CHOLMOD_NAME(analyze) (A, cm);
5682 CHOLMOD_NAME(factorize) (A, L, cm); 6278 CHOLMOD_NAME(factorize) (A, L, cm);
5683 rcond = CHOLMOD_NAME(rcond)(L, cm); 6279 if (calc_cond)
6280 rcond = CHOLMOD_NAME(rcond)(L, cm);
6281 else
6282 rcond = 1.;
5684 END_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE; 6283 END_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE;
5685 6284
5686 if (rcond == 0.0) 6285 if (rcond == 0.0)
5687 { 6286 {
5688 // Either its indefinite or singular. Try UMFPACK 6287 // Either its indefinite or singular. Try UMFPACK
5696 if (rcond_plus_one == 1.0 || xisnan (rcond)) 6295 if (rcond_plus_one == 1.0 || xisnan (rcond))
5697 { 6296 {
5698 err = -2; 6297 err = -2;
5699 6298
5700 if (sing_handler) 6299 if (sing_handler)
5701 sing_handler (rcond); 6300 {
6301 sing_handler (rcond);
6302 mattype.mark_as_rectangular ();
6303 }
5702 else 6304 else
5703 (*current_liboctave_error_handler) 6305 (*current_liboctave_error_handler)
5704 ("SparseMatrix::solve matrix singular to machine precision, rcond = %g", 6306 ("SparseMatrix::solve matrix singular to machine precision, rcond = %g",
5705 rcond); 6307 rcond);
5706 6308
5738 6340
5739 if (typ == SparseType::Full) 6341 if (typ == SparseType::Full)
5740 { 6342 {
5741 #ifdef HAVE_UMFPACK 6343 #ifdef HAVE_UMFPACK
5742 Matrix Control, Info; 6344 Matrix Control, Info;
5743 void *Numeric = factorize (err, rcond, Control, Info, sing_handler); 6345 void *Numeric = factorize (err, rcond, Control, Info,
6346 sing_handler, calc_cond);
5744 6347
5745 if (err == 0) 6348 if (err == 0)
5746 { 6349 {
5747 octave_idx_type b_nr = b.rows (); 6350 octave_idx_type b_nr = b.rows ();
5748 octave_idx_type b_nc = b.cols (); 6351 octave_idx_type b_nc = b.cols ();
5781 6384
5782 UMFPACK_ZNAME (report_info) (control, info); 6385 UMFPACK_ZNAME (report_info) (control, info);
5783 6386
5784 UMFPACK_ZNAME (free_numeric) (&Numeric); 6387 UMFPACK_ZNAME (free_numeric) (&Numeric);
5785 } 6388 }
6389 else
6390 mattype.mark_as_rectangular ();
6391
5786 #else 6392 #else
5787 (*current_liboctave_error_handler) ("UMFPACK not installed"); 6393 (*current_liboctave_error_handler) ("UMFPACK not installed");
5788 #endif 6394 #endif
5789 } 6395 }
5790 else if (typ != SparseType::Hermitian) 6396 else if (typ != SparseType::Hermitian)
5795 } 6401 }
5796 6402
5797 SparseComplexMatrix 6403 SparseComplexMatrix
5798 SparseComplexMatrix::fsolve (SparseType &mattype, const SparseComplexMatrix& b, 6404 SparseComplexMatrix::fsolve (SparseType &mattype, const SparseComplexMatrix& b,
5799 octave_idx_type& err, double& rcond, 6405 octave_idx_type& err, double& rcond,
5800 solve_singularity_handler sing_handler) const 6406 solve_singularity_handler sing_handler,
6407 bool calc_cond) const
5801 { 6408 {
5802 SparseComplexMatrix retval; 6409 SparseComplexMatrix retval;
5803 6410
5804 octave_idx_type nr = rows (); 6411 octave_idx_type nr = rows ();
5805 octave_idx_type nc = cols (); 6412 octave_idx_type nc = cols ();
5914 6521
5915 cholmod_factor *L; 6522 cholmod_factor *L;
5916 BEGIN_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE; 6523 BEGIN_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE;
5917 L = CHOLMOD_NAME(analyze) (A, cm); 6524 L = CHOLMOD_NAME(analyze) (A, cm);
5918 CHOLMOD_NAME(factorize) (A, L, cm); 6525 CHOLMOD_NAME(factorize) (A, L, cm);
5919 rcond = CHOLMOD_NAME(rcond)(L, cm); 6526 if (calc_cond)
6527 rcond = CHOLMOD_NAME(rcond)(L, cm);
6528 else
6529 rcond = 1.;
5920 END_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE; 6530 END_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE;
5921 6531
5922 if (rcond == 0.0) 6532 if (rcond == 0.0)
5923 { 6533 {
5924 // Either its indefinite or singular. Try UMFPACK 6534 // Either its indefinite or singular. Try UMFPACK
5932 if (rcond_plus_one == 1.0 || xisnan (rcond)) 6542 if (rcond_plus_one == 1.0 || xisnan (rcond))
5933 { 6543 {
5934 err = -2; 6544 err = -2;
5935 6545
5936 if (sing_handler) 6546 if (sing_handler)
5937 sing_handler (rcond); 6547 {
6548 sing_handler (rcond);
6549 mattype.mark_as_rectangular ();
6550 }
5938 else 6551 else
5939 (*current_liboctave_error_handler) 6552 (*current_liboctave_error_handler)
5940 ("SparseMatrix::solve matrix singular to machine precision, rcond = %g", 6553 ("SparseMatrix::solve matrix singular to machine precision, rcond = %g",
5941 rcond); 6554 rcond);
5942 6555
5980 6593
5981 if (typ == SparseType::Full) 6594 if (typ == SparseType::Full)
5982 { 6595 {
5983 #ifdef HAVE_UMFPACK 6596 #ifdef HAVE_UMFPACK
5984 Matrix Control, Info; 6597 Matrix Control, Info;
5985 void *Numeric = factorize (err, rcond, Control, Info, sing_handler); 6598 void *Numeric = factorize (err, rcond, Control, Info,
6599 sing_handler, calc_cond);
5986 6600
5987 if (err == 0) 6601 if (err == 0)
5988 { 6602 {
5989 octave_idx_type b_nr = b.rows (); 6603 octave_idx_type b_nr = b.rows ();
5990 octave_idx_type b_nc = b.cols (); 6604 octave_idx_type b_nc = b.cols ();
5997 6611
5998 OCTAVE_LOCAL_BUFFER (Complex, Bx, b_nr); 6612 OCTAVE_LOCAL_BUFFER (Complex, Bx, b_nr);
5999 6613
6000 // Take a first guess that the number of non-zero terms 6614 // Take a first guess that the number of non-zero terms
6001 // will be as many as in b 6615 // will be as many as in b
6002 octave_idx_type x_nz = b.nzmax (); 6616 octave_idx_type x_nz = b.nnz ();
6003 octave_idx_type ii = 0; 6617 octave_idx_type ii = 0;
6004 retval = SparseComplexMatrix (b_nr, b_nc, x_nz); 6618 retval = SparseComplexMatrix (b_nr, b_nc, x_nz);
6005 6619
6006 OCTAVE_LOCAL_BUFFER (Complex, Xx, b_nr); 6620 OCTAVE_LOCAL_BUFFER (Complex, Xx, b_nr);
6007 6621
6070 6684
6071 UMFPACK_ZNAME (report_info) (control, info); 6685 UMFPACK_ZNAME (report_info) (control, info);
6072 6686
6073 UMFPACK_ZNAME (free_numeric) (&Numeric); 6687 UMFPACK_ZNAME (free_numeric) (&Numeric);
6074 } 6688 }
6689 else
6690 mattype.mark_as_rectangular ();
6691
6075 #else 6692 #else
6076 (*current_liboctave_error_handler) ("UMFPACK not installed"); 6693 (*current_liboctave_error_handler) ("UMFPACK not installed");
6077 #endif 6694 #endif
6078 } 6695 }
6079 else if (typ != SparseType::Hermitian) 6696 else if (typ != SparseType::Hermitian)
6109 ComplexMatrix 6726 ComplexMatrix
6110 SparseComplexMatrix::solve (SparseType &mattype, const Matrix& b, octave_idx_type& err, 6727 SparseComplexMatrix::solve (SparseType &mattype, const Matrix& b, octave_idx_type& err,
6111 double& rcond, 6728 double& rcond,
6112 solve_singularity_handler sing_handler) const 6729 solve_singularity_handler sing_handler) const
6113 { 6730 {
6731 ComplexMatrix retval;
6114 int typ = mattype.type (false); 6732 int typ = mattype.type (false);
6115 6733
6116 if (typ == SparseType::Unknown) 6734 if (typ == SparseType::Unknown)
6117 typ = mattype.type (*this); 6735 typ = mattype.type (*this);
6118 6736
6119 if (typ == SparseType::Diagonal || typ == SparseType::Permuted_Diagonal) 6737 if (typ == SparseType::Diagonal || typ == SparseType::Permuted_Diagonal)
6120 return dsolve (mattype, b, err, rcond, sing_handler); 6738 retval = dsolve (mattype, b, err, rcond, sing_handler, false);
6121 else if (typ == SparseType::Upper || typ == SparseType::Permuted_Upper) 6739 else if (typ == SparseType::Upper || typ == SparseType::Permuted_Upper)
6122 return utsolve (mattype, b, err, rcond, sing_handler); 6740 retval = utsolve (mattype, b, err, rcond, sing_handler, false);
6123 else if (typ == SparseType::Lower || typ == SparseType::Permuted_Lower) 6741 else if (typ == SparseType::Lower || typ == SparseType::Permuted_Lower)
6124 return ltsolve (mattype, b, err, rcond, sing_handler); 6742 retval = ltsolve (mattype, b, err, rcond, sing_handler, false);
6125 else if (typ == SparseType::Banded || typ == SparseType::Banded_Hermitian) 6743 else if (typ == SparseType::Banded || typ == SparseType::Banded_Hermitian)
6126 return bsolve (mattype, b, err, rcond, sing_handler); 6744 retval = bsolve (mattype, b, err, rcond, sing_handler, false);
6127 else if (typ == SparseType::Tridiagonal || 6745 else if (typ == SparseType::Tridiagonal ||
6128 typ == SparseType::Tridiagonal_Hermitian) 6746 typ == SparseType::Tridiagonal_Hermitian)
6129 return trisolve (mattype, b, err, rcond, sing_handler); 6747 retval = trisolve (mattype, b, err, rcond, sing_handler, false);
6130 else if (typ == SparseType::Full || typ == SparseType::Hermitian) 6748 else if (typ == SparseType::Full || typ == SparseType::Hermitian)
6131 return fsolve (mattype, b, err, rcond, sing_handler); 6749 retval = fsolve (mattype, b, err, rcond, sing_handler, true);
6132 else 6750 else if (typ != SparseType::Rectangular)
6133 { 6751 {
6134 (*current_liboctave_error_handler) 6752 (*current_liboctave_error_handler) ("unknown matrix type");
6135 ("matrix dimension mismatch solution of linear equations");
6136 return ComplexMatrix (); 6753 return ComplexMatrix ();
6137 } 6754 }
6755
6756 if (mattype.type(false) == SparseType::Rectangular)
6757 {
6758 rcond = 1.;
6759 #ifdef USE_QRSOLVE
6760 retval = qrsolve (*this, b, err);
6761 #else
6762 retval = dmsolve<ComplexMatrix, SparseComplexMatrix,
6763 Matrix> (*this, b, err);
6764 #endif
6765 }
6766
6767 return retval;
6138 } 6768 }
6139 6769
6140 SparseComplexMatrix 6770 SparseComplexMatrix
6141 SparseComplexMatrix::solve (SparseType &mattype, const SparseMatrix& b) const 6771 SparseComplexMatrix::solve (SparseType &mattype, const SparseMatrix& b) const
6142 { 6772 {
6163 SparseComplexMatrix 6793 SparseComplexMatrix
6164 SparseComplexMatrix::solve (SparseType &mattype, const SparseMatrix& b, 6794 SparseComplexMatrix::solve (SparseType &mattype, const SparseMatrix& b,
6165 octave_idx_type& err, double& rcond, 6795 octave_idx_type& err, double& rcond,
6166 solve_singularity_handler sing_handler) const 6796 solve_singularity_handler sing_handler) const
6167 { 6797 {
6798 SparseComplexMatrix retval;
6168 int typ = mattype.type (false); 6799 int typ = mattype.type (false);
6169 6800
6170 if (typ == SparseType::Unknown) 6801 if (typ == SparseType::Unknown)
6171 typ = mattype.type (*this); 6802 typ = mattype.type (*this);
6172 6803
6173 if (typ == SparseType::Diagonal || typ == SparseType::Permuted_Diagonal) 6804 if (typ == SparseType::Diagonal || typ == SparseType::Permuted_Diagonal)
6174 return dsolve (mattype, b, err, rcond, sing_handler); 6805 retval = dsolve (mattype, b, err, rcond, sing_handler, false);
6175 else if (typ == SparseType::Upper || typ == SparseType::Permuted_Upper) 6806 else if (typ == SparseType::Upper || typ == SparseType::Permuted_Upper)
6176 return utsolve (mattype, b, err, rcond, sing_handler); 6807 retval = utsolve (mattype, b, err, rcond, sing_handler, false);
6177 else if (typ == SparseType::Lower || typ == SparseType::Permuted_Lower) 6808 else if (typ == SparseType::Lower || typ == SparseType::Permuted_Lower)
6178 return ltsolve (mattype, b, err, rcond, sing_handler); 6809 retval = ltsolve (mattype, b, err, rcond, sing_handler, false);
6179 else if (typ == SparseType::Banded || typ == SparseType::Banded_Hermitian) 6810 else if (typ == SparseType::Banded || typ == SparseType::Banded_Hermitian)
6180 return bsolve (mattype, b, err, rcond, sing_handler); 6811 retval = bsolve (mattype, b, err, rcond, sing_handler, false);
6181 else if (typ == SparseType::Tridiagonal || 6812 else if (typ == SparseType::Tridiagonal ||
6182 typ == SparseType::Tridiagonal_Hermitian) 6813 typ == SparseType::Tridiagonal_Hermitian)
6183 return trisolve (mattype, b, err, rcond, sing_handler); 6814 retval = trisolve (mattype, b, err, rcond, sing_handler, false);
6184 else if (typ == SparseType::Full || typ == SparseType::Hermitian) 6815 else if (typ == SparseType::Full || typ == SparseType::Hermitian)
6185 return fsolve (mattype, b, err, rcond, sing_handler); 6816 retval = fsolve (mattype, b, err, rcond, sing_handler, true);
6186 else 6817 else if (typ != SparseType::Rectangular)
6187 { 6818 {
6188 (*current_liboctave_error_handler) 6819 (*current_liboctave_error_handler) ("unknown matrix type");
6189 ("matrix dimension mismatch solution of linear equations");
6190 return SparseComplexMatrix (); 6820 return SparseComplexMatrix ();
6191 } 6821 }
6822
6823 if (mattype.type(false) == SparseType::Rectangular)
6824 {
6825 rcond = 1.;
6826 #ifdef USE_QRSOLVE
6827 retval = qrsolve (*this, b, err);
6828 #else
6829 retval = dmsolve<SparseComplexMatrix, SparseComplexMatrix,
6830 SparseMatrix> (*this, b, err);
6831 #endif
6832 }
6833
6834 return retval;
6192 } 6835 }
6193 6836
6194 ComplexMatrix 6837 ComplexMatrix
6195 SparseComplexMatrix::solve (SparseType &mattype, const ComplexMatrix& b) const 6838 SparseComplexMatrix::solve (SparseType &mattype, const ComplexMatrix& b) const
6196 { 6839 {
6217 ComplexMatrix 6860 ComplexMatrix
6218 SparseComplexMatrix::solve (SparseType &mattype, const ComplexMatrix& b, 6861 SparseComplexMatrix::solve (SparseType &mattype, const ComplexMatrix& b,
6219 octave_idx_type& err, double& rcond, 6862 octave_idx_type& err, double& rcond,
6220 solve_singularity_handler sing_handler) const 6863 solve_singularity_handler sing_handler) const
6221 { 6864 {
6865 ComplexMatrix retval;
6222 int typ = mattype.type (false); 6866 int typ = mattype.type (false);
6223 6867
6224 if (typ == SparseType::Unknown) 6868 if (typ == SparseType::Unknown)
6225 typ = mattype.type (*this); 6869 typ = mattype.type (*this);
6226 6870
6227 if (typ == SparseType::Diagonal || typ == SparseType::Permuted_Diagonal) 6871 if (typ == SparseType::Diagonal || typ == SparseType::Permuted_Diagonal)
6228 return dsolve (mattype, b, err, rcond, sing_handler); 6872 retval = dsolve (mattype, b, err, rcond, sing_handler, false);
6229 else if (typ == SparseType::Upper || typ == SparseType::Permuted_Upper) 6873 else if (typ == SparseType::Upper || typ == SparseType::Permuted_Upper)
6230 return utsolve (mattype, b, err, rcond, sing_handler); 6874 retval = utsolve (mattype, b, err, rcond, sing_handler, false);
6231 else if (typ == SparseType::Lower || typ == SparseType::Permuted_Lower) 6875 else if (typ == SparseType::Lower || typ == SparseType::Permuted_Lower)
6232 return ltsolve (mattype, b, err, rcond, sing_handler); 6876 retval = ltsolve (mattype, b, err, rcond, sing_handler, false);
6233 else if (typ == SparseType::Banded || typ == SparseType::Banded_Hermitian) 6877 else if (typ == SparseType::Banded || typ == SparseType::Banded_Hermitian)
6234 return bsolve (mattype, b, err, rcond, sing_handler); 6878 retval = bsolve (mattype, b, err, rcond, sing_handler, false);
6235 else if (typ == SparseType::Tridiagonal || 6879 else if (typ == SparseType::Tridiagonal ||
6236 typ == SparseType::Tridiagonal_Hermitian) 6880 typ == SparseType::Tridiagonal_Hermitian)
6237 return trisolve (mattype, b, err, rcond, sing_handler); 6881 retval = trisolve (mattype, b, err, rcond, sing_handler, false);
6238 else if (typ == SparseType::Full || typ == SparseType::Hermitian) 6882 else if (typ == SparseType::Full || typ == SparseType::Hermitian)
6239 return fsolve (mattype, b, err, rcond, sing_handler); 6883 retval = fsolve (mattype, b, err, rcond, sing_handler, true);
6240 else 6884 else if (typ != SparseType::Rectangular)
6241 { 6885 {
6242 (*current_liboctave_error_handler) 6886 (*current_liboctave_error_handler) ("unknown matrix type");
6243 ("matrix dimension mismatch solution of linear equations");
6244 return ComplexMatrix (); 6887 return ComplexMatrix ();
6245 } 6888 }
6889
6890 if (mattype.type(false) == SparseType::Rectangular)
6891 {
6892 rcond = 1.;
6893 #ifdef USE_QRSOLVE
6894 retval = qrsolve (*this, b, err);
6895 #else
6896 retval = dmsolve<ComplexMatrix, SparseComplexMatrix,
6897 ComplexMatrix> (*this, b, err);
6898 #endif
6899 }
6900
6901 return retval;
6246 } 6902 }
6247 6903
6248 SparseComplexMatrix 6904 SparseComplexMatrix
6249 SparseComplexMatrix::solve (SparseType &mattype, 6905 SparseComplexMatrix::solve (SparseType &mattype,
6250 const SparseComplexMatrix& b) const 6906 const SparseComplexMatrix& b) const
6272 SparseComplexMatrix 6928 SparseComplexMatrix
6273 SparseComplexMatrix::solve (SparseType &mattype, const SparseComplexMatrix& b, 6929 SparseComplexMatrix::solve (SparseType &mattype, const SparseComplexMatrix& b,
6274 octave_idx_type& err, double& rcond, 6930 octave_idx_type& err, double& rcond,
6275 solve_singularity_handler sing_handler) const 6931 solve_singularity_handler sing_handler) const
6276 { 6932 {
6933 SparseComplexMatrix retval;
6277 int typ = mattype.type (false); 6934 int typ = mattype.type (false);
6278 6935
6279 if (typ == SparseType::Unknown) 6936 if (typ == SparseType::Unknown)
6280 typ = mattype.type (*this); 6937 typ = mattype.type (*this);
6281 6938
6282 if (typ == SparseType::Diagonal || typ == SparseType::Permuted_Diagonal) 6939 if (typ == SparseType::Diagonal || typ == SparseType::Permuted_Diagonal)
6283 return dsolve (mattype, b, err, rcond, sing_handler); 6940 retval = dsolve (mattype, b, err, rcond, sing_handler, false);
6284 else if (typ == SparseType::Upper || typ == SparseType::Permuted_Upper) 6941 else if (typ == SparseType::Upper || typ == SparseType::Permuted_Upper)
6285 return utsolve (mattype, b, err, rcond, sing_handler); 6942 retval = utsolve (mattype, b, err, rcond, sing_handler, false);
6286 else if (typ == SparseType::Lower || typ == SparseType::Permuted_Lower) 6943 else if (typ == SparseType::Lower || typ == SparseType::Permuted_Lower)
6287 return ltsolve (mattype, b, err, rcond, sing_handler); 6944 retval = ltsolve (mattype, b, err, rcond, sing_handler, false);
6288 else if (typ == SparseType::Banded || typ == SparseType::Banded_Hermitian) 6945 else if (typ == SparseType::Banded || typ == SparseType::Banded_Hermitian)
6289 return bsolve (mattype, b, err, rcond, sing_handler); 6946 retval = bsolve (mattype, b, err, rcond, sing_handler, false);
6290 else if (typ == SparseType::Tridiagonal || 6947 else if (typ == SparseType::Tridiagonal ||
6291 typ == SparseType::Tridiagonal_Hermitian) 6948 typ == SparseType::Tridiagonal_Hermitian)
6292 return trisolve (mattype, b, err, rcond, sing_handler); 6949 retval = trisolve (mattype, b, err, rcond, sing_handler, false);
6293 else if (typ == SparseType::Full || typ == SparseType::Hermitian) 6950 else if (typ == SparseType::Full || typ == SparseType::Hermitian)
6294 return fsolve (mattype, b, err, rcond, sing_handler); 6951 retval = fsolve (mattype, b, err, rcond, sing_handler, true);
6295 else 6952 else if (typ != SparseType::Rectangular)
6296 { 6953 {
6297 (*current_liboctave_error_handler) 6954 (*current_liboctave_error_handler) ("unknown matrix type");
6298 ("matrix dimension mismatch solution of linear equations");
6299 return SparseComplexMatrix (); 6955 return SparseComplexMatrix ();
6300 } 6956 }
6957
6958 if (mattype.type(false) == SparseType::Rectangular)
6959 {
6960 rcond = 1.;
6961 #ifdef USE_QRSOLVE
6962 retval = qrsolve (*this, b, err);
6963 #else
6964 retval = dmsolve<SparseComplexMatrix, SparseComplexMatrix,
6965 SparseComplexMatrix> (*this, b, err);
6966 #endif
6967 }
6968
6969 return retval;
6301 } 6970 }
6302 6971
6303 ComplexColumnVector 6972 ComplexColumnVector
6304 SparseComplexMatrix::solve (SparseType &mattype, const ColumnVector& b) const 6973 SparseComplexMatrix::solve (SparseType &mattype, const ColumnVector& b) const
6305 { 6974 {
6541 { 7210 {
6542 ComplexMatrix tmp (b); 7211 ComplexMatrix tmp (b);
6543 return solve (tmp, info, rcond, sing_handler).column (static_cast<octave_idx_type> (0)); 7212 return solve (tmp, info, rcond, sing_handler).column (static_cast<octave_idx_type> (0));
6544 } 7213 }
6545 7214
6546 ComplexMatrix
6547 SparseComplexMatrix::lssolve (const Matrix& b) const
6548 {
6549 octave_idx_type info;
6550 octave_idx_type rank;
6551 return lssolve (b, info, rank);
6552 }
6553
6554 ComplexMatrix
6555 SparseComplexMatrix::lssolve (const Matrix& b, octave_idx_type& info) const
6556 {
6557 octave_idx_type rank;
6558 return lssolve (b, info, rank);
6559 }
6560
6561 ComplexMatrix
6562 SparseComplexMatrix::lssolve (const Matrix& b, octave_idx_type& info, octave_idx_type&) const
6563 {
6564 return qrsolve (*this, b, info);
6565 }
6566
6567 SparseComplexMatrix
6568 SparseComplexMatrix::lssolve (const SparseMatrix& b) const
6569 {
6570 octave_idx_type info;
6571 octave_idx_type rank;
6572 return lssolve (b, info, rank);
6573 }
6574
6575 SparseComplexMatrix
6576 SparseComplexMatrix::lssolve (const SparseMatrix& b, octave_idx_type& info) const
6577 {
6578 octave_idx_type rank;
6579 return lssolve (b, info, rank);
6580 }
6581
6582 SparseComplexMatrix
6583 SparseComplexMatrix::lssolve (const SparseMatrix& b, octave_idx_type& info,
6584 octave_idx_type&) const
6585 {
6586 return qrsolve (*this, b, info);
6587 }
6588
6589 ComplexMatrix
6590 SparseComplexMatrix::lssolve (const ComplexMatrix& b) const
6591 {
6592 octave_idx_type info;
6593 octave_idx_type rank;
6594 return lssolve (b, info, rank);
6595 }
6596
6597 ComplexMatrix
6598 SparseComplexMatrix::lssolve (const ComplexMatrix& b, octave_idx_type& info) const
6599 {
6600 octave_idx_type rank;
6601 return lssolve (b, info, rank);
6602 }
6603
6604 ComplexMatrix
6605 SparseComplexMatrix::lssolve (const ComplexMatrix& b, octave_idx_type& info,
6606 octave_idx_type&) const
6607 {
6608 return qrsolve (*this, b, info);
6609 }
6610
6611 SparseComplexMatrix
6612 SparseComplexMatrix::lssolve (const SparseComplexMatrix& b) const
6613 {
6614 octave_idx_type info;
6615 octave_idx_type rank;
6616 return lssolve (b, info, rank);
6617 }
6618
6619 SparseComplexMatrix
6620 SparseComplexMatrix::lssolve (const SparseComplexMatrix& b, octave_idx_type& info) const
6621 {
6622 octave_idx_type rank;
6623 return lssolve (b, info, rank);
6624 }
6625
6626 SparseComplexMatrix
6627 SparseComplexMatrix::lssolve (const SparseComplexMatrix& b, octave_idx_type& info,
6628 octave_idx_type&) const
6629 {
6630 return qrsolve (*this, b, info);
6631 }
6632
6633 ComplexColumnVector
6634 SparseComplexMatrix::lssolve (const ColumnVector& b) const
6635 {
6636 octave_idx_type info;
6637 octave_idx_type rank;
6638 return lssolve (b, info, rank);
6639 }
6640
6641 ComplexColumnVector
6642 SparseComplexMatrix::lssolve (const ColumnVector& b, octave_idx_type& info) const
6643 {
6644 octave_idx_type rank;
6645 return lssolve (b, info, rank);
6646 }
6647
6648 ComplexColumnVector
6649 SparseComplexMatrix::lssolve (const ColumnVector& b, octave_idx_type& info, octave_idx_type& rank) const
6650 {
6651 Matrix tmp (b);
6652 return lssolve (tmp, info, rank).column (static_cast<octave_idx_type> (0));
6653 }
6654
6655 ComplexColumnVector
6656 SparseComplexMatrix::lssolve (const ComplexColumnVector& b) const
6657 {
6658 octave_idx_type info;
6659 octave_idx_type rank;
6660 return lssolve (b, info, rank);
6661 }
6662
6663 ComplexColumnVector
6664 SparseComplexMatrix::lssolve (const ComplexColumnVector& b, octave_idx_type& info) const
6665 {
6666 octave_idx_type rank;
6667 return lssolve (b, info, rank);
6668 }
6669
6670 ComplexColumnVector
6671 SparseComplexMatrix::lssolve (const ComplexColumnVector& b, octave_idx_type& info,
6672 octave_idx_type& rank) const
6673 {
6674 ComplexMatrix tmp (b);
6675 return lssolve (tmp, info, rank).column (static_cast<octave_idx_type> (0));
6676 }
6677
6678 // unary operations 7215 // unary operations
6679 SparseBoolMatrix 7216 SparseBoolMatrix
6680 SparseComplexMatrix::operator ! (void) const 7217 SparseComplexMatrix::operator ! (void) const
6681 { 7218 {
6682 octave_idx_type nr = rows (); 7219 octave_idx_type nr = rows ();
6683 octave_idx_type nc = cols (); 7220 octave_idx_type nc = cols ();
6684 octave_idx_type nz1 = nzmax (); 7221 octave_idx_type nz1 = nnz ();
6685 octave_idx_type nz2 = nr*nc - nz1; 7222 octave_idx_type nz2 = nr*nc - nz1;
6686 7223
6687 SparseBoolMatrix r (nr, nc, nz2); 7224 SparseBoolMatrix r (nr, nc, nz2);
6688 7225
6689 octave_idx_type ii = 0; 7226 octave_idx_type ii = 0;
6753 SparseComplexMatrix 7290 SparseComplexMatrix
6754 SparseComplexMatrix::map (c_c_Mapper f) const 7291 SparseComplexMatrix::map (c_c_Mapper f) const
6755 { 7292 {
6756 octave_idx_type nr = rows (); 7293 octave_idx_type nr = rows ();
6757 octave_idx_type nc = cols (); 7294 octave_idx_type nc = cols ();
6758 octave_idx_type nz = nzmax (); 7295 octave_idx_type nz = nnz ();
6759 bool f_zero = (f(0.0) == 0.0); 7296 bool f_zero = (f(0.0) == 0.0);
6760 7297
6761 // Count number of non-zero elements 7298 // Count number of non-zero elements
6762 octave_idx_type nel = (f_zero ? 0 : nr*nc - nz); 7299 octave_idx_type nel = (f_zero ? 0 : nr*nc - nz);
6763 for (octave_idx_type i = 0; i < nz; i++) 7300 for (octave_idx_type i = 0; i < nz; i++)
6803 SparseMatrix 7340 SparseMatrix
6804 SparseComplexMatrix::map (d_c_Mapper f) const 7341 SparseComplexMatrix::map (d_c_Mapper f) const
6805 { 7342 {
6806 octave_idx_type nr = rows (); 7343 octave_idx_type nr = rows ();
6807 octave_idx_type nc = cols (); 7344 octave_idx_type nc = cols ();
6808 octave_idx_type nz = nzmax (); 7345 octave_idx_type nz = nnz ();
6809 bool f_zero = (f(0.0) == 0.0); 7346 bool f_zero = (f(0.0) == 0.0);
6810 7347
6811 // Count number of non-zero elements 7348 // Count number of non-zero elements
6812 octave_idx_type nel = (f_zero ? 0 : nr*nc - nz); 7349 octave_idx_type nel = (f_zero ? 0 : nr*nc - nz);
6813 for (octave_idx_type i = 0; i < nz; i++) 7350 for (octave_idx_type i = 0; i < nz; i++)
6853 SparseBoolMatrix 7390 SparseBoolMatrix
6854 SparseComplexMatrix::map (b_c_Mapper f) const 7391 SparseComplexMatrix::map (b_c_Mapper f) const
6855 { 7392 {
6856 octave_idx_type nr = rows (); 7393 octave_idx_type nr = rows ();
6857 octave_idx_type nc = cols (); 7394 octave_idx_type nc = cols ();
6858 octave_idx_type nz = nzmax (); 7395 octave_idx_type nz = nnz ();
6859 bool f_zero = f(0.0); 7396 bool f_zero = f(0.0);
6860 7397
6861 // Count number of non-zero elements 7398 // Count number of non-zero elements
6862 octave_idx_type nel = (f_zero ? 0 : nr*nc - nz); 7399 octave_idx_type nel = (f_zero ? 0 : nr*nc - nz);
6863 for (octave_idx_type i = 0; i < nz; i++) 7400 for (octave_idx_type i = 0; i < nz; i++)
6908 } 7445 }
6909 7446
6910 bool 7447 bool
6911 SparseComplexMatrix::any_element_is_inf_or_nan (void) const 7448 SparseComplexMatrix::any_element_is_inf_or_nan (void) const
6912 { 7449 {
6913 octave_idx_type nel = nzmax (); 7450 octave_idx_type nel = nnz ();
6914 7451
6915 for (octave_idx_type i = 0; i < nel; i++) 7452 for (octave_idx_type i = 0; i < nel; i++)
6916 { 7453 {
6917 Complex val = data (i); 7454 Complex val = data (i);
6918 if (xisinf (val) || xisnan (val)) 7455 if (xisinf (val) || xisnan (val))
6925 // Return true if no elements have imaginary components. 7462 // Return true if no elements have imaginary components.
6926 7463
6927 bool 7464 bool
6928 SparseComplexMatrix::all_elements_are_real (void) const 7465 SparseComplexMatrix::all_elements_are_real (void) const
6929 { 7466 {
6930 octave_idx_type nel = nzmax (); 7467 octave_idx_type nel = nnz ();
6931 7468
6932 for (octave_idx_type i = 0; i < nel; i++) 7469 for (octave_idx_type i = 0; i < nel; i++)
6933 { 7470 {
6934 double ip = std::imag (data (i)); 7471 double ip = std::imag (data (i));
6935 7472
6945 // imaginary) values and return them in MAX_VAL and MIN_VAL. 7482 // imaginary) values and return them in MAX_VAL and MIN_VAL.
6946 7483
6947 bool 7484 bool
6948 SparseComplexMatrix::all_integers (double& max_val, double& min_val) const 7485 SparseComplexMatrix::all_integers (double& max_val, double& min_val) const
6949 { 7486 {
6950 octave_idx_type nel = nzmax (); 7487 octave_idx_type nel = nnz ();
6951 7488
6952 if (nel == 0) 7489 if (nel == 0)
6953 return false; 7490 return false;
6954 7491
6955 max_val = std::real(data (0)); 7492 max_val = std::real(data (0));
6982 } 7519 }
6983 7520
6984 bool 7521 bool
6985 SparseComplexMatrix::too_large_for_float (void) const 7522 SparseComplexMatrix::too_large_for_float (void) const
6986 { 7523 {
6987 octave_idx_type nel = nzmax (); 7524 octave_idx_type nel = nnz ();
6988 7525
6989 for (octave_idx_type i = 0; i < nel; i++) 7526 for (octave_idx_type i = 0; i < nel; i++)
6990 { 7527 {
6991 Complex val = data (i); 7528 Complex val = data (i);
6992 7529
7060 #undef COL_EXPR 7597 #undef COL_EXPR
7061 } 7598 }
7062 7599
7063 SparseMatrix SparseComplexMatrix::abs (void) const 7600 SparseMatrix SparseComplexMatrix::abs (void) const
7064 { 7601 {
7065 octave_idx_type nz = nzmax (); 7602 octave_idx_type nz = nnz ();
7066 octave_idx_type nc = cols (); 7603 octave_idx_type nc = cols ();
7067 7604
7068 SparseMatrix retval (rows(), nc, nz); 7605 SparseMatrix retval (rows(), nc, nz);
7069 7606
7070 for (octave_idx_type i = 0; i < nc + 1; i++) 7607 for (octave_idx_type i = 0; i < nc + 1; i++)
7235 } 7772 }
7236 7773
7237 SparseComplexMatrix 7774 SparseComplexMatrix
7238 operator * (const SparseComplexMatrix& m, const SparseMatrix& a) 7775 operator * (const SparseComplexMatrix& m, const SparseMatrix& a)
7239 { 7776 {
7240 SparseComplexMatrix tmp (a); 7777 SPARSE_SPARSE_MUL (SparseComplexMatrix, Complex, double);
7241 return m * tmp;
7242 } 7778 }
7243 7779
7244 SparseComplexMatrix 7780 SparseComplexMatrix
7245 operator * (const SparseMatrix& m, const SparseComplexMatrix& a) 7781 operator * (const SparseMatrix& m, const SparseComplexMatrix& a)
7246 { 7782 {
7247 SparseComplexMatrix tmp (m); 7783 SPARSE_SPARSE_MUL (SparseComplexMatrix, Complex, Complex);
7248 return tmp * a;
7249 } 7784 }
7250 7785
7251 SparseComplexMatrix 7786 SparseComplexMatrix
7252 operator * (const SparseComplexMatrix& m, const SparseComplexMatrix& a) 7787 operator * (const SparseComplexMatrix& m, const SparseComplexMatrix& a)
7253 { 7788 {
7254 #ifdef HAVE_SPARSE_BLAS 7789 SPARSE_SPARSE_MUL (SparseComplexMatrix, Complex, Complex);
7255 // XXX FIXME XXX Isn't there a sparse BLAS ??
7256 #else
7257 // Use Andy's sparse matrix multiply function
7258 SPARSE_SPARSE_MUL (SparseComplexMatrix, Complex);
7259 #endif
7260 } 7790 }
7261 7791
7262 ComplexMatrix 7792 ComplexMatrix
7263 operator * (const ComplexMatrix& m, const SparseMatrix& a) 7793 operator * (const ComplexMatrix& m, const SparseMatrix& a)
7264 { 7794 {
7265 SparseComplexMatrix tmp (a); 7795 FULL_SPARSE_MUL (ComplexMatrix, double, Complex (0.,0.));
7266 return m * tmp;
7267 } 7796 }
7268 7797
7269 ComplexMatrix 7798 ComplexMatrix
7270 operator * (const Matrix& m, const SparseComplexMatrix& a) 7799 operator * (const Matrix& m, const SparseComplexMatrix& a)
7271 { 7800 {
7272 ComplexMatrix tmp (m); 7801 FULL_SPARSE_MUL (ComplexMatrix, Complex, Complex (0.,0.));
7273 return tmp * a;
7274 } 7802 }
7275 7803
7276 ComplexMatrix 7804 ComplexMatrix
7277 operator * (const ComplexMatrix& m, const SparseComplexMatrix& a) 7805 operator * (const ComplexMatrix& m, const SparseComplexMatrix& a)
7278 { 7806 {
7279 #ifdef HAVE_SPARSE_BLAS 7807 FULL_SPARSE_MUL (ComplexMatrix, Complex, Complex (0.,0.));
7280 // XXX FIXME XXX Isn't there a sparse BLAS ??
7281 #else
7282 FULL_SPARSE_MUL (ComplexMatrix, Complex);
7283 #endif
7284 } 7808 }
7285 7809
7286 ComplexMatrix 7810 ComplexMatrix
7287 operator * (const SparseComplexMatrix& m, const Matrix& a) 7811 operator * (const SparseComplexMatrix& m, const Matrix& a)
7288 { 7812 {
7289 ComplexMatrix tmp (a); 7813 SPARSE_FULL_MUL (ComplexMatrix, double, Complex (0.,0.));
7290 return m * tmp;
7291 } 7814 }
7292 7815
7293 ComplexMatrix 7816 ComplexMatrix
7294 operator * (const SparseMatrix& m, const ComplexMatrix& a) 7817 operator * (const SparseMatrix& m, const ComplexMatrix& a)
7295 { 7818 {
7296 SparseComplexMatrix tmp (m); 7819 SPARSE_FULL_MUL (ComplexMatrix, Complex, Complex (0.,0.));
7297 return tmp * a;
7298 } 7820 }
7299 7821
7300 ComplexMatrix 7822 ComplexMatrix
7301 operator * (const SparseComplexMatrix& m, const ComplexMatrix& a) 7823 operator * (const SparseComplexMatrix& m, const ComplexMatrix& a)
7302 { 7824 {
7303 #ifdef HAVE_SPARSE_BLAS 7825 SPARSE_FULL_MUL (ComplexMatrix, Complex, Complex (0.,0.));
7304 // XXX FIXME XXX Isn't there a sparse BLAS ??
7305 #else
7306 SPARSE_FULL_MUL (ComplexMatrix, Complex);
7307 #endif
7308 } 7826 }
7309 7827
7310 // XXX FIXME XXX -- it would be nice to share code among the min/max 7828 // XXX FIXME XXX -- it would be nice to share code among the min/max
7311 // functions below. 7829 // functions below.
7312 7830
7355 octave_idx_type a_nc = a.cols (); 7873 octave_idx_type a_nc = a.cols ();
7356 7874
7357 octave_idx_type b_nr = b.rows (); 7875 octave_idx_type b_nr = b.rows ();
7358 octave_idx_type b_nc = b.cols (); 7876 octave_idx_type b_nc = b.cols ();
7359 7877
7360 if (a_nr == 0 || b_nc == 0 || a.nzmax () == 0 || b.nzmax () == 0) 7878 if (a_nr == 0 || b_nc == 0 || a.nnz () == 0 || b.nnz () == 0)
7361 return SparseComplexMatrix (a_nr, a_nc); 7879 return SparseComplexMatrix (a_nr, a_nc);
7362 7880
7363 if (a_nr != b_nr || a_nc != b_nc) 7881 if (a_nr != b_nr || a_nc != b_nc)
7364 gripe_nonconformant ("min", a_nr, a_nc, b_nr, b_nc); 7882 gripe_nonconformant ("min", a_nr, a_nc, b_nr, b_nc);
7365 else 7883 else
7366 { 7884 {
7367 r = SparseComplexMatrix (a_nr, a_nc, (a.nzmax () + b.nzmax ())); 7885 r = SparseComplexMatrix (a_nr, a_nc, (a.nnz () + b.nnz ()));
7368 7886
7369 octave_idx_type jx = 0; 7887 octave_idx_type jx = 0;
7370 r.cidx (0) = 0; 7888 r.cidx (0) = 0;
7371 for (octave_idx_type i = 0 ; i < a_nc ; i++) 7889 for (octave_idx_type i = 0 ; i < a_nc ; i++)
7372 { 7890 {
7477 octave_idx_type b_nr = b.rows (); 7995 octave_idx_type b_nr = b.rows ();
7478 octave_idx_type b_nc = b.cols (); 7996 octave_idx_type b_nc = b.cols ();
7479 7997
7480 if (a_nr == 0 || b_nc == 0) 7998 if (a_nr == 0 || b_nc == 0)
7481 return SparseComplexMatrix (a_nr, a_nc); 7999 return SparseComplexMatrix (a_nr, a_nc);
7482 if (a.nzmax () == 0) 8000 if (a.nnz () == 0)
7483 return SparseComplexMatrix (b); 8001 return SparseComplexMatrix (b);
7484 if (b.nzmax () == 0) 8002 if (b.nnz () == 0)
7485 return SparseComplexMatrix (a); 8003 return SparseComplexMatrix (a);
7486 8004
7487 if (a_nr != b_nr || a_nc != b_nc) 8005 if (a_nr != b_nr || a_nc != b_nc)
7488 gripe_nonconformant ("min", a_nr, a_nc, b_nr, b_nc); 8006 gripe_nonconformant ("min", a_nr, a_nc, b_nr, b_nc);
7489 else 8007 else
7490 { 8008 {
7491 r = SparseComplexMatrix (a_nr, a_nc, (a.nzmax () + b.nzmax ())); 8009 r = SparseComplexMatrix (a_nr, a_nc, (a.nnz () + b.nnz ()));
7492 8010
7493 octave_idx_type jx = 0; 8011 octave_idx_type jx = 0;
7494 r.cidx (0) = 0; 8012 r.cidx (0) = 0;
7495 for (octave_idx_type i = 0 ; i < a_nc ; i++) 8013 for (octave_idx_type i = 0 ; i < a_nc ; i++)
7496 { 8014 {