/* -- translated by f2c (version 20191129).
You must link the resulting object file with libf2c:
on Microsoft Windows system, link with libf2c.lib;
on Linux or Unix systems, link with .../path/to/libf2c.a -lm
or, if you install libf2c.a in a standard place, with -lf2c -lm
-- in that order, at the end of the command line, as in
cc *.o -lf2c -lm
Source for libf2c is in /netlib/f2c/libf2c.zip, e.g.,
http://www.netlib.org/f2c/libf2c.zip
*/
#include "f2c.h"
/* Table of constant values */
static integer c__1 = 1;
/* > \brief \b DLAHQR computes the eigenvalues and Schur factorization of an upper Hessenberg matrix, using th
e double-shift/single-shift QR algorithm.
=========== DOCUMENTATION ===========
Online html documentation available at
http://www.netlib.org/lapack/explore-html/
> \htmlonly
> Download DLAHQR + dependencies
>
> [TGZ]
>
> [ZIP]
>
> [TXT]
> \endhtmlonly
Definition:
===========
SUBROUTINE DLAHQR( WANTT, WANTZ, N, ILO, IHI, H, LDH, WR, WI,
ILOZ, IHIZ, Z, LDZ, INFO )
INTEGER IHI, IHIZ, ILO, ILOZ, INFO, LDH, LDZ, N
LOGICAL WANTT, WANTZ
DOUBLE PRECISION H( LDH, * ), WI( * ), WR( * ), Z( LDZ, * )
> \par Purpose:
=============
>
> \verbatim
>
> DLAHQR is an auxiliary routine called by DHSEQR to update the
> eigenvalues and Schur decomposition already computed by DHSEQR, by
> dealing with the Hessenberg submatrix in rows and columns ILO to
> IHI.
> \endverbatim
Arguments:
==========
> \param[in] WANTT
> \verbatim
> WANTT is LOGICAL
> = .TRUE. : the full Schur form T is required;
> = .FALSE.: only eigenvalues are required.
> \endverbatim
>
> \param[in] WANTZ
> \verbatim
> WANTZ is LOGICAL
> = .TRUE. : the matrix of Schur vectors Z is required;
> = .FALSE.: Schur vectors are not required.
> \endverbatim
>
> \param[in] N
> \verbatim
> N is INTEGER
> The order of the matrix H. N >= 0.
> \endverbatim
>
> \param[in] ILO
> \verbatim
> ILO is INTEGER
> \endverbatim
>
> \param[in] IHI
> \verbatim
> IHI is INTEGER
> It is assumed that H is already upper quasi-triangular in
> rows and columns IHI+1:N, and that H(ILO,ILO-1) = 0 (unless
> ILO = 1). DLAHQR works primarily with the Hessenberg
> submatrix in rows and columns ILO to IHI, but applies
> transformations to all of H if WANTT is .TRUE..
> 1 <= ILO <= max(1,IHI); IHI <= N.
> \endverbatim
>
> \param[in,out] H
> \verbatim
> H is DOUBLE PRECISION array, dimension (LDH,N)
> On entry, the upper Hessenberg matrix H.
> On exit, if INFO is zero and if WANTT is .TRUE., H is upper
> quasi-triangular in rows and columns ILO:IHI, with any
> 2-by-2 diagonal blocks in standard form. If INFO is zero
> and WANTT is .FALSE., the contents of H are unspecified on
> exit. The output state of H if INFO is nonzero is given
> below under the description of INFO.
> \endverbatim
>
> \param[in] LDH
> \verbatim
> LDH is INTEGER
> The leading dimension of the array H. LDH >= max(1,N).
> \endverbatim
>
> \param[out] WR
> \verbatim
> WR is DOUBLE PRECISION array, dimension (N)
> \endverbatim
>
> \param[out] WI
> \verbatim
> WI is DOUBLE PRECISION array, dimension (N)
> The real and imaginary parts, respectively, of the computed
> eigenvalues ILO to IHI are stored in the corresponding
> elements of WR and WI. If two eigenvalues are computed as a
> complex conjugate pair, they are stored in consecutive
> elements of WR and WI, say the i-th and (i+1)th, with
> WI(i) > 0 and WI(i+1) < 0. If WANTT is .TRUE., the
> eigenvalues are stored in the same order as on the diagonal
> of the Schur form returned in H, with WR(i) = H(i,i), and, if
> H(i:i+1,i:i+1) is a 2-by-2 diagonal block,
> WI(i) = sqrt(H(i+1,i)*H(i,i+1)) and WI(i+1) = -WI(i).
> \endverbatim
>
> \param[in] ILOZ
> \verbatim
> ILOZ is INTEGER
> \endverbatim
>
> \param[in] IHIZ
> \verbatim
> IHIZ is INTEGER
> Specify the rows of Z to which transformations must be
> applied if WANTZ is .TRUE..
> 1 <= ILOZ <= ILO; IHI <= IHIZ <= N.
> \endverbatim
>
> \param[in,out] Z
> \verbatim
> Z is DOUBLE PRECISION array, dimension (LDZ,N)
> If WANTZ is .TRUE., on entry Z must contain the current
> matrix Z of transformations accumulated by DHSEQR, and on
> exit Z has been updated; transformations are applied only to
> the submatrix Z(ILOZ:IHIZ,ILO:IHI).
> If WANTZ is .FALSE., Z is not referenced.
> \endverbatim
>
> \param[in] LDZ
> \verbatim
> LDZ is INTEGER
> The leading dimension of the array Z. LDZ >= max(1,N).
> \endverbatim
>
> \param[out] INFO
> \verbatim
> INFO is INTEGER
> = 0: successful exit
> .GT. 0: If INFO = i, DLAHQR failed to compute all the
> eigenvalues ILO to IHI in a total of 30 iterations
> per eigenvalue; elements i+1:ihi of WR and WI
> contain those eigenvalues which have been
> successfully computed.
>
> If INFO .GT. 0 and WANTT is .FALSE., then on exit,
> the remaining unconverged eigenvalues are the
> eigenvalues of the upper Hessenberg matrix rows
> and columns ILO thorugh INFO of the final, output
> value of H.
>
> If INFO .GT. 0 and WANTT is .TRUE., then on exit
> (*) (initial value of H)*U = U*(final value of H)
> where U is an orthognal matrix. The final
> value of H is upper Hessenberg and triangular in
> rows and columns INFO+1 through IHI.
>
> If INFO .GT. 0 and WANTZ is .TRUE., then on exit
> (final value of Z) = (initial value of Z)*U
> where U is the orthogonal matrix in (*)
> (regardless of the value of WANTT.)
> \endverbatim
Authors:
========
> \author Univ. of Tennessee
> \author Univ. of California Berkeley
> \author Univ. of Colorado Denver
> \author NAG Ltd.
> \date September 2012
> \ingroup doubleOTHERauxiliary
> \par Further Details:
=====================
>
> \verbatim
>
> 02-96 Based on modifications by
> David Day, Sandia National Laboratory, USA
>
> 12-04 Further modifications by
> Ralph Byers, University of Kansas, USA
> This is a modified version of DLAHQR from LAPACK version 3.0.
> It is (1) more robust against overflow and underflow and
> (2) adopts the more conservative Ahues & Tisseur stopping
> criterion (LAWN 122, 1997).
> \endverbatim
>
=====================================================================
Subroutine */ int igraphdlahqr_(logical *wantt, logical *wantz, integer *n,
integer *ilo, integer *ihi, doublereal *h__, integer *ldh, doublereal
*wr, doublereal *wi, integer *iloz, integer *ihiz, doublereal *z__,
integer *ldz, integer *info)
{
/* System generated locals */
integer h_dim1, h_offset, z_dim1, z_offset, i__1, i__2, i__3;
doublereal d__1, d__2, d__3, d__4;
/* Builtin functions */
double sqrt(doublereal);
/* Local variables */
integer i__, j, k, l, m;
doublereal s, v[3];
integer i1, i2;
doublereal t1, t2, t3, v2, v3, aa, ab, ba, bb, h11, h12, h21, h22, cs;
integer nh;
doublereal sn;
integer nr;
doublereal tr;
integer nz;
doublereal det, h21s;
integer its;
doublereal ulp, sum, tst, rt1i, rt2i, rt1r, rt2r;
extern /* Subroutine */ int igraphdrot_(integer *, doublereal *, integer *,
doublereal *, integer *, doublereal *, doublereal *), igraphdcopy_(
integer *, doublereal *, integer *, doublereal *, integer *),
igraphdlanv2_(doublereal *, doublereal *, doublereal *, doublereal *,
doublereal *, doublereal *, doublereal *, doublereal *,
doublereal *, doublereal *), igraphdlabad_(doublereal *, doublereal *);
extern doublereal igraphdlamch_(char *);
extern /* Subroutine */ int igraphdlarfg_(integer *, doublereal *, doublereal *,
integer *, doublereal *);
doublereal safmin, safmax, rtdisc, smlnum;
/* -- LAPACK auxiliary routine (version 3.4.2) --
-- LAPACK is a software package provided by Univ. of Tennessee, --
-- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
September 2012
=========================================================
Parameter adjustments */
h_dim1 = *ldh;
h_offset = 1 + h_dim1;
h__ -= h_offset;
--wr;
--wi;
z_dim1 = *ldz;
z_offset = 1 + z_dim1;
z__ -= z_offset;
/* Function Body */
*info = 0;
/* Quick return if possible */
if (*n == 0) {
return 0;
}
if (*ilo == *ihi) {
wr[*ilo] = h__[*ilo + *ilo * h_dim1];
wi[*ilo] = 0.;
return 0;
}
/* ==== clear out the trash ==== */
i__1 = *ihi - 3;
for (j = *ilo; j <= i__1; ++j) {
h__[j + 2 + j * h_dim1] = 0.;
h__[j + 3 + j * h_dim1] = 0.;
/* L10: */
}
if (*ilo <= *ihi - 2) {
h__[*ihi + (*ihi - 2) * h_dim1] = 0.;
}
nh = *ihi - *ilo + 1;
nz = *ihiz - *iloz + 1;
/* Set machine-dependent constants for the stopping criterion. */
safmin = igraphdlamch_("SAFE MINIMUM");
safmax = 1. / safmin;
igraphdlabad_(&safmin, &safmax);
ulp = igraphdlamch_("PRECISION");
smlnum = safmin * ((doublereal) nh / ulp);
/* I1 and I2 are the indices of the first row and last column of H
to which transformations must be applied. If eigenvalues only are
being computed, I1 and I2 are set inside the main loop. */
if (*wantt) {
i1 = 1;
i2 = *n;
}
/* The main loop begins here. I is the loop index and decreases from
IHI to ILO in steps of 1 or 2. Each iteration of the loop works
with the active submatrix in rows and columns L to I.
Eigenvalues I+1 to IHI have already converged. Either L = ILO or
H(L,L-1) is negligible so that the matrix splits. */
i__ = *ihi;
L20:
l = *ilo;
if (i__ < *ilo) {
goto L160;
}
/* Perform QR iterations on rows and columns ILO to I until a
submatrix of order 1 or 2 splits off at the bottom because a
subdiagonal element has become negligible. */
for (its = 0; its <= 30; ++its) {
/* Look for a single small subdiagonal element. */
i__1 = l + 1;
for (k = i__; k >= i__1; --k) {
if ((d__1 = h__[k + (k - 1) * h_dim1], abs(d__1)) <= smlnum) {
goto L40;
}
tst = (d__1 = h__[k - 1 + (k - 1) * h_dim1], abs(d__1)) + (d__2 =
h__[k + k * h_dim1], abs(d__2));
if (tst == 0.) {
if (k - 2 >= *ilo) {
tst += (d__1 = h__[k - 1 + (k - 2) * h_dim1], abs(d__1));
}
if (k + 1 <= *ihi) {
tst += (d__1 = h__[k + 1 + k * h_dim1], abs(d__1));
}
}
/* ==== The following is a conservative small subdiagonal
. deflation criterion due to Ahues & Tisseur (LAWN 122,
. 1997). It has better mathematical foundation and
. improves accuracy in some cases. ==== */
if ((d__1 = h__[k + (k - 1) * h_dim1], abs(d__1)) <= ulp * tst) {
/* Computing MAX */
d__3 = (d__1 = h__[k + (k - 1) * h_dim1], abs(d__1)), d__4 = (
d__2 = h__[k - 1 + k * h_dim1], abs(d__2));
ab = max(d__3,d__4);
/* Computing MIN */
d__3 = (d__1 = h__[k + (k - 1) * h_dim1], abs(d__1)), d__4 = (
d__2 = h__[k - 1 + k * h_dim1], abs(d__2));
ba = min(d__3,d__4);
/* Computing MAX */
d__3 = (d__1 = h__[k + k * h_dim1], abs(d__1)), d__4 = (d__2 =
h__[k - 1 + (k - 1) * h_dim1] - h__[k + k * h_dim1],
abs(d__2));
aa = max(d__3,d__4);
/* Computing MIN */
d__3 = (d__1 = h__[k + k * h_dim1], abs(d__1)), d__4 = (d__2 =
h__[k - 1 + (k - 1) * h_dim1] - h__[k + k * h_dim1],
abs(d__2));
bb = min(d__3,d__4);
s = aa + ab;
/* Computing MAX */
d__1 = smlnum, d__2 = ulp * (bb * (aa / s));
if (ba * (ab / s) <= max(d__1,d__2)) {
goto L40;
}
}
/* L30: */
}
L40:
l = k;
if (l > *ilo) {
/* H(L,L-1) is negligible */
h__[l + (l - 1) * h_dim1] = 0.;
}
/* Exit from loop if a submatrix of order 1 or 2 has split off. */
if (l >= i__ - 1) {
goto L150;
}
/* Now the active submatrix is in rows and columns L to I. If
eigenvalues only are being computed, only the active submatrix
need be transformed. */
if (! (*wantt)) {
i1 = l;
i2 = i__;
}
if (its == 10) {
/* Exceptional shift. */
s = (d__1 = h__[l + 1 + l * h_dim1], abs(d__1)) + (d__2 = h__[l +
2 + (l + 1) * h_dim1], abs(d__2));
h11 = s * .75 + h__[l + l * h_dim1];
h12 = s * -.4375;
h21 = s;
h22 = h11;
} else if (its == 20) {
/* Exceptional shift. */
s = (d__1 = h__[i__ + (i__ - 1) * h_dim1], abs(d__1)) + (d__2 =
h__[i__ - 1 + (i__ - 2) * h_dim1], abs(d__2));
h11 = s * .75 + h__[i__ + i__ * h_dim1];
h12 = s * -.4375;
h21 = s;
h22 = h11;
} else {
/* Prepare to use Francis' double shift
(i.e. 2nd degree generalized Rayleigh quotient) */
h11 = h__[i__ - 1 + (i__ - 1) * h_dim1];
h21 = h__[i__ + (i__ - 1) * h_dim1];
h12 = h__[i__ - 1 + i__ * h_dim1];
h22 = h__[i__ + i__ * h_dim1];
}
s = abs(h11) + abs(h12) + abs(h21) + abs(h22);
if (s == 0.) {
rt1r = 0.;
rt1i = 0.;
rt2r = 0.;
rt2i = 0.;
} else {
h11 /= s;
h21 /= s;
h12 /= s;
h22 /= s;
tr = (h11 + h22) / 2.;
det = (h11 - tr) * (h22 - tr) - h12 * h21;
rtdisc = sqrt((abs(det)));
if (det >= 0.) {
/* ==== complex conjugate shifts ==== */
rt1r = tr * s;
rt2r = rt1r;
rt1i = rtdisc * s;
rt2i = -rt1i;
} else {
/* ==== real shifts (use only one of them) ==== */
rt1r = tr + rtdisc;
rt2r = tr - rtdisc;
if ((d__1 = rt1r - h22, abs(d__1)) <= (d__2 = rt2r - h22, abs(
d__2))) {
rt1r *= s;
rt2r = rt1r;
} else {
rt2r *= s;
rt1r = rt2r;
}
rt1i = 0.;
rt2i = 0.;
}
}
/* Look for two consecutive small subdiagonal elements. */
i__1 = l;
for (m = i__ - 2; m >= i__1; --m) {
/* Determine the effect of starting the double-shift QR
iteration at row M, and see if this would make H(M,M-1)
negligible. (The following uses scaling to avoid
overflows and most underflows.) */
h21s = h__[m + 1 + m * h_dim1];
s = (d__1 = h__[m + m * h_dim1] - rt2r, abs(d__1)) + abs(rt2i) +
abs(h21s);
h21s = h__[m + 1 + m * h_dim1] / s;
v[0] = h21s * h__[m + (m + 1) * h_dim1] + (h__[m + m * h_dim1] -
rt1r) * ((h__[m + m * h_dim1] - rt2r) / s) - rt1i * (rt2i
/ s);
v[1] = h21s * (h__[m + m * h_dim1] + h__[m + 1 + (m + 1) * h_dim1]
- rt1r - rt2r);
v[2] = h21s * h__[m + 2 + (m + 1) * h_dim1];
s = abs(v[0]) + abs(v[1]) + abs(v[2]);
v[0] /= s;
v[1] /= s;
v[2] /= s;
if (m == l) {
goto L60;
}
if ((d__1 = h__[m + (m - 1) * h_dim1], abs(d__1)) * (abs(v[1]) +
abs(v[2])) <= ulp * abs(v[0]) * ((d__2 = h__[m - 1 + (m -
1) * h_dim1], abs(d__2)) + (d__3 = h__[m + m * h_dim1],
abs(d__3)) + (d__4 = h__[m + 1 + (m + 1) * h_dim1], abs(
d__4)))) {
goto L60;
}
/* L50: */
}
L60:
/* Double-shift QR step */
i__1 = i__ - 1;
for (k = m; k <= i__1; ++k) {
/* The first iteration of this loop determines a reflection G
from the vector V and applies it from left and right to H,
thus creating a nonzero bulge below the subdiagonal.
Each subsequent iteration determines a reflection G to
restore the Hessenberg form in the (K-1)th column, and thus
chases the bulge one step toward the bottom of the active
submatrix. NR is the order of G.
Computing MIN */
i__2 = 3, i__3 = i__ - k + 1;
nr = min(i__2,i__3);
if (k > m) {
igraphdcopy_(&nr, &h__[k + (k - 1) * h_dim1], &c__1, v, &c__1);
}
igraphdlarfg_(&nr, v, &v[1], &c__1, &t1);
if (k > m) {
h__[k + (k - 1) * h_dim1] = v[0];
h__[k + 1 + (k - 1) * h_dim1] = 0.;
if (k < i__ - 1) {
h__[k + 2 + (k - 1) * h_dim1] = 0.;
}
} else if (m > l) {
/* ==== Use the following instead of
. H( K, K-1 ) = -H( K, K-1 ) to
. avoid a bug when v(2) and v(3)
. underflow. ==== */
h__[k + (k - 1) * h_dim1] *= 1. - t1;
}
v2 = v[1];
t2 = t1 * v2;
if (nr == 3) {
v3 = v[2];
t3 = t1 * v3;
/* Apply G from the left to transform the rows of the matrix
in columns K to I2. */
i__2 = i2;
for (j = k; j <= i__2; ++j) {
sum = h__[k + j * h_dim1] + v2 * h__[k + 1 + j * h_dim1]
+ v3 * h__[k + 2 + j * h_dim1];
h__[k + j * h_dim1] -= sum * t1;
h__[k + 1 + j * h_dim1] -= sum * t2;
h__[k + 2 + j * h_dim1] -= sum * t3;
/* L70: */
}
/* Apply G from the right to transform the columns of the
matrix in rows I1 to min(K+3,I).
Computing MIN */
i__3 = k + 3;
i__2 = min(i__3,i__);
for (j = i1; j <= i__2; ++j) {
sum = h__[j + k * h_dim1] + v2 * h__[j + (k + 1) * h_dim1]
+ v3 * h__[j + (k + 2) * h_dim1];
h__[j + k * h_dim1] -= sum * t1;
h__[j + (k + 1) * h_dim1] -= sum * t2;
h__[j + (k + 2) * h_dim1] -= sum * t3;
/* L80: */
}
if (*wantz) {
/* Accumulate transformations in the matrix Z */
i__2 = *ihiz;
for (j = *iloz; j <= i__2; ++j) {
sum = z__[j + k * z_dim1] + v2 * z__[j + (k + 1) *
z_dim1] + v3 * z__[j + (k + 2) * z_dim1];
z__[j + k * z_dim1] -= sum * t1;
z__[j + (k + 1) * z_dim1] -= sum * t2;
z__[j + (k + 2) * z_dim1] -= sum * t3;
/* L90: */
}
}
} else if (nr == 2) {
/* Apply G from the left to transform the rows of the matrix
in columns K to I2. */
i__2 = i2;
for (j = k; j <= i__2; ++j) {
sum = h__[k + j * h_dim1] + v2 * h__[k + 1 + j * h_dim1];
h__[k + j * h_dim1] -= sum * t1;
h__[k + 1 + j * h_dim1] -= sum * t2;
/* L100: */
}
/* Apply G from the right to transform the columns of the
matrix in rows I1 to min(K+3,I). */
i__2 = i__;
for (j = i1; j <= i__2; ++j) {
sum = h__[j + k * h_dim1] + v2 * h__[j + (k + 1) * h_dim1]
;
h__[j + k * h_dim1] -= sum * t1;
h__[j + (k + 1) * h_dim1] -= sum * t2;
/* L110: */
}
if (*wantz) {
/* Accumulate transformations in the matrix Z */
i__2 = *ihiz;
for (j = *iloz; j <= i__2; ++j) {
sum = z__[j + k * z_dim1] + v2 * z__[j + (k + 1) *
z_dim1];
z__[j + k * z_dim1] -= sum * t1;
z__[j + (k + 1) * z_dim1] -= sum * t2;
/* L120: */
}
}
}
/* L130: */
}
/* L140: */
}
/* Failure to converge in remaining number of iterations */
*info = i__;
return 0;
L150:
if (l == i__) {
/* H(I,I-1) is negligible: one eigenvalue has converged. */
wr[i__] = h__[i__ + i__ * h_dim1];
wi[i__] = 0.;
} else if (l == i__ - 1) {
/* H(I-1,I-2) is negligible: a pair of eigenvalues have converged.
Transform the 2-by-2 submatrix to standard Schur form,
and compute and store the eigenvalues. */
igraphdlanv2_(&h__[i__ - 1 + (i__ - 1) * h_dim1], &h__[i__ - 1 + i__ *
h_dim1], &h__[i__ + (i__ - 1) * h_dim1], &h__[i__ + i__ *
h_dim1], &wr[i__ - 1], &wi[i__ - 1], &wr[i__], &wi[i__], &cs,
&sn);
if (*wantt) {
/* Apply the transformation to the rest of H. */
if (i2 > i__) {
i__1 = i2 - i__;
igraphdrot_(&i__1, &h__[i__ - 1 + (i__ + 1) * h_dim1], ldh, &h__[
i__ + (i__ + 1) * h_dim1], ldh, &cs, &sn);
}
i__1 = i__ - i1 - 1;
igraphdrot_(&i__1, &h__[i1 + (i__ - 1) * h_dim1], &c__1, &h__[i1 + i__ *
h_dim1], &c__1, &cs, &sn);
}
if (*wantz) {
/* Apply the transformation to Z. */
igraphdrot_(&nz, &z__[*iloz + (i__ - 1) * z_dim1], &c__1, &z__[*iloz +
i__ * z_dim1], &c__1, &cs, &sn);
}
}
/* return to start of the main loop with new value of I. */
i__ = l - 1;
goto L20;
L160:
return 0;
/* End of DLAHQR */
} /* igraphdlahqr_ */