Mercurial > hg > octave-nkf
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 { |