Eigen-Contrib  5.0.1
 
Loading...
Searching...
No Matches
LMqrsolv.h
1// This file is part of Eigen, a lightweight C++ template library
2// for linear algebra.
3//
4// Copyright (C) 2009 Thomas Capricelli <orzel@freehackers.org>
5// Copyright (C) 2012 Desire Nuentsa <desire.nuentsa_wakam@inria.fr>
6//
7// This code initially comes from MINPACK whose original authors are:
8// Copyright Jorge More - Argonne National Laboratory
9// Copyright Burt Garbow - Argonne National Laboratory
10// Copyright Ken Hillstrom - Argonne National Laboratory
11//
12// This Source Code Form is subject to the terms of the Minpack license
13// (a BSD-like license) described in the accompanying CopyrightMINPACK.txt file.
14// SPDX-License-Identifier: MPL-2.0 AND LicenseRef-MINPACK
15
16#ifndef EIGEN_LMQRSOLV_H
17#define EIGEN_LMQRSOLV_H
18
19// IWYU pragma: private
20#include "./InternalHeaderCheck.h"
21
22namespace Eigen {
23
24namespace internal {
25
26template <typename Scalar, int Rows, int Cols, typename PermIndex>
27void lmqrsolv(Matrix<Scalar, Rows, Cols> &s, const PermutationMatrix<Dynamic, Dynamic, PermIndex> &iPerm,
28 const Matrix<Scalar, Dynamic, 1> &diag, const Matrix<Scalar, Dynamic, 1> &qtb,
29 Matrix<Scalar, Dynamic, 1> &x, Matrix<Scalar, Dynamic, 1> &sdiag) {
30 /* Local variables */
31 Index i, j, k;
32 Scalar temp;
33 Index n = s.cols();
34 Matrix<Scalar, Dynamic, 1> wa(n);
35 JacobiRotation<Scalar> givens;
36
37 /* Function Body */
38 // the following will only change the lower triangular part of s, including
39 // the diagonal, though the diagonal is restored afterward
40
41 /* copy r and (q transpose)*b to preserve input and initialize s. */
42 /* in particular, save the diagonal elements of r in x. */
43 x = s.diagonal();
44 wa = qtb;
45
46 s.topLeftCorner(n, n).template triangularView<StrictlyLower>() = s.topLeftCorner(n, n).transpose();
47 /* eliminate the diagonal matrix d using a givens rotation. */
48 for (j = 0; j < n; ++j) {
49 /* prepare the row of d to be eliminated, locating the */
50 /* diagonal element using p from the qr factorization. */
51 const PermIndex l = iPerm.indices()(j);
52 if (diag[l] == 0.) break;
53 sdiag.tail(n - j).setZero();
54 sdiag[j] = diag[l];
55
56 /* the transformations to eliminate the row of d */
57 /* modify only a single element of (q transpose)*b */
58 /* beyond the first n, which is initially zero. */
59 Scalar qtbpj = 0.;
60 for (k = j; k < n; ++k) {
61 /* determine a givens rotation which eliminates the */
62 /* appropriate element in the current row of d. */
63 givens.makeGivens(-s(k, k), sdiag[k]);
64
65 /* compute the modified diagonal element of r and */
66 /* the modified element of ((q transpose)*b,0). */
67 s(k, k) = givens.c() * s(k, k) + givens.s() * sdiag[k];
68 temp = givens.c() * wa[k] + givens.s() * qtbpj;
69 qtbpj = -givens.s() * wa[k] + givens.c() * qtbpj;
70 wa[k] = temp;
71
72 /* accumulate the transformation in the row of s. */
73 for (i = k + 1; i < n; ++i) {
74 temp = givens.c() * s(i, k) + givens.s() * sdiag[i];
75 sdiag[i] = -givens.s() * s(i, k) + givens.c() * sdiag[i];
76 s(i, k) = temp;
77 }
78 }
79 }
80
81 /* solve the triangular system for z. if the system is */
82 /* singular, then obtain a least squares solution. */
83 Index nsing;
84 for (nsing = 0; nsing < n && sdiag[nsing] != 0; nsing++) {
85 }
86
87 wa.tail(n - nsing).setZero();
88 s.topLeftCorner(nsing, nsing).transpose().template triangularView<Upper>().solveInPlace(wa.head(nsing));
89
90 // restore
91 sdiag = s.diagonal();
92 s.diagonal() = x;
93
94 /* permute the components of z back to components of x. */
95 x = iPerm * wa;
96}
97} // end namespace internal
98
99} // end namespace Eigen
100
101#endif // EIGEN_LMQRSOLV_H
Namespace containing all symbols from the Eigen library.