qrsolv.c
来自「InsightToolkit-1.4.0(有大量的优化算法程序)」· C语言 代码 · 共 197 行
C
197 行
#include "f2c.h"
#include "netlib.h"
extern double sqrt(double); /* #include <math.h> */
/* Subroutine */ void qrsolv_(n, r, ldr, ipvt, diag, qtb, x, sdiag, wa)
const integer *n;
doublereal *r;
const integer *ldr, *ipvt;
const doublereal *diag, *qtb;
doublereal *x, *sdiag, *wa;
{
/* Local variables */
static doublereal temp;
static integer i, j, k, l;
static doublereal cotan;
static integer nsing;
static doublereal qtbpj;
static doublereal tan_, cos_, sin_, sum;
/* ********** */
/* */
/* subroutine qrsolv */
/* */
/* given an m by n matrix a, an n by n diagonal matrix d, */
/* and an m-vector b, the problem is to determine an x which */
/* solves the system */
/* */
/* a*x = b , d*x = 0 , */
/* */
/* in the least squares sense. */
/* */
/* this subroutine completes the solution of the problem */
/* if it is provided with the necessary information from the */
/* qr factorization, with column pivoting, of a. that is, if */
/* a*p = q*r, where p is a permutation matrix, q has orthogonal */
/* columns, and r is an upper triangular matrix with diagonal */
/* elements of nonincreasing magnitude, then qrsolv expects */
/* the full upper triangle of r, the permutation matrix p, */
/* and the first n components of (q transpose)*b. the system */
/* a*x = b, d*x = 0, is then equivalent to */
/* */
/* t t */
/* r*z = q *b , p *d*p*z = 0 , */
/* */
/* where x = p*z. if this system does not have full rank, */
/* then a least squares solution is obtained. on output qrsolv */
/* also provides an upper triangular matrix s such that */
/* */
/* t t t */
/* p *(a *a + d*d)*p = s *s . */
/* */
/* s is computed within qrsolv and may be of separate interest. */
/* */
/* the subroutine statement is */
/* */
/* subroutine qrsolv(n,r,ldr,ipvt,diag,qtb,x,sdiag,wa) */
/* */
/* where */
/* */
/* n is a positive integer input variable set to the order of r.*/
/* */
/* r is an n by n array. on input the full upper triangle */
/* must contain the full upper triangle of the matrix r. */
/* on output the full upper triangle is unaltered, and the */
/* strict lower triangle contains the strict upper triangle */
/* (transposed) of the upper triangular matrix s. */
/* */
/* ldr is a positive integer input variable not less than n */
/* which specifies the leading dimension of the array r. */
/* */
/* ipvt is an integer input array of length n which defines the */
/* permutation matrix p such that a*p = q*r. column j of p */
/* is column ipvt(j) of the identity matrix. */
/* */
/* diag is an input array of length n which must contain the */
/* diagonal elements of the matrix d. */
/* */
/* qtb is an input array of length n which must contain the first */
/* n elements of the vector (q transpose)*b. */
/* */
/* x is an output array of length n which contains the least */
/* squares solution of the system a*x = b, d*x = 0. */
/* */
/* sdiag is an output array of length n which contains the */
/* diagonal elements of the upper triangular matrix s. */
/* */
/* wa is a work array of length n. */
/* */
/* argonne national laboratory. minpack project. march 1980. */
/* burton s. garbow, kenneth e. hillstrom, jorge j. more */
/* */
/* ********** */
/* */
/* copy r and (q transpose)*b to preserve input and initialize s. */
/* in particular, save the diagonal elements of r in x. */
for (j = 0; j < *n; ++j) {
for (i = j; i < *n; ++i) {
r[i + j * *ldr] = r[j + i * *ldr];
}
x[j] = r[j + j * *ldr];
wa[j] = qtb[j];
}
/* 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 = ipvt[j] - 1;
if (diag[l] == 0.) {
goto L90;
}
for (k = j; k < *n; ++k) {
sdiag[k] = 0.;
}
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. */
qtbpj = 0.;
for (k = j; k < *n; ++k) {
/* determine a givens rotation which eliminates the */
/* appropriate element in the current row of d. */
if (sdiag[k] == 0.)
continue;
if (abs(r[k + k * *ldr]) < abs(sdiag[k])) {
cotan = r[k + k * *ldr] / sdiag[k];
sin_ = .5 / sqrt(.25 + .25 * (cotan * cotan));
cos_ = sin_ * cotan;
} else {
tan_ = sdiag[k] / r[k + k * *ldr];
cos_ = .5 / sqrt(.25 + .25 * (tan_ * tan_));
sin_ = cos_ * tan_;
}
/* compute the modified diagonal element of r and */
/* the modified element of ((q transpose)*b,0). */
r[k + k * *ldr] = cos_ * r[k + k * *ldr] + sin_ * sdiag[k];
temp = cos_ * wa[k] + sin_ * qtbpj;
qtbpj = -sin_ * wa[k] + cos_ * qtbpj;
wa[k] = temp;
/* accumulate the transformation in the row of s. */
for (i = k+1; i < *n; ++i) {
temp = cos_ * r[i + k * *ldr] + sin_ * sdiag[i];
sdiag[i] = -sin_ * r[i + k * *ldr] + cos_ * sdiag[i];
r[i + k * *ldr] = temp;
}
}
L90:
/* store the diagonal element of s and restore */
/* the corresponding diagonal element of r. */
sdiag[j] = r[j + j * *ldr];
r[j + j * *ldr] = x[j];
}
/* solve the triangular system for z. if the system is */
/* singular, then obtain a least squares solution. */
nsing = *n;
for (j = 0; j < *n; ++j) {
if (sdiag[j] == 0. && nsing == *n) {
nsing = j;
}
if (nsing < *n) {
wa[j] = 0.;
}
}
for (k = 0; k < nsing; ++k) {
j = nsing - k - 1;
sum = 0.;
for (i = j+1; i < nsing; ++i) {
sum += r[i + j * *ldr] * wa[i];
}
wa[j] = (wa[j] - sum) / sdiag[j];
}
/* permute the components of z back to components of x. */
for (j = 0; j < *n; ++j) {
l = ipvt[j] - 1;
x[l] = wa[j];
}
} /* qrsolv_ */
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?