| // This file is part of Eigen, a lightweight C++ template library |
| // for linear algebra. |
| // |
| // Copyright (C) 2009 Thomas Capricelli <orzel@freehackers.org> |
| // Copyright (C) 2012 Desire Nuentsa <desire.nuentsa_wakam@inria.fr> |
| // |
| // This code initially comes from MINPACK whose original authors are: |
| // Copyright Jorge More - Argonne National Laboratory |
| // Copyright Burt Garbow - Argonne National Laboratory |
| // Copyright Ken Hillstrom - Argonne National Laboratory |
| // |
| // This Source Code Form is subject to the terms of the Minpack license |
| // (a BSD-like license) described in the campaigned CopyrightMINPACK.txt file. |
| |
| #ifndef EIGEN_LMQRSOLV_H |
| #define EIGEN_LMQRSOLV_H |
| |
| // IWYU pragma: private |
| #include "./InternalHeaderCheck.h" |
| |
| namespace Eigen { |
| |
| namespace internal { |
| |
| template <typename Scalar, int Rows, int Cols, typename PermIndex> |
| void lmqrsolv(Matrix<Scalar, Rows, Cols> &s, const PermutationMatrix<Dynamic, Dynamic, PermIndex> &iPerm, |
| const Matrix<Scalar, Dynamic, 1> &diag, const Matrix<Scalar, Dynamic, 1> &qtb, |
| Matrix<Scalar, Dynamic, 1> &x, Matrix<Scalar, Dynamic, 1> &sdiag) { |
| /* Local variables */ |
| Index i, j, k; |
| Scalar temp; |
| Index n = s.cols(); |
| Matrix<Scalar, Dynamic, 1> wa(n); |
| JacobiRotation<Scalar> givens; |
| |
| /* Function Body */ |
| // the following will only change the lower triangular part of s, including |
| // the diagonal, though the diagonal is restored afterward |
| |
| /* copy r and (q transpose)*b to preserve input and initialize s. */ |
| /* in particular, save the diagonal elements of r in x. */ |
| x = s.diagonal(); |
| wa = qtb; |
| |
| s.topLeftCorner(n, n).template triangularView<StrictlyLower>() = s.topLeftCorner(n, n).transpose(); |
| /* eliminate the diagonal matrix d using a givens rotation. */ |
| for (j = 0; j < n; ++j) { |
| /* prepare the row of d to be eliminated, locating the */ |
| /* diagonal element using p from the qr factorization. */ |
| const PermIndex l = iPerm.indices()(j); |
| if (diag[l] == 0.) break; |
| sdiag.tail(n - j).setZero(); |
| sdiag[j] = diag[l]; |
| |
| /* the transformations to eliminate the row of d */ |
| /* modify only a single element of (q transpose)*b */ |
| /* beyond the first n, which is initially zero. */ |
| Scalar qtbpj = 0.; |
| for (k = j; k < n; ++k) { |
| /* determine a givens rotation which eliminates the */ |
| /* appropriate element in the current row of d. */ |
| givens.makeGivens(-s(k, k), sdiag[k]); |
| |
| /* compute the modified diagonal element of r and */ |
| /* the modified element of ((q transpose)*b,0). */ |
| s(k, k) = givens.c() * s(k, k) + givens.s() * sdiag[k]; |
| temp = givens.c() * wa[k] + givens.s() * qtbpj; |
| qtbpj = -givens.s() * wa[k] + givens.c() * qtbpj; |
| wa[k] = temp; |
| |
| /* accumulate the transformation in the row of s. */ |
| for (i = k + 1; i < n; ++i) { |
| temp = givens.c() * s(i, k) + givens.s() * sdiag[i]; |
| sdiag[i] = -givens.s() * s(i, k) + givens.c() * sdiag[i]; |
| s(i, k) = temp; |
| } |
| } |
| } |
| |
| /* solve the triangular system for z. if the system is */ |
| /* singular, then obtain a least squares solution. */ |
| Index nsing; |
| for (nsing = 0; nsing < n && sdiag[nsing] != 0; nsing++) { |
| } |
| |
| wa.tail(n - nsing).setZero(); |
| s.topLeftCorner(nsing, nsing).transpose().template triangularView<Upper>().solveInPlace(wa.head(nsing)); |
| |
| // restore |
| sdiag = s.diagonal(); |
| s.diagonal() = x; |
| |
| /* permute the components of z back to components of x. */ |
| x = iPerm * wa; |
| } |
| |
| template <typename Scalar, int Options_, typename Index> |
| void lmqrsolv(SparseMatrix<Scalar, Options_, Index> &s, const PermutationMatrix<Dynamic, Dynamic> &iPerm, |
| const Matrix<Scalar, Dynamic, 1> &diag, const Matrix<Scalar, Dynamic, 1> &qtb, |
| Matrix<Scalar, Dynamic, 1> &x, Matrix<Scalar, Dynamic, 1> &sdiag) { |
| /* Local variables */ |
| typedef SparseMatrix<Scalar, RowMajor, Index> FactorType; |
| Index i, j, k, l; |
| Scalar temp; |
| Index n = s.cols(); |
| Matrix<Scalar, Dynamic, 1> wa(n); |
| JacobiRotation<Scalar> givens; |
| |
| /* Function Body */ |
| // the following will only change the lower triangular part of s, including |
| // the diagonal, though the diagonal is restored afterward |
| |
| /* copy r and (q transpose)*b to preserve input and initialize R. */ |
| wa = qtb; |
| FactorType R(s); |
| // Eliminate the diagonal matrix d using a givens rotation |
| for (j = 0; j < n; ++j) { |
| // Prepare the row of d to be eliminated, locating the |
| // diagonal element using p from the qr factorization |
| l = iPerm.indices()(j); |
| if (diag(l) == Scalar(0)) break; |
| sdiag.tail(n - j).setZero(); |
| sdiag[j] = diag[l]; |
| // the transformations to eliminate the row of d |
| // modify only a single element of (q transpose)*b |
| // beyond the first n, which is initially zero. |
| |
| Scalar qtbpj = 0; |
| // Browse the nonzero elements of row j of the upper triangular s |
| for (k = j; k < n; ++k) { |
| typename FactorType::InnerIterator itk(R, k); |
| for (; itk; ++itk) { |
| if (itk.index() < k) |
| continue; |
| else |
| break; |
| } |
| // At this point, we have the diagonal element R(k,k) |
| // Determine a givens rotation which eliminates |
| // the appropriate element in the current row of d |
| givens.makeGivens(-itk.value(), sdiag(k)); |
| |
| // Compute the modified diagonal element of r and |
| // the modified element of ((q transpose)*b,0). |
| itk.valueRef() = givens.c() * itk.value() + givens.s() * sdiag(k); |
| temp = givens.c() * wa(k) + givens.s() * qtbpj; |
| qtbpj = -givens.s() * wa(k) + givens.c() * qtbpj; |
| wa(k) = temp; |
| |
| // Accumulate the transformation in the remaining k row/column of R |
| for (++itk; itk; ++itk) { |
| i = itk.index(); |
| temp = givens.c() * itk.value() + givens.s() * sdiag(i); |
| sdiag(i) = -givens.s() * itk.value() + givens.c() * sdiag(i); |
| itk.valueRef() = temp; |
| } |
| } |
| } |
| |
| // Solve the triangular system for z. If the system is |
| // singular, then obtain a least squares solution |
| Index nsing; |
| for (nsing = 0; nsing < n && sdiag(nsing) != 0; nsing++) { |
| } |
| |
| wa.tail(n - nsing).setZero(); |
| // x = wa; |
| wa.head(nsing) = R.topLeftCorner(nsing, nsing).template triangularView<Upper>().solve /*InPlace*/ (wa.head(nsing)); |
| |
| sdiag = R.diagonal(); |
| // Permute the components of z back to components of x |
| x = iPerm * wa; |
| } |
| } // end namespace internal |
| |
| } // end namespace Eigen |
| |
| #endif // EIGEN_LMQRSOLV_H |