comparison liboctave/dMatrix.cc @ 5785:6b9cec830d72

[project @ 2006-05-03 19:32:46 by dbateman]
author dbateman
date Wed, 03 May 2006 19:32:48 +0000
parents ace8d8d26933
children c038c2947ee1
comparison
equal deleted inserted replaced
5784:70f7659d0fb9 5785:6b9cec830d72
105 F77_RET_T 105 F77_RET_T
106 F77_FUNC (dgelss, DGELSS) (const octave_idx_type&, const octave_idx_type&, const octave_idx_type&, 106 F77_FUNC (dgelss, DGELSS) (const octave_idx_type&, const octave_idx_type&, const octave_idx_type&,
107 double*, const octave_idx_type&, double*, 107 double*, const octave_idx_type&, double*,
108 const octave_idx_type&, double*, double&, octave_idx_type&, 108 const octave_idx_type&, double*, double&, octave_idx_type&,
109 double*, const octave_idx_type&, octave_idx_type&); 109 double*, const octave_idx_type&, octave_idx_type&);
110
111 F77_RET_T
112 F77_FUNC (dpotrf, DPOTRF) (F77_CONST_CHAR_ARG_DECL, const octave_idx_type&,
113 double *, const octave_idx_type&,
114 octave_idx_type& F77_CHAR_ARG_LEN_DECL);
115
116 F77_RET_T
117 F77_FUNC (dpocon, DPOCON) (F77_CONST_CHAR_ARG_DECL, const octave_idx_type&,
118 double*, const octave_idx_type&, const double&,
119 double&, double*, octave_idx_type*,
120 octave_idx_type& F77_CHAR_ARG_LEN_DECL);
121 F77_RET_T
122 F77_FUNC (dpotrs, DPOTRS) (F77_CONST_CHAR_ARG_DECL, const octave_idx_type&,
123 const octave_idx_type&, const double*,
124 const octave_idx_type&, double*,
125 const octave_idx_type&, octave_idx_type&
126 F77_CHAR_ARG_LEN_DECL);
127
128 F77_RET_T
129 F77_FUNC (dtrcon, DTRCON) (F77_CONST_CHAR_ARG_DECL, F77_CONST_CHAR_ARG_DECL,
130 F77_CONST_CHAR_ARG_DECL, const octave_idx_type&,
131 const double*, const octave_idx_type&, double&,
132 double*, octave_idx_type*, octave_idx_type&
133 F77_CHAR_ARG_LEN_DECL
134 F77_CHAR_ARG_LEN_DECL
135 F77_CHAR_ARG_LEN_DECL);
136 F77_RET_T
137 F77_FUNC (dtrtrs, DTRTRS) (F77_CONST_CHAR_ARG_DECL, F77_CONST_CHAR_ARG_DECL,
138 F77_CONST_CHAR_ARG_DECL, const octave_idx_type&,
139 const octave_idx_type&, const double*,
140 const octave_idx_type&, double*,
141 const octave_idx_type&, octave_idx_type&
142 F77_CHAR_ARG_LEN_DECL
143 F77_CHAR_ARG_LEN_DECL
144 F77_CHAR_ARG_LEN_DECL);
110 145
111 // Note that the original complex fft routines were not written for 146 // Note that the original complex fft routines were not written for
112 // double complex arguments. They have been modified by adding an 147 // double complex arguments. They have been modified by adding an
113 // implicit double precision (a-h,o-z) statement at the beginning of 148 // implicit double precision (a-h,o-z) statement at the beginning of
114 // each subroutine. 149 // each subroutine.
1152 1187
1153 return retval; 1188 return retval;
1154 } 1189 }
1155 1190
1156 Matrix 1191 Matrix
1157 Matrix::solve (const Matrix& b) const 1192 Matrix::utsolve (MatrixType &mattype, const Matrix& b, octave_idx_type& info,
1158 { 1193 double& rcond, solve_singularity_handler sing_handler,
1159 octave_idx_type info; 1194 bool calc_cond) const
1160 double rcond; 1195 {
1161 return solve (b, info, rcond, 0); 1196 Matrix retval;
1162 } 1197
1163 1198 octave_idx_type nr = rows ();
1164 Matrix 1199 octave_idx_type nc = cols ();
1165 Matrix::solve (const Matrix& b, octave_idx_type& info) const 1200
1166 { 1201 if (nr == 0 || nc == 0 || nr != b.rows ())
1167 double rcond; 1202 (*current_liboctave_error_handler)
1168 return solve (b, info, rcond, 0); 1203 ("matrix dimension mismatch solution of linear equations");
1169 } 1204 else
1170 1205 {
1171 Matrix 1206 volatile int typ = mattype.type ();
1172 Matrix::solve (const Matrix& b, octave_idx_type& info, double& rcond) const 1207
1173 { 1208 if (typ == MatrixType::Permuted_Upper ||
1174 return solve (b, info, rcond, 0); 1209 typ == MatrixType::Upper)
1175 } 1210 {
1176 1211 octave_idx_type b_nc = b.cols ();
1177 Matrix 1212 rcond = 1.;
1178 Matrix::solve (const Matrix& b, octave_idx_type& info, double& rcond, 1213 info = 0;
1179 solve_singularity_handler sing_handler) const 1214
1215 if (typ == MatrixType::Permuted_Upper)
1216 {
1217 (*current_liboctave_error_handler)
1218 ("Permuted triangular matrix not implemented");
1219 }
1220 else
1221 {
1222 const double *tmp_data = fortran_vec ();
1223
1224 if (calc_cond)
1225 {
1226 char norm = '1';
1227 char uplo = 'U';
1228 char dia = 'N';
1229
1230 Array<double> z (3 * nc);
1231 double *pz = z.fortran_vec ();
1232 Array<octave_idx_type> iz (nc);
1233 octave_idx_type *piz = iz.fortran_vec ();
1234
1235 F77_XFCN (dtrcon, DTRCON, (F77_CONST_CHAR_ARG2 (&norm, 1),
1236 F77_CONST_CHAR_ARG2 (&uplo, 1),
1237 F77_CONST_CHAR_ARG2 (&dia, 1),
1238 nr, tmp_data, nr, rcond,
1239 pz, piz, info
1240 F77_CHAR_ARG_LEN (1)
1241 F77_CHAR_ARG_LEN (1)
1242 F77_CHAR_ARG_LEN (1)));
1243
1244 if (f77_exception_encountered)
1245 (*current_liboctave_error_handler)
1246 ("unrecoverable error in dtrcon");
1247
1248 if (info != 0)
1249 info = -2;
1250
1251 volatile double rcond_plus_one = rcond + 1.0;
1252
1253 if (rcond_plus_one == 1.0 || xisnan (rcond))
1254 {
1255 info = -2;
1256
1257 if (sing_handler)
1258 sing_handler (rcond);
1259 else
1260 (*current_liboctave_error_handler)
1261 ("matrix singular to machine precision, rcond = %g",
1262 rcond);
1263 }
1264 }
1265
1266 if (info == 0)
1267 {
1268 retval = b;
1269 double *result = retval.fortran_vec ();
1270
1271 char uplo = 'U';
1272 char trans = 'N';
1273 char dia = 'N';
1274
1275 F77_XFCN (dtrtrs, DTRTRS, (F77_CONST_CHAR_ARG2 (&uplo, 1),
1276 F77_CONST_CHAR_ARG2 (&trans, 1),
1277 F77_CONST_CHAR_ARG2 (&dia, 1),
1278 nr, b_nc, tmp_data, nr,
1279 result, nr, info
1280 F77_CHAR_ARG_LEN (1)
1281 F77_CHAR_ARG_LEN (1)
1282 F77_CHAR_ARG_LEN (1)));
1283
1284 if (f77_exception_encountered)
1285 (*current_liboctave_error_handler)
1286 ("unrecoverable error in dtrtrs");
1287 }
1288 }
1289 }
1290 else
1291 (*current_liboctave_error_handler) ("incorrect matrix type");
1292 }
1293
1294 return retval;
1295 }
1296
1297 Matrix
1298 Matrix::ltsolve (MatrixType &mattype, const Matrix& b, octave_idx_type& info,
1299 double& rcond, solve_singularity_handler sing_handler,
1300 bool calc_cond) const
1301 {
1302 Matrix retval;
1303
1304 octave_idx_type nr = rows ();
1305 octave_idx_type nc = cols ();
1306
1307 if (nr == 0 || nc == 0 || nr != b.rows ())
1308 (*current_liboctave_error_handler)
1309 ("matrix dimension mismatch solution of linear equations");
1310 else
1311 {
1312 volatile int typ = mattype.type ();
1313
1314 if (typ == MatrixType::Permuted_Lower ||
1315 typ == MatrixType::Lower)
1316 {
1317 octave_idx_type b_nc = b.cols ();
1318 rcond = 1.;
1319 info = 0;
1320
1321 if (typ == MatrixType::Permuted_Lower)
1322 {
1323 (*current_liboctave_error_handler)
1324 ("Permuted triangular matrix not implemented");
1325 }
1326 else
1327 {
1328 const double *tmp_data = fortran_vec ();
1329
1330 if (calc_cond)
1331 {
1332 char norm = '1';
1333 char uplo = 'L';
1334 char dia = 'N';
1335
1336 Array<double> z (3 * nc);
1337 double *pz = z.fortran_vec ();
1338 Array<octave_idx_type> iz (nc);
1339 octave_idx_type *piz = iz.fortran_vec ();
1340
1341 F77_XFCN (dtrcon, DTRCON, (F77_CONST_CHAR_ARG2 (&norm, 1),
1342 F77_CONST_CHAR_ARG2 (&uplo, 1),
1343 F77_CONST_CHAR_ARG2 (&dia, 1),
1344 nr, tmp_data, nr, rcond,
1345 pz, piz, info
1346 F77_CHAR_ARG_LEN (1)
1347 F77_CHAR_ARG_LEN (1)
1348 F77_CHAR_ARG_LEN (1)));
1349
1350 if (f77_exception_encountered)
1351 (*current_liboctave_error_handler)
1352 ("unrecoverable error in dtrcon");
1353
1354 if (info != 0)
1355 info = -2;
1356
1357 volatile double rcond_plus_one = rcond + 1.0;
1358
1359 if (rcond_plus_one == 1.0 || xisnan (rcond))
1360 {
1361 info = -2;
1362
1363 if (sing_handler)
1364 sing_handler (rcond);
1365 else
1366 (*current_liboctave_error_handler)
1367 ("matrix singular to machine precision, rcond = %g",
1368 rcond);
1369 }
1370 }
1371
1372 if (info == 0)
1373 {
1374 retval = b;
1375 double *result = retval.fortran_vec ();
1376
1377 char uplo = 'L';
1378 char trans = 'N';
1379 char dia = 'N';
1380
1381 F77_XFCN (dtrtrs, DTRTRS, (F77_CONST_CHAR_ARG2 (&uplo, 1),
1382 F77_CONST_CHAR_ARG2 (&trans, 1),
1383 F77_CONST_CHAR_ARG2 (&dia, 1),
1384 nr, b_nc, tmp_data, nr,
1385 result, nr, info
1386 F77_CHAR_ARG_LEN (1)
1387 F77_CHAR_ARG_LEN (1)
1388 F77_CHAR_ARG_LEN (1)));
1389
1390 if (f77_exception_encountered)
1391 (*current_liboctave_error_handler)
1392 ("unrecoverable error in dtrtrs");
1393 }
1394 }
1395 }
1396 else
1397 (*current_liboctave_error_handler) ("incorrect matrix type");
1398 }
1399
1400 return retval;
1401 }
1402
1403 Matrix
1404 Matrix::fsolve (MatrixType &mattype, const Matrix& b, octave_idx_type& info,
1405 double& rcond, solve_singularity_handler sing_handler,
1406 bool calc_cond) const
1180 { 1407 {
1181 Matrix retval; 1408 Matrix retval;
1182 1409
1183 octave_idx_type nr = rows (); 1410 octave_idx_type nr = rows ();
1184 octave_idx_type nc = cols (); 1411 octave_idx_type nc = cols ();
1186 if (nr == 0 || nc == 0 || nr != nc || nr != b.rows ()) 1413 if (nr == 0 || nc == 0 || nr != nc || nr != b.rows ())
1187 (*current_liboctave_error_handler) 1414 (*current_liboctave_error_handler)
1188 ("matrix dimension mismatch solution of linear equations"); 1415 ("matrix dimension mismatch solution of linear equations");
1189 else 1416 else
1190 { 1417 {
1191 info = 0; 1418 volatile int typ = mattype.type ();
1192 1419
1193 Array<octave_idx_type> ipvt (nr); 1420 // Calculate the norm of the matrix, for later use.
1194 octave_idx_type *pipvt = ipvt.fortran_vec (); 1421 double anorm = -1.;
1195 1422
1196 Matrix atmp = *this; 1423 if (typ == MatrixType::Hermitian)
1197 double *tmp_data = atmp.fortran_vec ();
1198
1199 Array<double> z (4 * nc);
1200 double *pz = z.fortran_vec ();
1201 Array<octave_idx_type> iz (nc);
1202 octave_idx_type *piz = iz.fortran_vec ();
1203
1204 // Calculate the norm of the matrix, for later use.
1205 double anorm = atmp.abs().sum().row(static_cast<octave_idx_type>(0)).max();
1206
1207 F77_XFCN (dgetrf, DGETRF, (nr, nr, tmp_data, nr, pipvt, info));
1208
1209 if (f77_exception_encountered)
1210 (*current_liboctave_error_handler) ("unrecoverable error in dgetrf");
1211 else
1212 { 1424 {
1213 // Throw-away extra info LAPACK gives so as to not change output. 1425 info = 0;
1214 rcond = 0.0; 1426 char job = 'L';
1215 if (info != 0) 1427 Matrix atmp = *this;
1428 double *tmp_data = atmp.fortran_vec ();
1429 anorm = atmp.abs().sum().row(static_cast<octave_idx_type>(0)).max();
1430
1431 F77_XFCN (dpotrf, DPOTRF, (F77_CONST_CHAR_ARG2 (&job, 1), nr,
1432 tmp_data, nr, info
1433 F77_CHAR_ARG_LEN (1)));
1434
1435 if (f77_exception_encountered)
1436 (*current_liboctave_error_handler)
1437 ("unrecoverable error in dpotrf");
1438 else
1216 { 1439 {
1217 info = -2; 1440 // Throw-away extra info LAPACK gives so as to not change output.
1218 1441 rcond = 0.0;
1219 if (sing_handler) 1442 if (info != 0)
1220 sing_handler (rcond); 1443 {
1221 else 1444 info = -2;
1222 (*current_liboctave_error_handler) 1445
1223 ("matrix singular to machine precision"); 1446 mattype.mark_as_unsymmetric ();
1224 1447 typ = MatrixType::Full;
1225 } 1448 }
1226 else 1449 else
1450 {
1451 if (calc_cond)
1452 {
1453 Array<double> z (3 * nc);
1454 double *pz = z.fortran_vec ();
1455 Array<octave_idx_type> iz (nc);
1456 octave_idx_type *piz = iz.fortran_vec ();
1457
1458 F77_XFCN (dpocon, DPOCON, (F77_CONST_CHAR_ARG2 (&job, 1),
1459 nr, tmp_data, nr, anorm,
1460 rcond, pz, piz, info
1461 F77_CHAR_ARG_LEN (1)));
1462
1463 if (f77_exception_encountered)
1464 (*current_liboctave_error_handler)
1465 ("unrecoverable error in dpocon");
1466
1467 if (info != 0)
1468 info = -2;
1469
1470 volatile double rcond_plus_one = rcond + 1.0;
1471
1472 if (rcond_plus_one == 1.0 || xisnan (rcond))
1473 {
1474 info = -2;
1475
1476 if (sing_handler)
1477 sing_handler (rcond);
1478 else
1479 (*current_liboctave_error_handler)
1480 ("matrix singular to machine precision, rcond = %g",
1481 rcond);
1482 }
1483 }
1484
1485 if (info == 0)
1486 {
1487 retval = b;
1488 double *result = retval.fortran_vec ();
1489
1490 octave_idx_type b_nc = b.cols ();
1491
1492 F77_XFCN (dpotrs, DPOTRS, (F77_CONST_CHAR_ARG2 (&job, 1),
1493 nr, b_nc, tmp_data, nr,
1494 result, b.rows(), info
1495 F77_CHAR_ARG_LEN (1)));
1496
1497 if (f77_exception_encountered)
1498 (*current_liboctave_error_handler)
1499 ("unrecoverable error in dpotrs");
1500 }
1501 else
1502 {
1503 mattype.mark_as_unsymmetric ();
1504 typ = MatrixType::Full;
1505 }
1506 }
1507 }
1508 }
1509
1510 if (typ == MatrixType::Full)
1511 {
1512 info = 0;
1513
1514 Array<octave_idx_type> ipvt (nr);
1515 octave_idx_type *pipvt = ipvt.fortran_vec ();
1516
1517 Matrix atmp = *this;
1518 double *tmp_data = atmp.fortran_vec ();
1519 if(anorm < 0.)
1520 anorm = atmp.abs().sum().row(static_cast<octave_idx_type>(0)).max();
1521
1522 Array<double> z (4 * nc);
1523 double *pz = z.fortran_vec ();
1524 Array<octave_idx_type> iz (nc);
1525 octave_idx_type *piz = iz.fortran_vec ();
1526
1527 F77_XFCN (dgetrf, DGETRF, (nr, nr, tmp_data, nr, pipvt, info));
1528
1529 if (f77_exception_encountered)
1530 (*current_liboctave_error_handler)
1531 ("unrecoverable error in dgetrf");
1532 else
1227 { 1533 {
1228 // Now calculate the condition number for non-singular matrix. 1534 // Throw-away extra info LAPACK gives so as to not change output.
1229 char job = '1'; 1535 rcond = 0.0;
1230 F77_XFCN (dgecon, DGECON, (F77_CONST_CHAR_ARG2 (&job, 1),
1231 nc, tmp_data, nr, anorm,
1232 rcond, pz, piz, info
1233 F77_CHAR_ARG_LEN (1)));
1234
1235 if (f77_exception_encountered)
1236 (*current_liboctave_error_handler)
1237 ("unrecoverable error in dgecon");
1238
1239 if (info != 0) 1536 if (info != 0)
1240 info = -2;
1241
1242 volatile double rcond_plus_one = rcond + 1.0;
1243
1244 if (rcond_plus_one == 1.0 || xisnan (rcond))
1245 { 1537 {
1246 info = -2; 1538 info = -2;
1247 1539
1248 if (sing_handler) 1540 if (sing_handler)
1249 sing_handler (rcond); 1541 sing_handler (rcond);
1250 else 1542 else
1251 (*current_liboctave_error_handler) 1543 (*current_liboctave_error_handler)
1252 ("matrix singular to machine precision, rcond = %g", 1544 ("matrix singular to machine precision");
1253 rcond); 1545
1546 mattype.mark_as_rectangular ();
1254 } 1547 }
1255 else 1548 else
1256 { 1549 {
1257 retval = b; 1550 if (calc_cond)
1258 double *result = retval.fortran_vec (); 1551 {
1259 1552 // Now calculate the condition number for
1260 octave_idx_type b_nc = b.cols (); 1553 // non-singular matrix.
1261 1554 char job = '1';
1262 job = 'N'; 1555 F77_XFCN (dgecon, DGECON, (F77_CONST_CHAR_ARG2 (&job, 1),
1263 F77_XFCN (dgetrs, DGETRS, (F77_CONST_CHAR_ARG2 (&job, 1), 1556 nc, tmp_data, nr, anorm,
1264 nr, b_nc, tmp_data, nr, 1557 rcond, pz, piz, info
1265 pipvt, result, b.rows(), info 1558 F77_CHAR_ARG_LEN (1)));
1266 F77_CHAR_ARG_LEN (1))); 1559
1560 if (f77_exception_encountered)
1561 (*current_liboctave_error_handler)
1562 ("unrecoverable error in dgecon");
1563
1564 if (info != 0)
1565 info = -2;
1566
1567 volatile double rcond_plus_one = rcond + 1.0;
1568
1569 if (rcond_plus_one == 1.0 || xisnan (rcond))
1570 {
1571 info = -2;
1572
1573 if (sing_handler)
1574 sing_handler (rcond);
1575 else
1576 (*current_liboctave_error_handler)
1577 ("matrix singular to machine precision, rcond = %g",
1578 rcond);
1579 }
1580 }
1581
1582 if (info == 0)
1583 {
1584 retval = b;
1585 double *result = retval.fortran_vec ();
1586
1587 octave_idx_type b_nc = b.cols ();
1588
1589 char job = 'N';
1590 F77_XFCN (dgetrs, DGETRS, (F77_CONST_CHAR_ARG2 (&job, 1),
1591 nr, b_nc, tmp_data, nr,
1592 pipvt, result, b.rows(), info
1593 F77_CHAR_ARG_LEN (1)));
1267 1594
1268 if (f77_exception_encountered) 1595 if (f77_exception_encountered)
1269 (*current_liboctave_error_handler) 1596 (*current_liboctave_error_handler)
1270 ("unrecoverable error in dgetrs"); 1597 ("unrecoverable error in dgetrs");
1598 }
1599 else
1600 mattype.mark_as_rectangular ();
1271 } 1601 }
1272 } 1602 }
1273 } 1603 }
1274 } 1604 else if (typ != MatrixType::Hermitian)
1275 1605 (*current_liboctave_error_handler) ("incorrect matrix type");
1276 return retval; 1606 }
1607
1608 return retval;
1609 }
1610
1611 Matrix
1612 Matrix::solve (MatrixType &typ, const Matrix& b) const
1613 {
1614 octave_idx_type info;
1615 double rcond;
1616 return solve (typ, b, info, rcond, 0);
1617 }
1618
1619 Matrix
1620 Matrix::solve (MatrixType &typ, const Matrix& b, octave_idx_type& info,
1621 double& rcond) const
1622 {
1623 return solve (typ, b, info, rcond, 0);
1624 }
1625
1626 Matrix
1627 Matrix::solve (MatrixType &mattype, const Matrix& b, octave_idx_type& info,
1628 double& rcond, solve_singularity_handler sing_handler,
1629 bool singular_fallback) const
1630 {
1631 Matrix retval;
1632 int typ = mattype.type ();
1633
1634 if (typ == MatrixType::Unknown)
1635 typ = mattype.type (*this);
1636
1637 // Only calculate the condition number for LU/Cholesky
1638 if (typ == MatrixType::Upper || typ == MatrixType::Permuted_Upper)
1639 retval = utsolve (mattype, b, info, rcond, sing_handler, false);
1640 else if (typ == MatrixType::Lower || typ == MatrixType::Permuted_Lower)
1641 retval = ltsolve (mattype, b, info, rcond, sing_handler, false);
1642 else if (typ == MatrixType::Full || typ == MatrixType::Hermitian)
1643 retval = fsolve (mattype, b, info, rcond, sing_handler, true);
1644 else if (typ != MatrixType::Rectangular)
1645 {
1646 (*current_liboctave_error_handler) ("unknown matrix type");
1647 return Matrix ();
1648 }
1649
1650 // Rectangular or one of the above solvers flags a singular matrix
1651 if (singular_fallback && mattype.type () == MatrixType::Rectangular)
1652 {
1653 octave_idx_type rank;
1654 retval = lssolve (b, info, rank);
1655 }
1656
1657 return retval;
1658 }
1659
1660 ComplexMatrix
1661 Matrix::solve (MatrixType &typ, const ComplexMatrix& b) const
1662 {
1663 ComplexMatrix tmp (*this);
1664 return tmp.solve (typ, b);
1665 }
1666
1667 ComplexMatrix
1668 Matrix::solve (MatrixType &typ, const ComplexMatrix& b,
1669 octave_idx_type& info) const
1670 {
1671 ComplexMatrix tmp (*this);
1672 return tmp.solve (typ, b, info);
1673 }
1674
1675 ComplexMatrix
1676 Matrix::solve (MatrixType &typ, const ComplexMatrix& b, octave_idx_type& info,
1677 double& rcond) const
1678 {
1679 ComplexMatrix tmp (*this);
1680 return tmp.solve (typ, b, info, rcond);
1681 }
1682
1683 ComplexMatrix
1684 Matrix::solve (MatrixType &typ, const ComplexMatrix& b, octave_idx_type& info,
1685 double& rcond, solve_singularity_handler sing_handler,
1686 bool singular_fallback) const
1687 {
1688 ComplexMatrix tmp (*this);
1689 return tmp.solve (typ, b, info, rcond, sing_handler, singular_fallback);
1690 }
1691
1692 ColumnVector
1693 Matrix::solve (MatrixType &typ, const ColumnVector& b) const
1694 {
1695 octave_idx_type info; double rcond;
1696 return solve (typ, b, info, rcond);
1697 }
1698
1699 ColumnVector
1700 Matrix::solve (MatrixType &typ, const ColumnVector& b,
1701 octave_idx_type& info) const
1702 {
1703 double rcond;
1704 return solve (typ, b, info, rcond);
1705 }
1706
1707 ColumnVector
1708 Matrix::solve (MatrixType &typ, const ColumnVector& b, octave_idx_type& info,
1709 double& rcond) const
1710 {
1711 return solve (typ, b, info, rcond, 0);
1712 }
1713
1714 ColumnVector
1715 Matrix::solve (MatrixType &typ, const ColumnVector& b, octave_idx_type& info,
1716 double& rcond, solve_singularity_handler sing_handler) const
1717 {
1718 Matrix tmp (b);
1719 return solve (typ, tmp, info, rcond, sing_handler).column(static_cast<octave_idx_type> (0));
1720 }
1721
1722 ComplexColumnVector
1723 Matrix::solve (MatrixType &typ, const ComplexColumnVector& b) const
1724 {
1725 ComplexMatrix tmp (*this);
1726 return tmp.solve (typ, b);
1727 }
1728
1729 ComplexColumnVector
1730 Matrix::solve (MatrixType &typ, const ComplexColumnVector& b,
1731 octave_idx_type& info) const
1732 {
1733 ComplexMatrix tmp (*this);
1734 return tmp.solve (typ, b, info);
1735 }
1736
1737 ComplexColumnVector
1738 Matrix::solve (MatrixType &typ, const ComplexColumnVector& b,
1739 octave_idx_type& info, double& rcond) const
1740 {
1741 ComplexMatrix tmp (*this);
1742 return tmp.solve (typ, b, info, rcond);
1743 }
1744
1745 ComplexColumnVector
1746 Matrix::solve (MatrixType &typ, const ComplexColumnVector& b,
1747 octave_idx_type& info, double& rcond,
1748 solve_singularity_handler sing_handler) const
1749 {
1750 ComplexMatrix tmp (*this);
1751 return tmp.solve(typ, b, info, rcond, sing_handler);
1752 }
1753
1754 Matrix
1755 Matrix::solve (const Matrix& b) const
1756 {
1757 octave_idx_type info;
1758 double rcond;
1759 return solve (b, info, rcond, 0);
1760 }
1761
1762 Matrix
1763 Matrix::solve (const Matrix& b, octave_idx_type& info) const
1764 {
1765 double rcond;
1766 return solve (b, info, rcond, 0);
1767 }
1768
1769 Matrix
1770 Matrix::solve (const Matrix& b, octave_idx_type& info, double& rcond) const
1771 {
1772 return solve (b, info, rcond, 0);
1773 }
1774
1775 Matrix
1776 Matrix::solve (const Matrix& b, octave_idx_type& info,
1777 double& rcond, solve_singularity_handler sing_handler) const
1778 {
1779 MatrixType mattype (*this);
1780 return solve (mattype, b, info, rcond, sing_handler);
1277 } 1781 }
1278 1782
1279 ComplexMatrix 1783 ComplexMatrix
1280 Matrix::solve (const ComplexMatrix& b) const 1784 Matrix::solve (const ComplexMatrix& b) const
1281 { 1785 {
1327 1831
1328 ColumnVector 1832 ColumnVector
1329 Matrix::solve (const ColumnVector& b, octave_idx_type& info, double& rcond, 1833 Matrix::solve (const ColumnVector& b, octave_idx_type& info, double& rcond,
1330 solve_singularity_handler sing_handler) const 1834 solve_singularity_handler sing_handler) const
1331 { 1835 {
1332 ColumnVector retval; 1836 MatrixType mattype (*this);
1333 1837 return solve (mattype, b, info, rcond, sing_handler);
1334 octave_idx_type nr = rows ();
1335 octave_idx_type nc = cols ();
1336
1337 if (nr == 0 || nc == 0 || nr != nc || nr != b.length ())
1338 (*current_liboctave_error_handler)
1339 ("matrix dimension mismatch solution of linear equations");
1340 else
1341 {
1342 info = 0;
1343
1344 Array<octave_idx_type> ipvt (nr);
1345 octave_idx_type *pipvt = ipvt.fortran_vec ();
1346
1347 Matrix atmp = *this;
1348 double *tmp_data = atmp.fortran_vec ();
1349
1350 Array<double> z (4 * nc);
1351 double *pz = z.fortran_vec ();
1352 Array<octave_idx_type> iz (nc);
1353 octave_idx_type *piz = iz.fortran_vec ();
1354
1355 // Calculate the norm of the matrix, for later use.
1356 double anorm = atmp.abs().sum().row(static_cast<octave_idx_type>(0)).max();
1357
1358 F77_XFCN (dgetrf, DGETRF, (nr, nr, tmp_data, nr, pipvt, info));
1359
1360 if (f77_exception_encountered)
1361 (*current_liboctave_error_handler) ("unrecoverable error in dgetrf");
1362 else
1363 {
1364 // Throw-away extra info LAPACK gives so as to not change output.
1365 rcond = 0.0;
1366 if (info > 0)
1367 {
1368 info = -2;
1369
1370 if (sing_handler)
1371 sing_handler (rcond);
1372 else
1373 (*current_liboctave_error_handler)
1374 ("matrix singular to machine precision");
1375
1376 }
1377 else
1378 {
1379 // Now calculate the condition number for non-singular matrix.
1380 char job = '1';
1381 F77_XFCN (dgecon, DGECON, (F77_CONST_CHAR_ARG2 (&job, 1),
1382 nc, tmp_data, nr, anorm,
1383 rcond, pz, piz, info
1384 F77_CHAR_ARG_LEN (1)));
1385
1386 if (f77_exception_encountered)
1387 (*current_liboctave_error_handler)
1388 ("unrecoverable error in dgecon");
1389
1390 if (info != 0)
1391 info = -2;
1392
1393 volatile double rcond_plus_one = rcond + 1.0;
1394
1395 if (rcond_plus_one == 1.0 || xisnan (rcond))
1396 {
1397 info = -2;
1398
1399 if (sing_handler)
1400 sing_handler (rcond);
1401 else
1402 (*current_liboctave_error_handler)
1403 ("matrix singular to machine precision, rcond = %g",
1404 rcond);
1405 }
1406 else
1407 {
1408 retval = b;
1409 double *result = retval.fortran_vec ();
1410
1411 job = 'N';
1412 F77_XFCN (dgetrs, DGETRS, (F77_CONST_CHAR_ARG2 (&job, 1),
1413 nr, 1, tmp_data, nr, pipvt,
1414 result, b.length(), info
1415 F77_CHAR_ARG_LEN (1)));
1416
1417 if (f77_exception_encountered)
1418 (*current_liboctave_error_handler)
1419 ("unrecoverable error in dgetrs");
1420 }
1421 }
1422 }
1423 }
1424
1425 return retval;
1426 } 1838 }
1427 1839
1428 ComplexColumnVector 1840 ComplexColumnVector
1429 Matrix::solve (const ComplexColumnVector& b) const 1841 Matrix::solve (const ComplexColumnVector& b) const
1430 { 1842 {