dnlaso.c
来自「InsightToolkit-1.4.0(有大量的优化算法程序)」· C语言 代码 · 共 1,804 行 · 第 1/5 页
C
1,804 行
nval = *nr - *nl + 1;
flag = FALSE_;
for (i = 0; i < nval; ++i) {
if (ddot_(n, &eigvec[i * *lde], &c__1, &eigvec[i * *lde], &c__1) == 0.) {
dlaran_(n, &eigvec[i * *lde]);
}
}
/* LOOP OVER EIGENVALUES */
sigma = bound[(nval << 1) + 1];
for (j = 0; j < nval; ++j) {
numl = j+1;
/* PREPARE TO COMPUTE FIRST RAYLEIGH QUOTIENT */
L10:
dlabax_(n, nband, a, &eigvec[j * *lde], vtemp);
vnorm = dnrm2_(n, vtemp, &c__1);
if (vnorm != 0.) {
d__1 = 1. / vnorm;
dscal_(n, &d__1, vtemp, &c__1);
dscal_(n, &d__1, &eigvec[j * *lde], &c__1);
d__1 = -sigma;
daxpy_(n, &d__1, &eigvec[j * *lde], &c__1, vtemp, &c__1);
}
/* LOOP OVER SHIFTS */
/* COMPUTE RAYLEIGH QUOTIENT, RESIDUAL NORM, AND CURRENT TOLERANCE */
L20:
vnorm = dnrm2_(n, &eigvec[j * *lde], &c__1);
if (vnorm == 0.) {
dlaran_(n, &eigvec[j * *lde]);
goto L10;
}
rq = sigma + ddot_(n, &eigvec[j * *lde], &c__1, vtemp, &c__1) / vnorm / vnorm;
d__1 = sigma - rq;
daxpy_(n, &d__1, &eigvec[j * *lde], &c__1, vtemp, &c__1);
resid = max(*atol,dnrm2_(n, vtemp, &c__1) / vnorm);
d__1 = 1. / vnorm;
dscal_(n, &d__1, &eigvec[j * *lde], &c__1);
/* ACCEPT EIGENVALUE IF THE INTERVAL IS SMALL ENOUGH */
if (bound[(j << 1) + 3] - bound[(j << 1) + 2] < *atol * 3.) {
goto L300;
}
/* COMPUTE MINIMAL ERROR BOUND */
errb = resid;
gap = min(bound[(j << 1) + 4] - rq,rq - bound[(j << 1) + 1]);
if (gap > resid) {
errb = max(*atol,resid * resid / gap);
}
/* TENTATIVE NEW SHIFT */
sigma = (bound[(j << 1) + 2] + bound[(j << 1) + 3]) * .5;
/* CHECK FOR TERMINALTION */
if (resid > *atol * 2.) {
goto L40;
}
if (rq - errb > bound[(j << 1) + 1] && rq + errb < bound[(j << 1) + 4]) {
goto L310;
}
/* RQ IS TO THE LEFT OF THE INTERVAL */
L40:
if (rq >= bound[(j << 1) + 2]) {
goto L50;
}
if (rq - errb > bound[(j << 1) + 1]) {
goto L100;
}
if (rq + errb < bound[(j << 1) + 2]) {
dlaran_(n, &eigvec[j * *lde]);
}
goto L200;
/* RQ IS TO THE RIGHT OF THE INTERVAL */
L50:
if (rq <= bound[(j << 1) + 3]) {
goto L100;
}
if (rq + errb < bound[(j << 1) + 4]) {
goto L100;
}
/* SAVE THE REJECTED VECTOR IF INDICATED */
if (rq - errb <= bound[(j << 1) + 3]) {
goto L200;
}
for (i = j; i < nval; ++i) {
if (bound[(i << 1) + 3] > rq) {
dcopy_(n, &eigvec[j * *lde], &c__1, &eigvec[i * *lde], &c__1);
break;
}
}
dlaran_(n, &eigvec[j * *lde]);
goto L200;
/* PERTURB RQ TOWARD THE MIDDLE */
L100:
if (sigma < rq-errb) {
sigma = rq-errb;
}
if (sigma > rq+errb) {
sigma = rq+errb;
}
/* FACTOR AND SOLVE */
L200:
for (i = j; i < nval; ++i) {
if (sigma < bound[(i << 1) + 2]) {
break;
}
}
numvec = i - j;
numvec = min(numvec,*nband+2);
if (resid < *artol) {
numvec = min(1,numvec);
}
dcopy_(n, &eigvec[j * *lde], &c__1, vtemp, &c__1);
i__1 = (*nband << 1) - 1;
dlabfc_(n, nband, a, &sigma, &numvec, lde, &eigvec[j * *lde], &numl, &i__1, atemp, d, atol);
/* PARTIALLY SCALE EXTRA VECTORS TO PREVENT UNDERFLOW OR OVERFLOW */
for (i = j+1; i < numvec+j; ++i) {
d__1 = 1. / vnorm;
dscal_(n, &d__1, &eigvec[i * *lde], &c__1);
}
/* UPDATE INTERVALS */
numl -= *nl - 1;
if (numl >= 0) {
bound[1] = min(bound[1],sigma);
}
for (i = j; i < nval; ++i) {
if (sigma < bound[(i << 1) + 2]) {
goto L20;
}
if (numl <= i)
bound[(i << 1) + 2] = sigma;
else
bound[(i << 1) + 3] = sigma;
}
if (numl < nval + 1) {
if (sigma > bound[(nval << 1) + 2])
bound[(nval << 1) + 2] = sigma;
}
goto L20;
/* ACCEPT AN EIGENPAIR */
L300:
dlaran_(n, &eigvec[j * *lde]);
flag = TRUE_;
goto L310;
L305:
flag = FALSE_;
rq = (bound[(j << 1) + 2] + bound[(j << 1) + 3]) * .5;
i__1 = (*nband << 1) - 1;
dlabfc_(n, nband, a, &rq, &numvec, lde, &eigvec[j * *lde], &numl, &i__1, atemp, d, atol);
vnorm = dnrm2_(n, &eigvec[j * *lde], &c__1);
if (vnorm != 0.) {
d__1 = 1. / vnorm;
dscal_(n, &d__1, &eigvec[j * *lde], &c__1);
}
/* ORTHOGONALIZE THE NEW EIGENVECTOR AGAINST THE OLD ONES */
L310:
eigval[j] = rq;
for (i = 0; i < j; ++i) {
d__1 = -ddot_(n, &eigvec[i * *lde], &c__1, &eigvec[j * *lde], &c__1);
daxpy_(n, &d__1, &eigvec[i * *lde], &c__1, &eigvec[j * *lde], &c__1);
}
vnorm = dnrm2_(n, &eigvec[j * *lde], &c__1);
if (vnorm == 0.) {
goto L305;
}
d__1 = 1. / vnorm;
dscal_(n, &d__1, &eigvec[j * *lde], &c__1);
/* ORTHOGONALIZE LATER VECTORS AGAINST THE CONVERGED ONE */
if (flag) {
goto L305;
}
for (i = j+1; i < nval; ++i) {
d__1 = -ddot_(n, &eigvec[j * *lde], &c__1, &eigvec[i * *lde], &c__1);
daxpy_(n, &d__1, &eigvec[j * *lde], &c__1, &eigvec[i * *lde], &c__1);
}
}
} /* dlabcm_ */
/* *********************************************************************** */
/* Subroutine */ void dlabfc_(n, nband, a, sigma, number, lde, eigvec, numl, ldad, atemp, d, atol)
const integer *n, *nband;
doublereal *a, *sigma;
const integer *number, *lde;
doublereal *eigvec;
integer *numl, *ldad;
doublereal *atemp, *d, *atol;
{
/* System generated locals */
integer i__1;
doublereal d__1;
/* Local variables */
static doublereal zero=0.;
static integer i, j, k, l, m;
static integer la, ld, nb1, lpm;
/* THIS SUBROUTINE FACTORS (A-SIGMA*I) WHERE A IS A GIVEN BAND */
/* MATRIX AND SIGMA IS AN INPUT PARAMETER. IT ALSO SOLVES ZERO */
/* OR MORE SYSTEMS OF LINEAR EQUATIONS. IT RETURNS THE NUMBER */
/* OF EIGENVALUES OF A LESS THAN SIGMA BY COUNTING THE STURM */
/* SEQUENCE DURING THE FACTORIZATION. TO OBTAIN THE STURM */
/* SEQUENCE COUNT WHILE ALLOWING NON-SYMMETRIC PIVOTING FOR */
/* STABILITY, THE CODE USES A GUPTA'S MULTIPLE PIVOTING */
/* ALGORITHM. */
/* INITIALIZE */
nb1 = *nband - 1;
*numl = 0;
i__1 = *ldad * *nband;
dcopy_(&i__1, &zero, &c__0, d, &c__1);
/* LOOP OVER COLUMNS OF A */
for (k = 0; k < *n; ++k) {
/* ADD A COLUMN OF A TO D */
d[nb1 + nb1 * *ldad] = a[k * *nband] - *sigma;
m = min(k,nb1);
for (i = 0; i < m; ++i) {
la = k - i - 1;
ld = nb1 - i - 1;
d[ld + nb1 * *ldad] = a[i + 1 + la * *nband];
}
m = min(*n-k-1,nb1);
for (i = 0; i < m; ++i) {
ld = *nband + i;
d[ld + nb1 * *ldad] = a[i + 1 + k * *nband];
}
/* TERMINATE */
lpm = 1;
for (i = 0; i < nb1; ++i) {
l = k - nb1 + i;
if (d[i + nb1 * *ldad] == 0.) {
continue;
}
if (abs(d[i + i * *ldad]) >= abs(d[i + nb1 * *ldad])) {
goto L50;
}
if ( (d[i + nb1 * *ldad] < 0. && d[i + i * *ldad] < 0. ) ||
(d[i + nb1 * *ldad] > 0. && d[i + i * *ldad] >= 0.) ) {
lpm = -lpm;
}
i__1 = *ldad - i;
dswap_(&i__1, &d[i + i * *ldad], &c__1, &d[i + nb1 * *ldad], &c__1);
dswap_(number, &eigvec[l], lde, &eigvec[k], lde);
L50:
i__1 = *ldad - i - 1;
d__1 = -d[i + nb1 * *ldad] / d[i + i * *ldad];
daxpy_(&i__1, &d__1, &d[i + 1 + i * *ldad], &c__1, &d[i + 1 + nb1 * *ldad], &c__1);
d__1 = -d[i + nb1 * *ldad] / d[i + i * *ldad];
daxpy_(number, &d__1, &eigvec[l], lde, &eigvec[k], lde);
}
/* UPDATE STURM SEQUENCE COUNT */
if (d[nb1 + nb1 * *ldad] < 0.) {
lpm = -lpm;
}
if (lpm < 0) {
++(*numl);
}
if (k == *n-1) {
goto L110;
}
/* COPY FIRST COLUMN OF D INTO ATEMP */
if (k >= nb1) {
l = k - nb1;
dcopy_(ldad, d, &c__1, &atemp[l * *ldad], &c__1);
}
/* SHIFT THE COLUMNS OF D OVER AND UP */
for (i = 0; i < nb1; ++i) {
i__1 = *ldad - i - 1;
dcopy_(&i__1, &d[i + 1 + (i + 1) * *ldad], &c__1, &d[i + i * *ldad], &c__1);
d[*ldad - 1 + i * *ldad] = 0.;
}
}
/* TRANSFER D TO ATEMP */
L110:
for (i = 0; i < *nband; ++i) {
i__1 = *nband - i;
l = *n - i__1;
dcopy_(&i__1, &d[i + i * *ldad], &c__1, &atemp[l * *ldad], &c__1);
}
/* BACK SUBSTITUTION */
if (*number == 0) {
return;
}
for (k = *n-1; k >= 0; --k) {
if (abs(atemp[k * *ldad]) <= *atol) {
atemp[k * *ldad] = d_sign(atol, &atemp[k * *ldad]);
}
for (i = 0; i < *number; ++i) {
eigvec[k + i * *lde] /= atemp[k * *ldad];
m = min(*ldad-1,k);
for (j = 0; j < m; ++j) {
l = k - j - 1;
eigvec[l + i * *lde] -= atemp[j + 1 + l * *ldad] * eigvec[k + i * *lde];
}
}
}
} /* dlabfc_ */
/* Subroutine */ void dlaeig_(n, nband, nl, nr, a, eigval, lde, eigvec, bound, atemp, d, vtemp, eps, tmin, tmax)
const integer *n, *nband, *nl, *nr;
doublereal *a, *eigval;
const integer *lde;
doublereal *eigvec, *bound, *atemp, *d, *vtemp, *eps, *tmin, *tmax;
{
/* Local variables */
static doublereal atol;
static integer nval, i;
static doublereal artol;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?