947 typedef Teuchos::SerialDenseMatrix<int,Scalar>
mat_type;
950 typedef Teuchos::ScalarTraits<scalar_type> STS;
951 typedef Teuchos::ScalarTraits<magnitude_type> STM;
952 typedef Teuchos::BLAS<int, scalar_type> blas_type;
953 typedef Teuchos::LAPACK<int, scalar_type> lapack_type;
972 defaultRobustness_ (defaultRobustness)
992 return updateColumnGivens (problem.
H, problem.
R, problem.
y, problem.
z,
1015 return updateColumnsGivens (problem.
H, problem.
R, problem.
y, problem.
z,
1037 solveGivens (problem.
y, problem.
R, problem.
z, curCol);
1044 std::pair<int, bool>
1091 std::pair<int, bool>
1098 TEUCHOS_TEST_FOR_EXCEPTION(X.numRows() != B.numRows(), std::invalid_argument,
1099 "The output X and right-hand side B have different "
1100 "numbers of rows. X has " << X.numRows() <<
" rows"
1101 ", and B has " << B.numRows() <<
" rows.");
1106 TEUCHOS_TEST_FOR_EXCEPTION(X.numCols() > B.numCols(), std::invalid_argument,
1107 "The output X has more columns than the "
1108 "right-hand side B. X has " << X.numCols()
1109 <<
" columns and B has " << B.numCols()
1112 mat_type B_view (Teuchos::View, B, B.numRows(), X.numCols());
1127 std::pair<int, bool>
1142 std::pair<int, bool>
1148 using Teuchos::Array;
1149 using Teuchos::Copy;
1150 using Teuchos::LEFT_SIDE;
1151 using Teuchos::RIGHT_SIDE;
1154 const int M = R.numRows();
1155 const int N = R.numCols();
1156 TEUCHOS_TEST_FOR_EXCEPTION(M < N, std::invalid_argument,
1157 "The input matrix R has fewer columns than rows. "
1158 "R is " << M <<
" x " << N <<
".");
1160 mat_type R_view (Teuchos::View, R, N, N);
1162 if (side == LEFT_SIDE) {
1163 TEUCHOS_TEST_FOR_EXCEPTION(X.numRows() < N, std::invalid_argument,
1164 "The input/output matrix X has only "
1165 << X.numRows() <<
" rows, but needs at least "
1166 << N <<
" rows to match the matrix for a "
1167 "left-side solve R \\ X.");
1168 }
else if (side == RIGHT_SIDE) {
1169 TEUCHOS_TEST_FOR_EXCEPTION(X.numCols() < N, std::invalid_argument,
1170 "The input/output matrix X has only "
1171 << X.numCols() <<
" columns, but needs at least "
1172 << N <<
" columns to match the matrix for a "
1173 "right-side solve X / R.");
1177 std::invalid_argument,
1178 "Invalid robustness value " << robustness <<
".");
1185 TEUCHOS_TEST_FOR_EXCEPTION(count > 0, std::runtime_error,
1186 "There " << (count != 1 ?
"are" :
"is")
1187 <<
" " << count <<
" Inf or NaN entr"
1188 << (count != 1 ?
"ies" :
"y")
1189 <<
" in the upper triangle of R.");
1191 TEUCHOS_TEST_FOR_EXCEPTION(count > 0, std::runtime_error,
1192 "There " << (count != 1 ?
"are" :
"is")
1193 <<
" " << count <<
" Inf or NaN entr"
1194 << (count != 1 ?
"ies" :
"y") <<
" in the "
1195 "right-hand side(s) X.");
1200 bool foundRankDeficiency =
false;
1208 blas.TRSM(side, Teuchos::UPPER_TRI, Teuchos::NO_TRANS,
1209 Teuchos::NON_UNIT_DIAG, X.numRows(), X.numCols(),
1210 STS::one(), R.values(), R.stride(),
1211 X.values(), X.stride());
1215 mat_type B (Copy, X, X.numRows(), X.numCols());
1219 blas.TRSM(side, Teuchos::UPPER_TRI, Teuchos::NO_TRANS,
1220 Teuchos::NON_UNIT_DIAG, X.numRows(), X.numCols(),
1221 STS::one(), R.values(), R.stride(),
1222 X.values(), X.stride());
1228 warn_ <<
"Upper triangular solve: Found Infs and/or NaNs in the "
1229 "solution after using the fast algorithm. Retrying using a more "
1230 "robust algorithm." << std::endl;
1239 if (side == LEFT_SIDE) {
1241 mat_type R_copy (Teuchos::Copy, R_view, N, N);
1250 rank = solveLeastSquaresUsingSVD (R_copy, X);
1259 mat_type X_star (X.numCols(), X.numRows());
1265 rank = solveLeastSquaresUsingSVD (R_star, X_star);
1271 foundRankDeficiency =
true;
1275 TEUCHOS_TEST_FOR_EXCEPTION(
true, std::logic_error,
1276 "Should never get here! Invalid robustness value "
1277 << robustness <<
". Please report this bug to the "
1278 "Belos developers.");
1280 return std::make_pair (rank, foundRankDeficiency);
1298 out <<
"Testing Givens rotations:" << endl;
1299 Scalar x = STS::random();
1300 Scalar y = STS::random();
1301 out <<
" x = " << x <<
", y = " << y << endl;
1303 Scalar theCosine, theSine, result;
1305 computeGivensRotation (x, y, theCosine, theSine, result);
1306 out <<
"-- After computing rotation:" << endl;
1307 out <<
"---- cos,sin = " << theCosine <<
"," << theSine << endl;
1308 out <<
"---- x = " << x <<
", y = " << y
1309 <<
", result = " << result << endl;
1311 blas.ROT (1, &x, 1, &y, 1, &theCosine, &theSine);
1312 out <<
"-- After applying rotation:" << endl;
1313 out <<
"---- cos,sin = " << theCosine <<
"," << theSine << endl;
1314 out <<
"---- x = " << x <<
", y = " << y << endl;
1317 if (STS::magnitude(y) > 2*STS::eps())
1355 const bool testBlockGivens=
false,
1356 const bool extraVerbose=
false)
1358 using Teuchos::Array;
1361 TEUCHOS_TEST_FOR_EXCEPTION(numCols <= 0, std::invalid_argument,
1362 "numCols = " << numCols <<
" <= 0.");
1363 const int numRows = numCols + 1;
1368 mat_type R_givens (numRows, numCols);
1371 Array<Scalar> theCosines (numCols);
1372 Array<Scalar> theSines (numCols);
1374 mat_type R_blockGivens (numRows, numCols);
1375 mat_type y_blockGivens (numRows, 1);
1376 mat_type z_blockGivens (numRows, 1);
1377 Array<Scalar> blockCosines (numCols);
1378 Array<Scalar> blockSines (numCols);
1379 const int panelWidth = std::min (3, numCols);
1381 mat_type R_lapack (numRows, numCols);
1386 makeRandomProblem (H, z);
1388 printMatrix<Scalar> (out,
"H", H);
1389 printMatrix<Scalar> (out,
"z", z);
1394 z_givens.assign (z);
1395 if (testBlockGivens) {
1396 z_blockGivens.assign (z);
1398 z_lapack.assign (z);
1406 for (
int curCol = 0; curCol < numCols; ++curCol) {
1407 residualNormGivens = updateColumnGivens (H, R_givens, y_givens, z_givens,
1408 theCosines, theSines, curCol);
1410 solveGivens (y_givens, R_givens, z_givens, numCols-1);
1415 if (testBlockGivens) {
1416 const bool testBlocksAtATime =
true;
1417 if (testBlocksAtATime) {
1419 for (
int startCol = 0; startCol < numCols; startCol += panelWidth) {
1420 int endCol = std::min (startCol + panelWidth - 1, numCols - 1);
1421 residualNormBlockGivens =
1422 updateColumnsGivens (H, R_blockGivens, y_blockGivens, z_blockGivens,
1423 blockCosines, blockSines, startCol, endCol);
1429 for (
int startCol = 0; startCol < numCols; ++startCol) {
1430 residualNormBlockGivens =
1431 updateColumnsGivens (H, R_blockGivens, y_blockGivens, z_blockGivens,
1432 blockCosines, blockSines, startCol, startCol);
1439 solveGivens (y_blockGivens, R_blockGivens, z_blockGivens, numCols-1);
1444 solveLapack (H, R_lapack, y_lapack, z_lapack, numCols-1);
1451 leastSquaresConditionNumber (H, z, residualNormLapack);
1462 mat_type y_givens_view (Teuchos::View, y_givens, numCols, 1);
1463 mat_type y_blockGivens_view (Teuchos::View, y_blockGivens, numCols, 1);
1464 mat_type y_lapack_view (Teuchos::View, y_lapack, numCols, 1);
1467 solutionError (y_givens_view, y_lapack_view);
1468 const magnitude_type blockGivensSolutionError = testBlockGivens ?
1469 solutionError (y_blockGivens_view, y_lapack_view) :
1476 mat_type R_factorFromGivens (numCols, numCols);
1477 mat_type R_factorFromBlockGivens (numCols, numCols);
1478 mat_type R_factorFromLapack (numCols, numCols);
1480 for (
int j = 0; j < numCols; ++j) {
1481 for (
int i = 0; i <= j; ++i) {
1482 R_factorFromGivens(i,j) = R_givens(i,j);
1483 if (testBlockGivens) {
1484 R_factorFromBlockGivens(i,j) = R_blockGivens(i,j);
1486 R_factorFromLapack(i,j) = R_lapack(i,j);
1490 printMatrix<Scalar> (out,
"R_givens", R_factorFromGivens);
1491 printMatrix<Scalar> (out,
"y_givens", y_givens_view);
1492 printMatrix<Scalar> (out,
"z_givens", z_givens);
1494 if (testBlockGivens) {
1495 printMatrix<Scalar> (out,
"R_blockGivens", R_factorFromBlockGivens);
1496 printMatrix<Scalar> (out,
"y_blockGivens", y_blockGivens_view);
1497 printMatrix<Scalar> (out,
"z_blockGivens", z_blockGivens);
1500 printMatrix<Scalar> (out,
"R_lapack", R_factorFromLapack);
1501 printMatrix<Scalar> (out,
"y_lapack", y_lapack_view);
1502 printMatrix<Scalar> (out,
"z_lapack", z_lapack);
1508 out <<
"||H||_F = " << H_norm << endl;
1510 out <<
"||H y_givens - z||_2 / ||H||_F = "
1511 << leastSquaresResidualNorm (H, y_givens_view, z) / H_norm << endl;
1512 if (testBlockGivens) {
1513 out <<
"||H y_blockGivens - z||_2 / ||H||_F = "
1514 << leastSquaresResidualNorm (H, y_blockGivens_view, z) / H_norm << endl;
1516 out <<
"||H y_lapack - z||_2 / ||H||_F = "
1517 << leastSquaresResidualNorm (H, y_lapack_view, z) / H_norm << endl;
1519 out <<
"||y_givens - y_lapack||_2 / ||y_lapack||_2 = "
1520 << givensSolutionError << endl;
1521 if (testBlockGivens) {
1522 out <<
"||y_blockGivens - y_lapack||_2 / ||y_lapack||_2 = "
1523 << blockGivensSolutionError << endl;
1526 out <<
"Least-squares condition number = "
1527 << leastSquaresCondNum << endl;
1543 10 * STM::squareroot( numRows*numCols );
1545 wiggleFactor * leastSquaresCondNum;
1547 solutionErrorBoundFactor * STS::eps();
1548 out <<
"Solution error bound: " << solutionErrorBoundFactor
1549 <<
" * eps = " << solutionErrorBound << endl;
1554 if (STM::isnaninf (solutionErrorBound)) {
1560 if (STM::isnaninf (givensSolutionError)) {
1562 }
else if (givensSolutionError > solutionErrorBound) {
1564 }
else if (testBlockGivens) {
1565 if (STM::isnaninf (blockGivensSolutionError)) {
1567 }
else if (blockGivensSolutionError > solutionErrorBound) {
1595 const int testProblemSize,
1597 const bool verbose=
false)
1599 using Teuchos::LEFT_SIDE;
1600 using Teuchos::RIGHT_SIDE;
1602 typedef Teuchos::SerialDenseMatrix<int, scalar_type>
mat_type;
1604 Teuchos::oblackholestream blackHole;
1605 std::ostream& verboseOut = verbose ? out : blackHole;
1607 verboseOut <<
"Testing upper triangular solves" << endl;
1611 verboseOut <<
"-- Generating test matrix" << endl;
1612 const int N = testProblemSize;
1615 for (
int j = 0; j < N; ++j) {
1616 for (
int i = 0; i <= j; ++i) {
1617 R(i,j) = STS::random ();
1629 mat_type R_copy (Teuchos::Copy, R, N, N);
1630 mat_type B_copy (Teuchos::Copy, B, N, 1);
1636 verboseOut <<
"-- Solving RX=B" << endl;
1641 Resid.assign (B_copy);
1643 ops.
matMatMult (STS::one(), Resid, -STS::one(), R_copy, X);
1644 verboseOut <<
"---- ||R*X - B||_F = " << Resid.normFrobenius() << endl;
1645 verboseOut <<
"---- ||R||_F ||X||_F + ||B||_F = "
1646 << (R_norm * X.normFrobenius() + B_norm)
1660 B_star_copy.assign (B_star);
1662 verboseOut <<
"-- Solving YR=B^*" << endl;
1667 Resid2.assign (B_star_copy);
1668 ops.
matMatMult (STS::one(), Resid2, -STS::one(), Y, R_copy);
1669 verboseOut <<
"---- ||Y*R - B^*||_F = " << Resid2.normFrobenius() << endl;
1670 verboseOut <<
"---- ||Y||_F ||R||_F + ||B^*||_F = "
1671 << (Y.normFrobenius() * R_norm + B_norm)
1684 std::ostream& warn_;
1707 using Teuchos::Array;
1712 TEUCHOS_TEST_FOR_EXCEPTION(count != 0, std::invalid_argument,
1713 "solveLeastSquaresUsingSVD: The input matrix A "
1714 "contains " << count <<
"Inf and/or NaN entr"
1715 << (count != 1 ?
"ies" :
"y") <<
".");
1717 TEUCHOS_TEST_FOR_EXCEPTION(count != 0, std::invalid_argument,
1718 "solveLeastSquaresUsingSVD: The input matrix X "
1719 "contains " << count <<
"Inf and/or NaN entr"
1720 << (count != 1 ?
"ies" :
"y") <<
".");
1722 const int N = std::min (A.numRows(), A.numCols());
1733 Array<magnitude_type> singularValues (N);
1741 Array<magnitude_type> rwork (1);
1742 if (STS::isComplex) {
1743 rwork.resize (std::max (1, 5 * N));
1748 Scalar lworkScalar = STS::one();
1750 lapack.GELSS (A.numRows(), A.numCols(), X.numCols(),
1751 A.values(), A.stride(), X.values(), X.stride(),
1752 &singularValues[0], rankTolerance, &rank,
1753 &lworkScalar, -1, &rwork[0], &info);
1754 TEUCHOS_TEST_FOR_EXCEPTION(info != 0, std::logic_error,
1755 "_GELSS workspace query returned INFO = "
1756 << info <<
" != 0.");
1757 const int lwork =
static_cast<int> (STS::real (lworkScalar));
1758 TEUCHOS_TEST_FOR_EXCEPTION(lwork < 0, std::logic_error,
1759 "_GELSS workspace query returned LWORK = "
1760 << lwork <<
" < 0.");
1762 Array<Scalar> work (std::max (1, lwork));
1764 lapack.GELSS (A.numRows(), A.numCols(), X.numCols(),
1765 A.values(), A.stride(), X.values(), X.stride(),
1766 &singularValues[0], rankTolerance, &rank,
1767 &work[0], lwork, &rwork[0], &info);
1768 TEUCHOS_TEST_FOR_EXCEPTION(info != 0, std::runtime_error,
1769 "_GELSS returned INFO = " << info <<
" != 0.");
1785 const int numRows = curCol + 2;
1790 const mat_type R_view (Teuchos::View, R, numRows-1, numRows-1);
1791 const mat_type z_view (Teuchos::View, z, numRows-1, z.numCols());
1792 mat_type y_view (Teuchos::View, y, numRows-1, y.numCols());
1795 R_view, z_view, defaultRobustness_);
1809 for (
int j = 0; j < H.numCols(); ++j) {
1810 for (
int i = j+2; i < H.numRows(); ++i) {
1811 H(i,j) = STS::zero();
1822 const int numTrials = 1000;
1824 for (
int trial = 0; trial < numTrials && z_init == STM::zero(); ++trial) {
1825 z_init = STM::random();
1827 TEUCHOS_TEST_FOR_EXCEPTION(z_init == STM::zero(), std::runtime_error,
1828 "After " << numTrials <<
" trial"
1829 << (numTrials != 1 ?
"s" :
"")
1830 <<
", we were unable to generate a nonzero pseudo"
1831 "random real number. This most likely indicates a "
1832 "broken pseudorandom number generator.");
1845 computeGivensRotation (
const Scalar& x,
1853 const bool useLartg =
false;
1858 lapack.LARTG (x, y, &theCosine, &theSine, &result);
1867 blas.ROTG (&x_temp, &y_temp, &theCosine, &theSine);
1875 Teuchos::ArrayView<magnitude_type> sigmas)
1877 using Teuchos::Array;
1878 using Teuchos::ArrayView;
1880 const int numRows = A.numRows();
1881 const int numCols = A.numCols();
1882 TEUCHOS_TEST_FOR_EXCEPTION(sigmas.size() < std::min (numRows, numCols),
1883 std::invalid_argument,
1884 "The sigmas array is only of length " << sigmas.size()
1885 <<
", but must be of length at least "
1886 << std::min (numRows, numCols)
1887 <<
" in order to hold all the singular values of the "
1893 mat_type A_copy (numRows, numCols);
1899 Scalar lworkScalar = STS::zero();
1900 Array<magnitude_type> rwork (std::max (std::min (numRows, numCols) - 1, 1));
1901 lapack.GESVD (
'N',
'N', numRows, numCols,
1902 A_copy.values(), A_copy.stride(), &sigmas[0],
1903 (Scalar*) NULL, 1, (Scalar*) NULL, 1,
1904 &lworkScalar, -1, &rwork[0], &info);
1906 TEUCHOS_TEST_FOR_EXCEPTION(info != 0, std::logic_error,
1907 "LAPACK _GESVD workspace query failed with INFO = "
1909 const int lwork =
static_cast<int> (STS::real (lworkScalar));
1910 TEUCHOS_TEST_FOR_EXCEPTION(lwork < 0, std::logic_error,
1911 "LAPACK _GESVD workspace query returned LWORK = "
1912 << lwork <<
" < 0.");
1915 Teuchos::Array<Scalar> work (std::max (1, lwork));
1918 lapack.GESVD (
'N',
'N', numRows, numCols,
1919 A_copy.values(), A_copy.stride(), &sigmas[0],
1920 (Scalar*) NULL, 1, (Scalar*) NULL, 1,
1921 &work[0], lwork, &rwork[0], &info);
1922 TEUCHOS_TEST_FOR_EXCEPTION(info != 0, std::logic_error,
1923 "LAPACK _GESVD failed with INFO = " << info <<
".");
1933 std::pair<magnitude_type, magnitude_type>
1934 extremeSingularValues (
const mat_type& A)
1936 using Teuchos::Array;
1938 const int numRows = A.numRows();
1939 const int numCols = A.numCols();
1941 Array<magnitude_type> sigmas (std::min (numRows, numCols));
1942 singularValues (A, sigmas);
1943 return std::make_pair (sigmas[0], sigmas[std::min(numRows, numCols) - 1]);
1957 leastSquaresConditionNumber (
const mat_type& A,
1962 const std::pair<magnitude_type, magnitude_type> sigmaMaxMin =
1963 extremeSingularValues (A);
1967 TEUCHOS_TEST_FOR_EXCEPTION(sigmaMaxMin.second == STM::zero(), std::runtime_error,
1968 "The test matrix is rank deficient; LAPACK's _GESVD "
1969 "routine reports that its smallest singular value is "
1973 const magnitude_type A_cond = sigmaMaxMin.first / sigmaMaxMin.second;
1979 const magnitude_type sinTheta = residualNorm / b.normFrobenius();
1992 STM::zero() : STM::squareroot (1 - sinTheta * sinTheta);
2000 return 2 * A_cond / cosTheta + tanTheta * A_cond * A_cond;
2005 leastSquaresResidualNorm (
const mat_type& A,
2009 mat_type r (b.numRows(), b.numCols());
2013 LocalDenseMatrixOps<Scalar> ops;
2014 ops.
matMatMult (STS::one(), r, -STS::one(), A, x);
2015 return r.normFrobenius ();
2023 solutionError (
const mat_type& x_approx,
2026 const int numRows = x_exact.numRows();
2027 const int numCols = x_exact.numCols();
2029 mat_type x_diff (numRows, numCols);
2030 for (
int j = 0; j < numCols; ++j) {
2031 for (
int i = 0; i < numRows; ++i) {
2032 x_diff(i,j) = x_exact(i,j) - x_approx(i,j);
2038 return x_diff.normFrobenius() /
2039 (scalingFactor == STM::zero() ? STM::one() : scalingFactor);
2089 updateColumnGivens (
const mat_type& H,
2093 Teuchos::ArrayView<scalar_type> theCosines,
2094 Teuchos::ArrayView<scalar_type> theSines,
2100 const int numRows = curCol + 2;
2101 const int LDR = R.stride();
2102 const bool extraDebug =
false;
2105 cerr <<
"updateColumnGivens: curCol = " << curCol << endl;
2111 const mat_type H_col (Teuchos::View, H, numRows, 1, 0, curCol);
2115 mat_type R_col (Teuchos::View, R, numRows, 1, 0, curCol);
2119 R_col.assign (H_col);
2122 printMatrix<Scalar> (cerr,
"R_col before ", R_col);
2128 for (
int j = 0; j < curCol; ++j) {
2131 Scalar theCosine = theCosines[j];
2132 Scalar theSine = theSines[j];
2135 cerr <<
" j = " << j <<
": (cos,sin) = "
2136 << theCosines[j] <<
"," << theSines[j] << endl;
2138 blas.ROT (1, &R_col(j,0), LDR, &R_col(j+1,0), LDR,
2139 &theCosine, &theSine);
2141 if (extraDebug && curCol > 0) {
2142 printMatrix<Scalar> (cerr,
"R_col after applying previous "
2143 "Givens rotations", R_col);
2148 Scalar theCosine, theSine, result;
2149 computeGivensRotation (R_col(curCol,0), R_col(curCol+1,0),
2150 theCosine, theSine, result);
2151 theCosines[curCol] = theCosine;
2152 theSines[curCol] = theSine;
2155 cerr <<
" New cos,sin = " << theCosine <<
"," << theSine << endl;
2161 R_col(curCol, 0) = result;
2162 R_col(curCol+1, 0) = STS::zero();
2165 printMatrix<Scalar> (cerr,
"R_col after applying current "
2166 "Givens rotation", R_col);
2174 const int LDZ = z.stride();
2175 blas.ROT (z.numCols(),
2176 &z(curCol,0), LDZ, &z(curCol+1,0), LDZ,
2177 &theCosine, &theSine);
2183 printMatrix<Scalar> (cerr,
"z_after", z);
2189 return STS::magnitude( z(numRows-1, 0) );
2232 const int numRows = curCol + 2;
2233 const int numCols = curCol + 1;
2234 const int LDR = R.stride();
2237 const mat_type H_view (Teuchos::View, H, numRows, numCols);
2238 mat_type R_view (Teuchos::View, R, numRows, numCols);
2239 R_view.assign (H_view);
2243 mat_type y_view (Teuchos::View, y, numRows, y.numCols());
2244 mat_type z_view (Teuchos::View, z, numRows, y.numCols());
2245 y_view.assign (z_view);
2249 Scalar lworkScalar = STS::zero();
2251 lapack.GELS (
'N', numRows, numCols, y_view.numCols(),
2252 NULL, LDR, NULL, y_view.stride(),
2253 &lworkScalar, -1, &info);
2254 TEUCHOS_TEST_FOR_EXCEPTION(info != 0, std::logic_error,
2255 "LAPACK _GELS workspace query failed with INFO = "
2256 << info <<
", for a " << numRows <<
" x " << numCols
2257 <<
" matrix with " << y_view.numCols()
2258 <<
" right hand side"
2259 << ((y_view.numCols() != 1) ?
"s" :
"") <<
".");
2260 TEUCHOS_TEST_FOR_EXCEPTION(STS::real(lworkScalar) < STM::zero(),
2262 "LAPACK _GELS workspace query returned an LWORK with "
2263 "negative real part: LWORK = " << lworkScalar
2264 <<
". That should never happen. Please report this "
2265 "to the Belos developers.");
2266 TEUCHOS_TEST_FOR_EXCEPTION(STS::isComplex && STS::imag(lworkScalar) != STM::zero(),
2268 "LAPACK _GELS workspace query returned an LWORK with "
2269 "nonzero imaginary part: LWORK = " << lworkScalar
2270 <<
". That should never happen. Please report this "
2271 "to the Belos developers.");
2277 const int lwork = std::max (1,
static_cast<int> (STS::real (lworkScalar)));
2280 Teuchos::Array<Scalar> work (lwork);
2285 lapack.GELS (
'N', numRows, numCols, y_view.numCols(),
2286 R_view.values(), R_view.stride(),
2287 y_view.values(), y_view.stride(),
2288 (lwork > 0 ? &work[0] : (Scalar*) NULL),
2291 TEUCHOS_TEST_FOR_EXCEPTION(info != 0, std::logic_error,
2292 "Solving projected least-squares problem with LAPACK "
2293 "_GELS failed with INFO = " << info <<
", for a "
2294 << numRows <<
" x " << numCols <<
" matrix with "
2295 << y_view.numCols() <<
" right hand side"
2296 << (y_view.numCols() != 1 ?
"s" :
"") <<
".");
2300 return STS::magnitude( y_view(numRows-1, 0) );
2314 updateColumnsGivens (
const mat_type& H,
2318 Teuchos::ArrayView<scalar_type> theCosines,
2319 Teuchos::ArrayView<scalar_type> theSines,
2323 TEUCHOS_TEST_FOR_EXCEPTION(startCol > endCol, std::invalid_argument,
2324 "updateColumnGivens: startCol = " << startCol
2325 <<
" > endCol = " << endCol <<
".");
2328 for (
int curCol = startCol; curCol <= endCol; ++curCol) {
2329 lastResult = updateColumnGivens (H, R, y, z, theCosines, theSines, curCol);
2347 updateColumnsGivensBlock (
const mat_type& H,
2351 Teuchos::ArrayView<scalar_type> theCosines,
2352 Teuchos::ArrayView<scalar_type> theSines,
2356 const int numRows = endCol + 2;
2357 const int numColsToUpdate = endCol - startCol + 1;
2358 const int LDR = R.stride();
2363 const mat_type H_view (Teuchos::View, H, numRows, numColsToUpdate, 0, startCol);
2364 mat_type R_view (Teuchos::View, R, numRows, numColsToUpdate, 0, startCol);
2365 R_view.assign (H_view);
2373 for (
int j = 0; j < startCol; ++j) {
2374 blas.ROT (numColsToUpdate,
2375 &R(j, startCol), LDR, &R(j+1, startCol), LDR,
2376 &theCosines[j], &theSines[j]);
2380 for (
int curCol = startCol; curCol < endCol; ++curCol) {
2383 for (
int j = startCol; j < curCol; ++j) {
2384 blas.ROT (1, &R(j, curCol), LDR, &R(j+1, curCol), LDR,
2385 &theCosines[j], &theSines[j]);
2389 Scalar theCosine, theSine, result;
2390 computeGivensRotation (R(curCol, curCol), R(curCol+1, curCol),
2391 theCosine, theSine, result);
2392 theCosines[curCol] = theCosine;
2393 theSines[curCol] = theSine;
2398 R(curCol+1, curCol) = result;
2399 R(curCol+1, curCol) = STS::zero();
2406 const int LDZ = z.stride();
2407 blas.ROT (z.numCols(),
2408 &z(curCol,0), LDZ, &z(curCol+1,0), LDZ,
2409 &theCosine, &theSine);
2415 return STS::magnitude( z(numRows-1, 0) );