📄 dhgeqz.c
字号:
*info = -3;
} else if (*n < 0) {
*info = -4;
} else if (*ilo < 1) {
*info = -5;
} else if (*ihi > *n || *ihi < *ilo - 1) {
*info = -6;
} else if (*lda < *n) {
*info = -8;
} else if (*ldb < *n) {
*info = -10;
} else if (*ldq < 1 || ilq && *ldq < *n) {
*info = -15;
} else if (*ldz < 1 || ilz && *ldz < *n) {
*info = -17;
} else if (*lwork < max(1,*n) && ! lquery) {
*info = -19;
}
if (*info != 0) {
i__1 = -(*info);
xerbla_("DHGEQZ", &i__1);
return 0;
} else if (lquery) {
return 0;
}
/* Quick return if possible */
if (*n <= 0) {
work[1] = 1.;
/* --------------------- Begin Timing Code ----------------------- */
latime_1.itcnt = 0.;
/* ---------------------- End Timing Code ------------------------ */
return 0;
}
/* Initialize Q and Z */
if (icompq == 3) {
dlaset_("Full", n, n, &c_b12, &c_b13, &q[q_offset], ldq);
}
if (icompz == 3) {
dlaset_("Full", n, n, &c_b12, &c_b13, &z__[z_offset], ldz);
}
/* Machine Constants */
in = *ihi + 1 - *ilo;
safmin = dlamch_("S");
safmax = 1. / safmin;
ulp = dlamch_("E") * dlamch_("B");
anorm = dlanhs_("F", &in, &a_ref(*ilo, *ilo), lda, &work[1]);
bnorm = dlanhs_("F", &in, &b_ref(*ilo, *ilo), ldb, &work[1]);
/* Computing MAX */
d__1 = safmin, d__2 = ulp * anorm;
atol = max(d__1,d__2);
/* Computing MAX */
d__1 = safmin, d__2 = ulp * bnorm;
btol = max(d__1,d__2);
ascale = 1. / max(safmin,anorm);
bscale = 1. / max(safmin,bnorm);
/* Set Eigenvalues IHI+1:N */
i__1 = *n;
for (j = *ihi + 1; j <= i__1; ++j) {
if (b_ref(j, j) < 0.) {
if (ilschr) {
i__2 = j;
for (jr = 1; jr <= i__2; ++jr) {
a_ref(jr, j) = -a_ref(jr, j);
b_ref(jr, j) = -b_ref(jr, j);
/* L10: */
}
} else {
a_ref(j, j) = -a_ref(j, j);
b_ref(j, j) = -b_ref(j, j);
}
if (ilz) {
i__2 = *n;
for (jr = 1; jr <= i__2; ++jr) {
z___ref(jr, j) = -z___ref(jr, j);
/* L20: */
}
}
}
alphar[j] = a_ref(j, j);
alphai[j] = 0.;
beta[j] = b_ref(j, j);
/* L30: */
}
/* ---------------------- Begin Timing Code -------------------------
Count ops for norms, etc. */
opst = 0.;
/* Computing 2nd power */
i__1 = *n;
latime_1.ops += (doublereal) ((i__1 * i__1 << 1) + *n * 6);
/* ----------------------- End Timing Code --------------------------
If IHI < ILO, skip QZ steps */
if (*ihi < *ilo) {
goto L380;
}
/* MAIN QZ ITERATION LOOP
Initialize dynamic indices
Eigenvalues ILAST+1:N have been found.
Column operations modify rows IFRSTM:whatever.
Row operations modify columns whatever:ILASTM.
If only eigenvalues are being computed, then
IFRSTM is the row of the last splitting row above row ILAST;
this is always at least ILO.
IITER counts iterations since the last eigenvalue was found,
to tell when to use an extraordinary shift.
MAXIT is the maximum number of QZ sweeps allowed. */
ilast = *ihi;
if (ilschr) {
ifrstm = 1;
ilastm = *n;
} else {
ifrstm = *ilo;
ilastm = *ihi;
}
iiter = 0;
eshift = 0.;
maxit = (*ihi - *ilo + 1) * 30;
i__1 = maxit;
for (jiter = 1; jiter <= i__1; ++jiter) {
/* Split the matrix if possible.
Two tests:
1: A(j,j-1)=0 or j=ILO
2: B(j,j)=0 */
if (ilast == *ilo) {
/* Special case: j=ILAST */
goto L80;
} else {
if ((d__1 = a_ref(ilast, ilast - 1), abs(d__1)) <= atol) {
a_ref(ilast, ilast - 1) = 0.;
goto L80;
}
}
if ((d__1 = b_ref(ilast, ilast), abs(d__1)) <= btol) {
b_ref(ilast, ilast) = 0.;
goto L70;
}
/* General case: j<ILAST */
i__2 = *ilo;
for (j = ilast - 1; j >= i__2; --j) {
/* Test 1: for A(j,j-1)=0 or j=ILO */
if (j == *ilo) {
ilazro = TRUE_;
} else {
if ((d__1 = a_ref(j, j - 1), abs(d__1)) <= atol) {
a_ref(j, j - 1) = 0.;
ilazro = TRUE_;
} else {
ilazro = FALSE_;
}
}
/* Test 2: for B(j,j)=0 */
if ((d__1 = b_ref(j, j), abs(d__1)) < btol) {
b_ref(j, j) = 0.;
/* Test 1a: Check for 2 consecutive small subdiagonals in A */
ilazr2 = FALSE_;
if (! ilazro) {
temp = (d__1 = a_ref(j, j - 1), abs(d__1));
temp2 = (d__1 = a_ref(j, j), abs(d__1));
tempr = max(temp,temp2);
if (tempr < 1. && tempr != 0.) {
temp /= tempr;
temp2 /= tempr;
}
if (temp * (ascale * (d__1 = a_ref(j + 1, j), abs(d__1)))
<= temp2 * (ascale * atol)) {
ilazr2 = TRUE_;
}
}
/* If both tests pass (1 & 2), i.e., the leading diagonal
element of B in the block is zero, split a 1x1 block off
at the top. (I.e., at the J-th row/column) The leading
diagonal element of the remainder can also be zero, so
this may have to be done repeatedly. */
if (ilazro || ilazr2) {
i__3 = ilast - 1;
for (jch = j; jch <= i__3; ++jch) {
temp = a_ref(jch, jch);
dlartg_(&temp, &a_ref(jch + 1, jch), &c__, &s, &a_ref(
jch, jch));
a_ref(jch + 1, jch) = 0.;
i__4 = ilastm - jch;
drot_(&i__4, &a_ref(jch, jch + 1), lda, &a_ref(jch +
1, jch + 1), lda, &c__, &s);
i__4 = ilastm - jch;
drot_(&i__4, &b_ref(jch, jch + 1), ldb, &b_ref(jch +
1, jch + 1), ldb, &c__, &s);
if (ilq) {
drot_(n, &q_ref(1, jch), &c__1, &q_ref(1, jch + 1)
, &c__1, &c__, &s);
}
if (ilazr2) {
a_ref(jch, jch - 1) = a_ref(jch, jch - 1) * c__;
}
ilazr2 = FALSE_;
/* --------------- Begin Timing Code ----------------- */
opst += (doublereal) ((ilastm - jch) * 12 + 7 + nq *
6);
/* ---------------- End Timing Code ------------------ */
if ((d__1 = b_ref(jch + 1, jch + 1), abs(d__1)) >=
btol) {
if (jch + 1 >= ilast) {
goto L80;
} else {
ifirst = jch + 1;
goto L110;
}
}
b_ref(jch + 1, jch + 1) = 0.;
/* L40: */
}
goto L70;
} else {
/* Only test 2 passed -- chase the zero to B(ILAST,ILAST)
Then process as in the case B(ILAST,ILAST)=0 */
i__3 = ilast - 1;
for (jch = j; jch <= i__3; ++jch) {
temp = b_ref(jch, jch + 1);
dlartg_(&temp, &b_ref(jch + 1, jch + 1), &c__, &s, &
b_ref(jch, jch + 1));
b_ref(jch + 1, jch + 1) = 0.;
if (jch < ilastm - 1) {
i__4 = ilastm - jch - 1;
drot_(&i__4, &b_ref(jch, jch + 2), ldb, &b_ref(
jch + 1, jch + 2), ldb, &c__, &s);
}
i__4 = ilastm - jch + 2;
drot_(&i__4, &a_ref(jch, jch - 1), lda, &a_ref(jch +
1, jch - 1), lda, &c__, &s);
if (ilq) {
drot_(n, &q_ref(1, jch), &c__1, &q_ref(1, jch + 1)
, &c__1, &c__, &s);
}
temp = a_ref(jch + 1, jch);
dlartg_(&temp, &a_ref(jch + 1, jch - 1), &c__, &s, &
a_ref(jch + 1, jch));
a_ref(jch + 1, jch - 1) = 0.;
i__4 = jch + 1 - ifrstm;
drot_(&i__4, &a_ref(ifrstm, jch), &c__1, &a_ref(
ifrstm, jch - 1), &c__1, &c__, &s);
i__4 = jch - ifrstm;
drot_(&i__4, &b_ref(ifrstm, jch), &c__1, &b_ref(
ifrstm, jch - 1), &c__1, &c__, &s);
if (ilz) {
drot_(n, &z___ref(1, jch), &c__1, &z___ref(1, jch
- 1), &c__1, &c__, &s);
}
/* L50: */
}
/* ---------------- Begin Timing Code ------------------- */
opst += (doublereal) ((ilastm - ifrstm) * 12 + 26 + (nq +
nz) * 6) * (doublereal) (ilast - j);
/* ----------------- End Timing Code -------------------- */
goto L70;
}
} else if (ilazro) {
/* Only test 1 passed -- work on J:ILAST */
ifirst = j;
goto L110;
}
/* Neither test passed -- try next J
L60: */
}
/* (Drop-through is "impossible") */
*info = *n + 1;
goto L420;
/* B(ILAST,ILAST)=0 -- clear A(ILAST,ILAST-1) to split off a
1x1 block. */
L70:
temp = a_ref(ilast, ilast);
dlartg_(&temp, &a_ref(ilast, ilast - 1), &c__, &s, &a_ref(ilast,
ilast));
a_ref(ilast, ilast - 1) = 0.;
i__2 = ilast - ifrstm;
drot_(&i__2, &a_ref(ifrstm, ilast), &c__1, &a_ref(ifrstm, ilast - 1),
&c__1, &c__, &s);
i__2 = ilast - ifrstm;
drot_(&i__2, &b_ref(ifrstm, ilast), &c__1, &b_ref(ifrstm, ilast - 1),
&c__1, &c__, &s);
if (ilz) {
drot_(n, &z___ref(1, ilast), &c__1, &z___ref(1, ilast - 1), &c__1,
&c__, &s);
}
/* --------------------- Begin Timing Code ----------------------- */
opst += (doublereal) ((ilast - ifrstm) * 12 + 7 + nz * 6);
/* ---------------------- End Timing Code ------------------------
A(ILAST,ILAST-1)=0 -- Standardize B, set ALPHAR, ALPHAI,
and BETA */
L80:
if (b_ref(ilast, ilast) < 0.) {
if (ilschr) {
i__2 = ilast;
for (j = ifrstm; j <= i__2; ++j) {
a_ref(j, ilast) = -a_ref(j, ilast);
b_ref(j, ilast) = -b_ref(j, ilast);
/* L90: */
}
} else {
a_ref(ilast, ilast) = -a_ref(ilast, ilast);
b_ref(ilast, ilast) = -b_ref(ilast, ilast);
}
if (ilz) {
i__2 = *n;
for (j = 1; j <= i__2; ++j) {
z___ref(j, ilast) = -z___ref(j, ilast);
/* L100: */
}
}
}
alphar[ilast] = a_ref(ilast, ilast);
alphai[ilast] = 0.;
beta[ilast] = b_ref(ilast, ilast);
/* Go to next block -- exit if finished. */
--ilast;
if (ilast < *ilo) {
goto L380;
}
/* Reset counters */
iiter = 0;
eshift = 0.;
if (! ilschr) {
ilastm = ilast;
if (ifrstm > ilast) {
ifrstm = *ilo;
}
}
goto L350;
/* QZ step
This iteration only involves rows/columns IFIRST:ILAST. We
assume IFIRST < ILAST, and that the diagonal of B is non-zero. */
L110:
++iiter;
if (! ilschr) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -